3 Replies Latest reply on May 5, 2010 9:23 AM by sebersole

    CNFE with JTS and a scoped classloader

    brian.stansberry

      Starting a discussion failure seen at https://jira.jboss.org/jira/browse/JBAS-7434.

      Simple description of the problem is that the test deploys a Hibernate application with a scoped classloader, so some application classes are not visible to the classloader that loads JBossTS or jacorb.jar. As part of transaction processing, Hibernate registers a Synchronization that during beforeCompletion() serializes an object to a byte[] and then deserializes it. Basically as a mechanism to make a defensive copy. The deserialization fails with a CNFE.

      This test has worked fine for years with the standard AS JTA config; last week we started executing it with the AS configured for JTS, and it fails. See the JIRA description for a stack trace.

      It seems the biggest difference is with JTS the thread executing the Synchronization is not the original client request thread that invoked on Hibernate. Rather it's a jacorb RequestProcessor thread. This thread doesn't appear to have the correct TCL.

      Seems to me either JBossTS should be establishing the correct TCL on the thread or Hibernate should when the Synchronization is invoked. Steve Ebersole tells me Hibernate *never* sets the TCL on a thread, so I'm looking for input from you folks.

      I'm going to assign this JIRA to Steve for now. The failure popped up in a test with cluster in the package, but the actual failure mode has nothing to do with clustering. I'll also notify him of this thread, and will follow it myself. It seems like something common that would have popped up before -- loading a class in a tx synchronization callback -- so maybe I'm missing something.

        • 1. Re: CNFE with JTS and a scoped classloader
          smarlow

          For the above mentioned case, Is there a way to make the com.arjuna.ArjunaOTS.ManagedSynchronizationPOA._invoke run in the user/application thread that commited the transaction. This might be an optimization for the case where the client invocation came from a local thread.

          • 2. Re: CNFE with JTS and a scoped classloader
            jhalliday

            The threading model depends on the ORB implementation, some of which do optimize out the thread switch. However, running in the loader context of the commit()/rollback() caller is probably wrong, not least because it still leaves you in a mess if the caller is remote or is itself isolated e.g. the tx is begun/ended by the container or another app.

            IMO you are better off using the loader that was in effect at the time the Synchronization was registered with the tx i.e. have the SynchronizaitonImple (JBossTS) or javax.transaction.Synchronization impl (Hibernate) keep a CL ref in the constructor and use it in before/afterCompletion. That way it still works even if the tx spans multiple isolated loaders, each of which may register Synchronizations.

            Impl detail if we decide to do this on the TS side: com.arjuna.ArjunaOTS code is autogenerated from the IDL, so don't mess with it. SynchronizationImple is where the action is.

            • 3. Re: CNFE with JTS and a scoped classloader
              sebersole

              The issue here imo is in org.hibernate.type.SerializableToBlobType.deepCopy.  Brian, not sure if you remember but we made some changes to the Hibermate Type implementations that dealt with serialization such that we use the class loader of the serializable class when doing the deserialization or deep copy.  Not all use cases have been covered yet.  Here, the class used to determine the classloader is java.io.Serializable itself

               

              This is changing in 3.6 and I could *potentially* back-port the changes to 3.5.  Which version are you using here?