What causes a NotSerializableException in Tomcat 7? [duplicate]
Asked Answered
O

3

21

My DAO implementation is throwing a not serializable exception on server start up with Tomcat7. Any idea what causes this? None of my other DAOs are doing this.

Here's the class:

package com.project.dao;

import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.project.model.User;

public class UserDAOImpl implements UserDAO {
    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    @Override
    public void saveUser(User user) {
        hibernateTemplate.saveOrUpdate(user);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<User> listUser() {
        return hibernateTemplate.find("from User");
    }

    @Override
    @SuppressWarnings("unchecked")
    public User getUserByID(long userID) {
        List<User> users= hibernateTemplate.find("from User where id = '" + userID + "'");
        return users.size() > 0 ? users.get(0) : null;
    }
}

Here's my config:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <bean id="myDataSource" 
    class="org.apache.tomcat.dbcp.dbcp.BasicDataSource">
      <property name="driverClassName">
        <value>com.mysql.jdbc.Driver</value>
      </property>
      <property name="url">
        <value>jdbc:mysql://localhost/context</value>
      </property>
      <property name="username">
        <value>someUser</value>
      </property>
      <property name="password">
        <value>somePassword</value>
      </property>
      <!-- Disable the second-level cache  -->
        <!-- Echo all executed SQL to stdout -->
    </bean>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" /> 
        <property name="annotatedClasses">
            <list>
                <value>com.project.model.User</value>
            </list>
        </property> 
        <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
        </property>
    </bean>
    <bean id="myUserDAO" class="com.project.dao.UserDAOImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean> 
</beans>

Here's my stack:

SEVERE: IOException while loading persisted sessions: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.news.dao.UserDAOImpl
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.project.dao.UserDAOImpl

at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1600)
at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1073)
at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:284)
at org.apache.catalina.session.StandardManager.load(StandardManager.java:204)
at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:470)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.startup.Catalina.start(Catalina.java:620)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431)

Caused by: java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1676)
at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1090)
at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:411)
at org.apache.catalina.session.StandardManager.unload(StandardManager.java:353)
at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:497)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5464)
at java.lang.Thread.run(Thread.java:662)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5481)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:502)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:748)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.startup.Catalina.stop(Catalina.java:693)
at org.apache.catalina.startup.Catalina.start(Catalina.java:654)
... 6 more
Jul 31, 2011 9:27:21 PM org.apache.catalina.session.StandardManager startInternal

SEVERE: Exception loading sessions from persistent storage
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1332)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1600)
at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1073)
at org.apache.catalina.session.StandardManager.doLoad(StandardManager.java:284)
at org.apache.catalina.session.StandardManager.load(StandardManager.java:204)
at org.apache.catalina.session.StandardManager.startInternal(StandardManager.java:470)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5241)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.startup.Catalina.start(Catalina.java:620)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431)

Caused by: java.io.NotSerializableException: com.project.dao.UserDAOImpl
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1164)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1518)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1483)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1400)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1158)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:330)
at org.apache.catalina.session.StandardSession.writeObject(StandardSession.java:1676)
at org.apache.catalina.session.StandardSession.writeObjectData(StandardSession.java:1090)
at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:411)
at org.apache.catalina.session.StandardManager.unload(StandardManager.java:353)
at org.apache.catalina.session.StandardManager.stopInternal(StandardManager.java:497)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardContext$4.run(StandardContext.java:5464)
at java.lang.Thread.run(Thread.java:662)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5481)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.ContainerBase.stopInternal(ContainerBase.java:1072)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardService.stopInternal(StandardService.java:502)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.core.StandardServer.stopInternal(StandardServer.java:748)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:225)
at org.apache.catalina.startup.Catalina.stop(Catalina.java:693)
at org.apache.catalina.startup.Catalina.start(Catalina.java:654)
... 6 more
Ophelia answered 1/8, 2011 at 2:49 Comment(3)
Are you setting this object somewhere in your session or as a variable of an object that is stored at the session?Submergible
It is a variable in an object that is stored in session.Ophelia
Remove it then, as this object has access to the Hibernate session it's never going to be able to serialize itself.Submergible
A
21

UserDaoImpl must implement the java.io.Serializable interface if it is to be serialized (your stack trace indicates an attempt is made to write an instance of the class to an object stream).

The instance to be serialized, along with all objects in the object graph of that instance, must all be serializable.

