When I use RMI, are the only objects passed over the network ( and hence need to have a serialID specified ) the ones that you bind to your RMI registry, or are other classes - like exceptions throw in your binded objects also serialized and passed around?
so say I have a Car class, and I bind it to my registry so others can perform remote method invocation on it. My car class contains tires ( of class Tire ) and it also could possibly throw some custom exceptions ( like say, OutOfGasException ). Should Tire and OutOfGasException have a serialID? Are these objects serialized?
Every object that implements Serializable should have a serialVersionUID. If you don't provide one, a default one will be generated. Have a look at the javadoc of the Serializable interface, it contains a lot of valuable information about the purpose of this property. In every class which implements Serializable (and has the capability to be transported over a network) I explicitly declared a serialVersionUID with a self chosen value (just 1 value for all classes).
"In every class which implements Serializable (and has the capability to be transported over a network) I explicitly declared a serialVersionUID with a self chosen value (just 1 value for all classes)"
Yes exactly what I was thinking, yet I am still confused on one aspect ( how to tell which object get transported over the network ). Going by the example I gave, would I only give an ID for the class that I bind to my RMI registry, or would any class that has any type of relationship with it ( in my case Tire and OutOfGasException ).
I use the assertion that ignores compiler warnings for serializeable in my GUI classes, since these shouldn't be transported over the network ( and quit frankly don't understand why all SWING classes implement serializable ).
In your project, what critera did you go by to decide on weither to give an explicit ID or not? I'm assuming on all your GUI code you used the assertion to ignore the warnings. Is there a way to tell exactly which items will travel over the network?
The Java Serialization Specification clearly describes the SUIDs and the reasons for their existence. The SUID is not related to RMI, but to serialization, and it is inherently related to the concept of type evolution.
Imagine that you have a database of serialized objects in version 1.0 of your application, already owned by a bunch of your clients. Now you are working on version 2.0 of the application. Whatever modifications that you make to the classes already serialized in the client's database may prove incompatible. What is a compatible change and what is not?
What if you add a new field to the class? What if you remove a field? What if you change a field data type? or move class to another package or simply rename it?
Whatever change you do to a class will most likely prove incompatible if you do not define an explicit serial version unique identifier. This SUID field is the only way you have to tell the Java Virtual Machine that the changes that you do are compatible with previous versions of a class. This does not mean that you code will prove to be compatible, this only means that you are telling the JVM that you have taken care of the code to ensure it is compatible.
For instance, add a field to class will make a previous version of class impossible to deserialize. If you defined the SUID, however, if you keep it as it was, the JVM will deserialize the class for you, regardless of change, but the new filed will be initialized to its default value (remember that deserialization does not invoke constructors or instance initializers). This means that if your new filed is an object and if you use this field without taking care that it could be null you could could fail by a NullPointerException.
In the distributed environment, since objects are serialized over the network, you also have to take into account the strategy for distributing the classes. If you change a serializable class on the server and you do not change the class for all the clients, the object being marshalled over the network may prove impossible to deserialize in the client.
Bottom line, you must be aware of type evolution and be prepare to deal with it every time you deal with serializable classes.
Regarding Swing components being serializable, I do not know the reasons, I guess you can consider among other things the possibility to serialize components to disk and get them back later with the properties as they were, and the possibilities of having distributed GUIs. But I am not Swing guy, so I cannot be certain of how this feature is being used in real world applications.
Kenny Johnson wrote:In your project, what critera did you go by to decide on weither to give an explicit ID or not? I'm assuming on all your GUI code you used the assertion to ignore the warnings. Is there a way to tell exactly which items will travel over the network?
Wrong assumption: every class which extends a class which implements Serializable has an serialVersionUID (gui code, business exceptions, database exceptions,...). Furthermore every class which should be capable to move between client and server, implements Serializable and has a serialVersionUID (data transfer objects,...).
Joined: Jan 01, 2007
Thank you for the detailed reply, and although the information is good and may help a new comer I am already aware of the reason for IDs and such. I am simply wondering which classes in my application I should explicitly define an ID for as to adhere to good coding standards.
In my response to Roel, I made the assumption that any GUI classes ( JFrames, JPanels, Buttons, etc etc ) will have the assertion @SuppressWarnings("serial") which 1.) remove annoying compiler warnings, and 2.) indicate to any other developers who might read your code that your most probably NOT ever serializing these classes even though they implement Serializable.
In my SCJD app, I want to provide an explicit serialID value on all the classes which might get serialized due to using RMI as my network technique. I know that my GUI classes are never being shared, so I confidently add @SuppressWarnings("serial") to them as an indication that they will never be serialized ( even though they implement serializable ).