deven
deven

Reputation: 815

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

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)

Upvotes: 25

Views: 80607

Answers (2)

BalusC
BalusC

Reputation: 1109522

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, UploadedFile, 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 a concrete example in this answer: How to make persistent Cookies with a DefaultHttpClient in Android?

The alternative is to replace the unserializable type by a serialiable type. E.g. using byte[] content/String filename instead of InputStream/UploadedFile. Or just write it to a (temp) file immediately within the method wherein you're retrieving it instead of assigning it as a bean property. See also:

See also:


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:

Upvotes: 63

Thilo
Thilo

Reputation: 262814

You need to make bean.ProjectAreaBean serializable.

Upvotes: 3

Related Questions