From the javadocs for Serializable,

Serializability of a class is enabled by the class implementing the java.io.Serializable interface...When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.

Note that there are exceptions to these rules. I recommend that you read the Java Object Serialization Specification for a full understanding of when object serialization takes place and it what it takes to avoid a NotSerializableException.

Arria answered 1/8, 2011 at 3:0 Comment(3)
This isn't particular useful information. The OP needs to know why this is happening during startup, rather the fine detail about serialization mechanics.Honeycomb
This might be the proximal cause, but not the root cause. How do you propose to make a HibernateTemplate serializable?Pecker
It isn't a good idea to serialize spring-managed beans.Divisor
P
32

It is happening because somewhere in your code, you are storing a UserDAO in the session (or you are storing an object that has a reference to a UserDAO). Tomcat tries to serialize the full object graph of all active sessions when you shut it down, and then it tries to restore them when you start it back up. The crux of this is that Tomcat uses "normal" java object serialization, which requires all objects to be Serializable.

How to remedy:

  1. Don't store non-serializable objects in the users session (generally a good practice).
  2. Make your UserDAO serializable. Probably involves implementing the Serializable interface and marking your hibernateTemplate as transient as i don't think that HibernateTemplate is, in itself, serializable. You may have to add some code that re-initialize the hibernateTemplate on deserialization if you really want it to work.
  3. Don't have Tomcat serializing sessions (add <Manager pathname="" /> to the context.xml, either in your own app or in the global tomcat context.xml in the conf/ directory, inside the <Context> element. This might be the best course of action for you, unless you really need sessions to be persisted across restarts.
Pecker answered 1/8, 2011 at 8:25 Comment(1)
I need to say this. Your answer is great. Helped me a lot, thanks.Certainly
A
21

UserDaoImpl must implement the java.io.Serializable interface if it is to be serialized (your stack trace indicates an attempt is made to write an instance of the class to an object stream).

The instance to be serialized, along with all objects in the object graph of that instance, must all be serializable.

From the javadocs for Serializable,

Serializability of a class is enabled by the class implementing the java.io.Serializable interface...When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.

Note that there are exceptions to these rules. I recommend that you read the Java Object Serialization Specification for a full understanding of when object serialization takes place and it what it takes to avoid a NotSerializableException.

Arria answered 1/8, 2011 at 3:0 Comment(3)
This isn't particular useful information. The OP needs to know why this is happening during startup, rather the fine detail about serialization mechanics.Honeycomb
This might be the proximal cause, but not the root cause. How do you propose to make a HibernateTemplate serializable?Pecker
It isn't a good idea to serialize spring-managed beans.Divisor
P
13

The other answers here explain serialization well. Since this is the first result in Google I wanted to add information that really helped me resolve the issue.

The exception message itself does not indicate which field in which class caused this issue. If you can't make a class serializable and need to add the transient keyword so Java does not try to serialize a field it can be tricky to figure out which field is causing the issue.

If you add the parameter -Dsun.io.serialization.extendedDebugInfo=true to Java/Tomcat when starting it the exception will be much more useful. Here is an example of what the exception message will look like:

java.io.NotSerializableException: za.co.abc.presentation.control.Three
 - field (class "za.co.abc.presentation.control.Two", name: "three", type: "class za.co.abc.presentation.control.Three")
 - object (class "za.co.abc.presentation.control.Two", za.co.abc.presentation.control.Two@fbbb20)
 - field (class "za.co.abc.presentation.control.One", name: "two", type: "class za.co.abc.presentation.control.Two")
 - object (class "za.co.abc.presentation.control.One", za.co.abc.presentation.control.One@17ee6c9)
 - field (class "za.co.abc.presentation.control.Trail", name: "one", type: "class za.co.abc.presentation.control.One")
 - root object (class "za.co.abc.presentation.control.Trail", {/click-tests/home.htm=home})

If you do use the transient keyword to make fields not serialize you probably have to then set those fields when the class is read. You have to implement the readObject() method to do that. Here is an example:

private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
    // magically read all non-transient fields from input stream and populate their values
    in.defaultReadObject();

    someTransientField = new NotSerializableClass();
}
Pinwheel answered 13/2, 2013 at 19:43 Comment(1)
+1 for -Dsun.io.serialization.extendedDebugInfo=true, very useful even for standalone Java applications.Shatter

© 2022 - 2024 — McMap. All rights reserved.