2011-08-01 14 views
21

Mi implementación de DAO arroja una excepción no serializable en el inicio del servidor con Tomcat7. Alguna idea que causa esto? Ninguno de mis otros DAO está haciendo esto.¿Qué causa una NotSerializableException en Tomcat 7?

Aquí está la clase:

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; 
    } 
} 

Aquí es mi 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> 

Aquí es mi pila:

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 
+0

¿Está estableciendo este objeto en algún lugar de la sesión o como una variable de un objeto que está almacenado en la sesión? –

+0

Es una variable en un objeto que se almacena en sesión. – coder

+0

Quítelo, ya que este objeto tiene acceso a la sesión de Hibernate y nunca podrá serializarse. –

Respuesta

21

UserDaoImpl debe implementar la interfaz java.io.Serializable si ha de ser serializado (su rastro de pila indica que se ha intentado escribir una instancia de la clase a una secuencia de objetos).

La instancia que se serializará, junto con todos los objetos en el gráfico de objetos de esa instancia, deben ser serializables.

De los javadocs para Serializable,

Serializabilidad de una clase está habilitado de la clase que implementa la interfaz java.io.Serializable ... Cuando atraviesa un gráfico, un objeto puede encontrarse que hace no es compatible con la interfaz Serializable. En este caso, se lanzará NotSerializableException y se identificará la clase del objeto no serializable.

Tenga en cuenta que existen excepciones a estas reglas. Le recomiendo que lea el documento Java Object Serialization Specification para obtener una comprensión completa de cuándo tiene lugar la serialización de objetos y qué se necesita para evitar una NotSerializableException.

+9

Esto no es información útil en particular. El OP necesita saber * por qué * esto está sucediendo durante el inicio, en lugar del fino detalle sobre la mecánica de serialización. – skaffman

+1

Esta podría ser la causa proximal, pero no la causa raíz. ¿Cómo propone hacer una HibernateTemplate serializable? – pap

+1

No es una buena idea serializar beans manejados por resorte. –

32

Está sucediendo porque en algún lugar de su código, está almacenando un UserDAO en la sesión (o está almacenando un objeto que tiene una referencia a un UserDAO). Tomcat intenta serializar el gráfico de objetos completo de todas las sesiones activas cuando lo cierra, y luego intenta restaurarlas cuando lo inicia de nuevo. El quid de esto es que Tomcat usa la serialización de objetos java "normal", que requiere que todos los objetos sean Serializable.

cómo remediar:

  1. No guarde objetos no serializables en la sesión de usuarios (generalmente una buena práctica).
  2. Haga su UserDAO serializable. Probablemente implica implementar la interfaz Serializable y marcar hibernateTemplate como transient ya que no creo que HibernateTemplate sea, en sí mismo, serializable. Es posible que deba agregar algún código que reinicialice la plantilla hibernate en la deserialización si realmente desea que funcione.
  3. No tiene sesiones de serialización Tomcat (agregue <Manager pathname="" /> al contexto.xml, ya sea en su propia aplicación o en el contexto global tomcat context.xml en el directorio conf/dentro del elemento <Context>. Este podría ser el mejor curso de acción para usted, a menos que realmente necesite sesiones para continuar en reinicios.
+1

Necesito decir esto. Tu respuesta es genial. Me ayudó mucho, gracias. – me1111

13

Las otras respuestas aquí explican bien la serialización. Como este es el primer resultado en Google, quería agregar información que realmente me ayudó a resolver el problema.

El mensaje de excepción en sí no indica qué campo en qué clase causó este problema. Si no puede hacer que una clase sea serializable y necesita agregar la palabra clave transitoria para que Java no intente serializar un campo, puede ser difícil determinar qué campo está causando el problema.

Si agrega el parámetro -Dsun.io.serialization.extendedDebugInfo=true a Java/Tomcat al iniciarlo, la excepción será mucho más útil. Aquí está un ejemplo de lo que el mensaje de excepción se verá así:

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", [email protected]) 
- 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", [email protected]) 
- 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}) 

Si utiliza la palabra clave transitoria para hacer campos no serializar es probable que tenga que configurar entonces esos campos cuando se lee la clase. Tienes que implementar el método readObject() para hacer eso. Aquí hay un ejemplo:

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(); 
} 
+4

+1 para '-Dsun.io.serialization.extendedDebugInfo = true', muy útil incluso para aplicaciones Java independientes. – javashlook

Cuestiones relacionadas