1 Reply Latest reply on Jul 27, 2007 2:05 PM by genman

    Classloading issue either with JMS inflow, TM, or Hibernate

    genman


      Issue with JBoss 4.2.0

      Hibernate can't seem to find my class when it does a commit from a MDB. It seems Hibernate doesn't know the classloader, and

      The way to reproduce this is to create an EJB3 entity with a Serializable field, modify that field in an MDB, and you get this:

      2007-07-25 11:14:41,313 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
      org.hibernate.type.SerializationException: could not deserialize
      at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:214)
      at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:240)
      at org.hibernate.type.SerializableType.fromBytes(SerializableType.java:82)
      at org.hibernate.type.SerializableType.deepCopyNotNull(SerializableType.java:74)
      at org.hibernate.type.MutableType.deepCopy(MutableType.java:25)
      at org.hibernate.type.SerializableToBlobType.deepCopy(SerializableToBlobType.java:102)
      at org.hibernate.type.TypeFactory.deepCopy(TypeFactory.java:353)
      at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:114)
      at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
      at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
      at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:515)
      at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:114)
      at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:249)
      at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:88)
      at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177)
      at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1256)
      at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
      at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
      at org.jboss.resource.adapter.jms.inflow.JmsServerSession$XATransactionDemarcationStrategy.end(JmsServerSession.java:494)
      at org.jboss.resource.adapter.jms.inflow.JmsServerSession.run(JmsServerSession.java:248)
      at org.jboss.resource.work.WorkWrapper.execute(WorkWrapper.java:204)
      at org.jboss.util.threadpool.BasicTaskWrapper.run(BasicTaskWrapper.java:275)
      at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
      at java.lang.Thread.run(Thread.java:595)
      Caused by: java.lang.ClassNotFoundException: No ClassLoaders found for: com.example.msg.Message
      at org.jboss.mx.loading.LoadMgr3.beginLoadTask(LoadMgr3.java:306)
      at org.jboss.mx.loading.RepositoryClassLoader.loadClassImpl(RepositoryClassLoader.java:514)
      at org.jboss.mx.loading.RepositoryClassLoader.loadClass(RepositoryClassLoader.java:408)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:242)
      at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:574)
      at org.hibernate.util.SerializationHelper$CustomObjectInputStream.resolveClass(SerializationHelper.java:268)
      at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1538)
      at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1460)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1693)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
      at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:210)
      ... 28 more
      


      Looks like serialization expects the context classloader to be set correctly for the calling thread:

      
      public final class SerializationHelper {
      ...
       /**
       * Custom ObjectInputStream implementation to more appropriately handle classloading
       * within app servers (mainly jboss - hence this class inspired by jboss's class of
       * the same purpose).
       */
       private static final class CustomObjectInputStream extends ObjectInputStream {
       ClassLoader loader = Thread.currentThread().getContextClassLoader();
      
      


        • 1. Re: Classloading issue either with JMS inflow, TM, or Hibern
          genman


          I have more of a definitive question than a problem.

          When does Thread.setCurrentClassLoader() get called for messages being processed in an MDB?

          It seems this is somehow reset. JBoss AS /connector does not do this. Looking at the Hibernate sources, Hibernate does not make this call. So I assume it's part of JBoss Messaging (the JmsSession), and it must get reset before transaction commit.