Reputation: 328594
Imagine I have a class Foo
which has had the serialVersionUID
s 1, 3 and 17 in the past and I need to be able to read all three versions into Foo
instances. How do I do that?
I specifically need to know which version was saved in the byte stream, so I can do some data migration. How do I get access to the serialVersionUID
in readObject()
? Or is that already too late?
Upvotes: 2
Views: 316
Reputation: 16999
You can get the former serialVersionUID
by catching the error during deserialization:
try {
// deserialize here...
} catch (final java.io.InvalidClassException e) {
System.out.println(e.getMessage());
// The message string contains the former uid.
// Message: local class incompatible: stream classdesc serialVersionUID = OLD_UID_HERE, local class serialVersionUID = NEW_UID_HERE
}
Upvotes: 1
Reputation: 13890
It is not easy, but possible. For each historical version of class you need to create separate classloader which will load old versions of data-model classes. Then you need to try reading your file with each classloader until some will fit. I believe ObjectInputStream
uses current classloader from thread context. Fell free to ask me if you need more details.
Later addition: it seems that it is not so easy to specify which classloader will be used by ObjectInputStream
. Additional investigation is probably needed here.
Another later addition: Probably you can override resolveClass(ObjectStreamClass)
method in ObjectInputStream
to make is use proper class loader.
Upvotes: 2
Reputation: 15758
Use different classloaders to deserialize the different versions of the object. After that you have to manually initialize the internal state of the common (probably the latest) instance based on the prevoius versions (you must write a converter for that).
Be sure that your classloader path is totally distinct. If a super classloader can load a class, it will load. So, all classloaders should be totally separate of each other (neither should be the super of the others).
Upvotes: 2