Parent/Child Serialization local class incompatible Exception - java

I'm getting a serialization compatibility error from the below two classes. Only the parent class, CommericalCustomer implements serialization. What is the proper way to use the Serializable Interface when having a parent/child relation as I have below?
public class CachedCommercialCustomers extends CommercialCustomer {
}
public class CommercialCustomer implements Serializable {
private static final long serialVersionUID = 1L;
}
Exception:
[#|2013-01-02T05:01:02.553-0800|SEVERE|glassfish3.1.2|com.hazelcast.nio.AbstractSerializer|_ThreadID=10;_ThreadName=Thread-2;|spot.api.model.vo.backoffice.CachedCommercialCustomers; local class incompatible: stream classdesc serialVersionUID = -2672531984245897526, local class serialVersionUID = -743225273062282831
java.io.InvalidClassException: com.sample.CachedCommercialCustomers; local class incompatible: stream classdesc serialVersionUID = -2672531984245897526, local class serialVersionUID = -743225273062282831
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:579)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1600)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1513)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1749)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1346)
at java.io.ObjectInputStream.readUnshared(ObjectInputStream.java:458)
at com.hazelcast.nio.DefaultSerializer$ObjectSerializer.readNormal(DefaultSerializer.java:383)
at com.hazelcast.nio.DefaultSerializer$ObjectSerializer.read(DefaultSerializer.java:353)
at com.hazelcast.nio.DefaultSerializer.read(DefaultSerializer.java:134)
at com.hazelcast.nio.CustomSerializerAdapter.read(CustomSerializerAdapter.java:33)
at com.hazelcast.nio.AbstractSerializer.toObject(AbstractSerializer.java:116)
at com.hazelcast.nio.AbstractSerializer.toObject(AbstractSerializer.java:146)
at com.hazelcast.nio.Serializer.readObject(Serializer.java:72)
at com.hazelcast.impl.ThreadContext.toObject(ThreadContext.java:103)
at com.hazelcast.nio.IOUtil.toObject(IOUtil.java:149)
at com.hazelcast.impl.BaseManager$RequestBasedCall.getResultAsObject(BaseManager.java:384)
at com.hazelcast.impl.BaseManager$ResponseQueueCall.getResultAsObject(BaseManager.java:455)
at com.hazelcast.impl.BaseManager$RequestBasedCall.getResultAsObject(BaseManager.java:368)
at com.hazelcast.impl.BaseManager$ResponseQueueCall.getResultAsObject(BaseManager.java:455)

The problem here is that you don't specify a serialVersionId for your sub class - so java will generate one for you instead. A simple recompilation might change this value if you change the java source file. See the spec.
The fact that the I'd changes when the code changes is a good thing, but in some cases it will cause you some grief :)
See here for more information and how to "fix" the problem if necessary.

Related

Serial version uid in abstract exception class

I have a base custom exception class BaseException
public class BaseException extends RuntimeException {
}
and several custom exceptions that extends BaseException
public class CustomException extends BaseException {
private static final long serialVersionUID = 3655655808021733968L;
}
I got a warning about serial version uid being not declared in the BaseException class. Is it needed in an abstract class? Is it a good practice? Is any way to get rid of the warning?
Yes, you need to define the serialVersionUID in an abstract class. Serialization serializes instance state, which usually means the non-static fields; any inherited state needs to be serialized along with the rest of the object’s state.
The fact that you don’t have fields in BaseException doesn’t mean you should skip the serialVersionUID.
Note that, contrary to popular belief, a serialVersionUID does not need to be based on a hash of the class’s name or structure. Only the default computed serial version UID does this, when the class does not define a serialVersionUID field explicitly. Normally, you can declare it as a simple number:
private static final long serialVersionUID = 1;

reading binary data after refactoring of classes

