Reputation: 63
Someone thought it would be a good idea to store Objects in the database in a blob column using Java's default serialization methods. The structure of these objects is controlled by another group and they changed a field type from BigDecimal to a Long, but the data in our database remains the same. Now we can't read the objects back because it causes ClassCastExceptions.
I tried to override it by writing my own readObject method, but that throws a StreamCorruptedException because what was written by the default writeObject method.
How do I make my readObject call behave like Java's default one? Is there a certain number of bytes I can skip to get to my data?
Upvotes: 6
Views: 429
Reputation: 38300
Implement the readObject and readObjectNoData methods in you class.
Read the appropriate type using ObjectInoutStream.readObject
and convert it to the new type
See the Serializable interface API for details.
You can only fix this easily if you control the source of the class that was serialized into the blob. If you do not control this class, then you have only a few limited and difficult options:
Next you have to do one of these
Upvotes: 0
Reputation: 310893
If you want to read what's already in your database your only option is to get them to change the class back again, and to institute some awareness that you're relying on the class definition as it was when the class was serialized. Merely implementing your own readObject() call can't fix this, and if the class is under someone else's control you can't do that anyway.
If you're prepared to throw away the existing data you have many other choices starting with custom Serialization, writeReplace()/readResolve(), Externalizable, ... or a different mechanism such as XML.
But if you're going to have third parties changing things whenever they feel like it you're always going to have problems of one kind or another.
BigDecimal to Long sounds like a retrograde step anyway.
Upvotes: 1
Reputation: 49744
Externalizable
allows you to take full control of serialization/deserialization. But it means you're responsible for writing and reading every field,
When it gets difficult though is when something was written out using the default serialization and you want to read it via Externalizable
. (Or rather, it's impossible. If you try to read an object serialized with the default method using Externalizable
, it'll just throw an exception.)
If you've got absolutely no control on the output, your only option is to keep two versions of the class: use the default deserialization of the old version, then convert to the new. The upside of this solution is that it keeps the "dirty" code in one place, separate from your nice and clean objects.
Again, unless you want to do things really complicated, your best option is to keep the old class as the "transport" bean and rename the class your code really uses to something else.
Upvotes: 2