Thursday, June 28, 2007

Use of serialVersionUID

Whenever i implement a seializable interface to my class it gives me a warning to add a SerialiazableUID. I just add it with default value to make my class looks no warning message in eclibse IDE. I thought that this id will be useful in deserializing. So i tried an example to find out the real purpose for this id.

Consider this basic Employee view Class with one private varialble name..

package Serializable;
import java.io.Serializable;
public class EmployeeView implements Serializable {
private String name;
public String getName() {

return name;
}
public void setName( String name ) {

this.name = name;
}
}


Then i write a class to serialize this class

package Serializable;
import java.io.FileInputStream;

import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerialiaztionTester {

private static String fileName = "SerTest.txt";

public void writer() {
ObjectOutputStream out = null;
FileOutputStream fos = null;
EmployeeView e = new EmployeeView();
e.setName( "bala" + System.currentTimeMillis() );
System.out.println( "In Writer Employee Name is " + e.getName() );
try{
fos = new FileOutputStream( fileName );
out = new ObjectOutputStream( fos );
out.writeObject( e );
out.close();
}
catch ( Exception ex ){
ex.printStackTrace();
}
}

public void reader() {
ObjectInputStream in = null;
FileInputStream fis = null;
try{
fis = new FileInputStream( fileName );
in = new ObjectInputStream( fis );
EmployeeView e = ( EmployeeView ) in.readObject();
in.close();
System.out.println( "In reader employee name is "+e.getName() );
}
catch ( Exception ex ){
ex.printStackTrace();
}
}

public static void main( String a[] ) {
SerialiaztionTester test = new SerialiaztionTester();
test.writer();
test.reader();
}

}

In writer method just serialize my EmployeeView class to a SerTest.txt file. And in reader method just deserialize my EmployeeView class. Hope you guyz know what is serialization and deserialization. Just for reminder,

Object serialization is the process of saving objects state as a sequence of byte for rebuilding the objects original state at a future time. Rebuilding the object from this sequence of bytes is called deserialization.

when you run the above code you got the following output

In Writer Employee Name is bala1183102973513
In reader employee name is bala1183102973513


Now i am just writing the object,

public static void main( String a[] ) {
SerialiaztionTester test = new SerialiaztionTester();
test.writer();
// test.reader();
}


output is
In Writer Employee Name is bala1183103114211


Adding a new variable age and setter , getter methods in employee class

package Serializable;
import java.io.Serializable;
public class EmployeeView implements Serializable {
private String name;

private int age;
public String getName() {

return name;
}
public void setName( String name ) {

this.name = name;
}
public int getAge() {

return age;
}
public void setAge( int age ) {

this.age = age;
}
}


then i call the reader method from the main class without writing. keep in mind that when i serialized my class which consists of only name variable. now it has name as well as age variable

public static void main( String a[] ) {
SerialiaztionTester test = new SerialiaztionTester();
// test.writer();
test.reader();
}

My output for this

java.io.InvalidClassException: Serializable.EmployeeView; local class incompatible: stream classdesc serialVersionUID = 6513632082659324604, local class serialVersionUID = -6641931785738549045
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:459)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1521)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1435)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1626)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
at Serializable.SerialiaztionTester.reader(SerialiaztionTester.java:35)
at Serializable.SerialiaztionTester.main(SerialiaztionTester.java:47)


From the error itself you can easily have an idea why this error is occured

java.io.InvalidClassException: Serializable.EmployeeView; local class incompatible: stream classdesc serialVersionUID = 6513632082659324604, local class serialVersionUID = -6641931785738549045

Whenever you implement the serialiable it will be assigned a serialVersionUID by default. This unique id should be match when you are deserialzing the object.

To avoid this you can assigned a SerialVersionUID like this

package Serializable;
import java.io.Serializable;
public class EmployeeView implements Serializable {

private static final long serialVersionUID = 1L;

private String name;
private int age;
public String getName() {

return name;
}
public void setName( String name ) {

this.name = name;
}
public int getAge() {

return age;
}
public void setAge( int age ) {

this.age = age;
}
}


Now whenever you change or add a variable it wont throw any exception until unless you remove the implementation Serializable.

Want to know more about Serialization check out this article