I have old binary data serialized and stored in a db with an old class 'mypackage.Myclass'
I would like to refactor this class to 'mypackage.topic.Myclass' and still able to read the binary data back (deserialization)
I get an error Classnotfound when :
ois = new ObjectInputStream(bos);
o = ois.readObject();
mypackage.topic.Myclass myclass = (mypackage.topic.Myclass) o;
Is there a way to force readObject() to match another class then the original serialized class ? Or any otherhint doing this ?
You can solve this by creating a data wrapper class called mypackage.Myclass. When deserializing the binary data, you can first try to deserialize it as mypackage.topic.Myclass. When this fails, deserialize it as mypackage.Myclass and convert it afterwards to the class mypackage.topic.Myclass.
You can also set the serialVersionUID of the mypackage.topic.Myclass to the serialVersionUID of the mypackage.Myclass. If you don't know the serialVersionUID of the class mypackage.Myclass, or if you doesn't have set the serialVersionUID, you can generate the serialVersionUID, which is probably used/automatically created by the JVM using this command: serialver -classpath whatever com.foo.bar.MyClass (See: Java - Modifying serialVersionUID of binary serialized object)
When the classes have the same serialVersionUID, there will be no error when you deserialize the class.

serialVersionUID Exception

I'm currently writing a project where I have a serializable class ClientRepository. The class don't specifies any serialVersionUID.
When I try to run my program, I got following Exception:
Exception in thread "main" java.io.InvalidClassException: ClientRepository; local class incompatible: stream classdesc serialVersionUID = -477189107700903771, local class serialVersionUID = -3576242897222506440
So I added a default serialVersionUID (1L), but now I get
Exception in thread "main" java.io.InvalidClassException: ClientRepository; local class incompatible: stream classdesc serialVersionUID = -477189107700903771, local class serialVersionUID = 1
How can I change the "stream classdesc serialVersionUID" to 1L, so it won't conflict?
Thanks!
Don't try to change the data - instead, if you're certain that your class is still compatible with the old version (and if only one version has data out in the wild), change your declared serialVersionUID to -477189107700903771L to match the value in the data. The value is arbitrary - it just has to match what's in the data.
Of course, if your class has changed in an incompatible way, you'll need to write some custom serialization code.
Personally I try to avoid native binary serialization like this for precisely these brittleness reasons. You might wish to look at alternatives such as Protocol Buffers.
The problem is probably the objects that were serialized into the repository before adding serialVersionUID = 1L - they still have generated serialVersionUID that is different from 1L. You should purge the repository.

How to get rid of InvalidClassException SerialVersionUID?

I had saved one java object in the Database and then after few days I changed my jre version.
Now when i tried to read that same object I am getting following exception:
Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
serialVersionUID = -6377573678240024862, local class serialVersionUID = -8204757486033751616
How can I get rid of this,how can I get the saved object?
please help me.
If you can affect source code of this class and JRE was only thing that changed, most likely you can still deserialize object that was serialized by older JVM. Just define following field in class to be deserialized:
private static final long serialVersionUID = -6377573678240024862L;

SerialVersionUID with "private static final long" still gets InvalidClassException

I have compiled and jarred the various projects in my Java application, generating serialVersionUIDs automatically through Eclipse for all my classes derived from Serializable.
I read the answers to this question, and verified that serialVersionUids are all private static final long.
Nevertheless, I get an error like this when I try to run:
java.io.InvalidClassException: com.acme.product.Widget; local class
incompatible: stream classdesc serialVersionUID = 5226096973188250357, local
class serialVersionUID = -5432967318654384362
What am I missing?
You probably have a classpath issue, where your program is resolving an older incompatible version of the class which has a different value for serialVersionUID.
Or the serialized object that is being loaded, was serialized with an oder version of the class which is now unavailable.
If the class has changed since you serialized it, the change may be incompatible. Serialization can't deserialize it, even with the included serialVersionUID.
If you have the class as it was when serialized (e.g. from SCM), then try reverting back to that, regenerate the serialVersionUID and rerun.
If you have made incompatible changes, then you will have to implement readObject() /writeObject() to handle the serialization details yourself.
stream classdesc serialVersionUID =
5226096973188250357
What am I missing?
What you are missing is private static final long serialVersionUID = 5226096973188250357L;
However if the changed class is no longer serialization-compatible (see the Object Serialization Specification) you may now get more obscure errors.

Categories

Resources