java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException

deven picture deven · Feb 19, 2010 · Viewed 66.3k times · Source

What causes this kind of error in Tomcat?

SEVERE: Exception loading sessions from persistent storage
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException:
   bean.ProjectAreaBean
 at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1333)
 at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
 at java.util.ArrayList.readObject(ArrayList.java:593)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(
    DelegatingMethodAccessorImpl.java:25)

Answer

BalusC picture BalusC · Jul 27, 2012

Just implement Serializable

If you're getting a NotSerializableException like follows,

java.io.NotSerializableException: bean.ProjectAreaBean

then it simply means that the class as identified by the fully qualified name in the exception message (which is bean.ProjectAreaBean in your case) does not implement the Serializable interface while it is been expected by the code behind. Fixing it is relatively simple, just let the class implement the Serializable interface.

package bean;

import java.io.Serializable;

public class ProjectAreaBean implements Serializable {
    private static final long serialVersionUID = 1L;

    // ...
}

The serialVersionUID field is not necessary, but strongly recommended as this maintains the binary compatibility between different versions of the class and the serialized representations of its instances. So when you add later a new serializable field to the class, then you'd need to change the serialVersionUID field (usually just incrementing it by 1 is sufficient) to prevent problems during deserialization of an instance of an older version of the class. IDEs like Eclipse also offer an option to (re)generate the serialVersionUID value which is basically a hash computed based on all fields.

See also:


Mark unserializable fields transient

If your Serializable class contains in turn a field/property referencing an instance of another class which can absolutely not be made Serializable (usually, these represent resources, such as InputStream, Connection, etc), then you'd need to mark it transient. This way it will be skipped during serialization of the class.

private transient SomeObject thisWillNotBeSerialized;

You need to understand that after deserialization this field would always become null. Note that the class' constructor and initialization blocks are not invoked during deserialization. If you'd like to have finer grained control over serialization and deserialization, then override the readObject() and writeObject() methods. You can find concrete examples in below links:


Why serialization?

As to the why you need to worry about serialization, this is because most Java servlet containers like Tomcat require classes to implement Serializable whenever instances of those classes are been stored as an attribute of the HttpSession. That is because the HttpSession may need to be saved on the local disk file system or even transferred over network when the servlet container needs to shutdown/restart or is being placed in a cluster of servers wherein the session has to be synchronized.

In order to be able to save Java objects on the local disk file system or transfer them over network, they have to be converted to a byte stream first (basically: a byte[] or an InputStream) and that is only possible if the class behind the object implements Serializable. The Serializable interface itself doesn't really do anything, it's merely a marker interface. The code behind merely does an instanceof Serializable check on the session attribute to act accordingly.

See also: