1

Assume the following structure:

class Foo implements Serializable {
    private static final long serialVersionUID = 7...L;
    private final String someField; ...
}

class BarWithErrorInformation extends Foo {
    private static final long serialVersionUID = 1L
    private final Exception someCause; ...
}

( the serialVersionUIDs represent the values that we actually have in our product right now )

Our (probably stupid) design does "remote" calls from some system A to another system B. The result on B is a serialized BarWithErrorInformation object; that goes back to A.

That alone works fine, but unfortunately, A and B can be on different code levels. This means that we are now receiving BarWithErrorInformation objects containing an exception object of a class that does not exist on A. In that case, deserialization fails (throwing a ClassNotFoundException on A).

I thought I could simply add a custom readObject() method to BarWithErrorInformation:

private void readObject(ObjectInputStream o) throws IOException, ClassNotFoundException {
    try {
        o.defaultReadObject();
    } catch (ClassNotFoundException cnfe) {
      this.someCause = new SpecialException(cnfe);
    } ...

But if I read the answers from here correctly, the above code would result in only someCause having a meaningful value.

Is there a way to deserialize all inherited fields with the correct information, while at the same time handling the problem with the unknown exception class?

Update: I agree with the comments that were made; our approach is wrong; and we need to change our mechanism to transport error information. Nonetheless I keep this question open for answers; as the pure technical question (can it be done, and if so, how) still seems worth following on its own!

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • how do you use this exception in system A? maybe its easier to send just a stacktrace? – AdamSkywalker Mar 08 '16 at 19:39
  • Updated the question; we are not interested in stack traces. – GhostCat Mar 08 '16 at 19:42
  • I imagine you'd have to create your own (possibly anonymous) subclass of ObjectInputStream and override [readClassDescriptor](http://docs.oracle.com/javase/8/docs/api/java/io/ObjectInputStream.html#readClassDescriptor--). – VGR Mar 08 '16 at 20:04
  • 1
    So it is not considered a bug to have the code on System A out of sync with the code on System B? Because you mention that you would like to provide the end user with helpful information when these errors occur, but _shouldn't code version problems of this kind be completely resolved before moving the code into a production environment_? I'm not trying to preach, but this kind of problem is a **true bug**, so going through the trouble of providing information to users shouldn't be necessary or something to be anticipated, because they should be resolved before promotion to production, right? – Sean Mickey Mar 08 '16 at 20:16
  • There is a reason why I tend to consider this a stupid, buggy design by now. To our customers, A and B are two (somehow) independent products. Thus we allow them to upgrade them independently. Unfortunately the group making that design ... did overlook that fact. And no, we can't change that policy. – GhostCat Mar 08 '16 at 20:18
  • @Jägermeister: Do you have access to the super-class(es) source code (`Foo` in your example code), have the ability to change the super-class serialized form, and _this part is important_, have the super-class(es) been previously released using the default Java serialized form? – Sean Mickey Mar 08 '16 at 23:12
  • @SeanMickey Updated the question to show the serialVersionUIDs that we currently have in place. – GhostCat Mar 09 '16 at 09:33

0 Answers0