4 Replies Latest reply on Nov 3, 2014 2:17 PM by spadhi

    JTA: Hibernate can't find java:jboss/UserTransaction

    spadhi

      I'm migrating a legacy Spring3/Hibernate3/JBoss5 codebase to Spring4/Hibernate4 on JBoss Wildfly8. Getting Spring4 and Hibernate4 to play well together using JTA on Wildfly has been a challenge so far.  The issues that I'm facing are:

       

      1. Hibernate is unable to get the transaction. The error happens in line 92 of hibernate-orm/JTASessionContext.java at master · hibernate/hibernate-orm · GitHub

       

      2. To get around the issue#1, I open a new Hibernate session (when getSessionFactory().getCurrentSession() throws the exception above). Hibernate is then unable to locate the userTransaction at line 79 of hibernate-orm/JtaTransactionFactory.java at master · hibernate/hibernate-orm · GitHub

       

      The JNDI view in the Wildfly console shows java:jboss/TransactionManager and java:jboss/UserTransaction as follows:

       

      java:jboss

       

       

      TransactionManagerTransactionManagerDelegate@49e6e9c8

       

       

      TransactionSynchronizationRegistryTransactionSynchronizationRegistryImple@40cd0746

       

       

      UserTransactionUserTransaction

       

       

      jaasjava:jboss/jaas/ Context proxy

       

      The Spring setup "seems" to be ok based on initial debugging. And the Hibernate session seems not to be in sync. Not sure what I'm missing here, so I would really appreciate it if anyone has tried this before and has any suggestions. Here's the relevant snippet of what I have in the Spring config xml:

       

          <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">

              <property name="userTransactionName" value="java:jboss/UserTransaction"/>

              <property name="transactionManagerName" value="java:jboss/TransactionManager"/>

          </bean>

       

           <tx:annotation-driven/>

       

          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="false">

              <property name="jndiName" value="java:jboss/datasources/jdbc/my-srvr"/>

              <property name="cache">

                  <value>false</value>

              </property>

              <property name="proxyInterface">

                  <value>javax.sql.DataSource</value>

              </property>

          </bean>

       

          <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" lazy-init="true">

       

       

              <property name="dataSource" ref="dataSource"/>

       

       

              <property name="jtaTransactionManager" ref="transactionManager"/>

       

       

              <property name="packagesToScan" value="com.mydomain" />

       

       

              <property name="mappingResources">

                  <list>

                      <value>sample1.hbm.xml</value>

                      <value>sample2.hbm.xml</value>

                  </list>

              </property>

       

       

              <property name="hibernateProperties">

                  <props>

                      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>

                      <prop key="hibernate.show_sql">false</prop>

                      <prop key="hibernate.generate_statistics">false</prop>

       

                      <!-- JTA  -->

                      <prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop>

                      <prop key="hibernate.flushMode">AUTO</prop>

                      <prop key="jta.UserTransaction">java:jboss/UserTransaction</prop>

                      <prop key="jta.TransactionManager">java:jboss/TransactionManager</prop>

                      <prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform</prop>

                      <prop key="hibernate.current_session_context_class">org.hibernate.context.internal.JTASessionContext</prop>

       

                     <!--Turned off caching to focus on JTA issues-->

                     <prop key="hibernate.cache.use_second_level_cache">false</prop>

                      <prop key="hibernate.cache.use_query_cache">false</prop>

                      <!--prop key="hibernate.cache.provider_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop-->

                      <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

       

                      <prop key="net.sf.ehcache.configurationResourceName">sample-ehcache.xml</prop>

                  </props>

              </property>

       

              <!--No hibernate4 equivalent in Spring; comment out for now-->

              <!--property name="eventListeners">

                  <map>

                      <entry key="merge">

                          <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>

                      </entry>

                  </map>

              </property-->

          </bean>

       

      Thanks in advance!

        • 1. Re: JTA: Can't find java:jboss/UserTransaction
          ksreen

          I think specifying just <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" /> should do.  There is no need to override the JNDI names of the TransactionManager and UserTransaction as the JtaTransactionManager will figure out the the JNDI names.

          • 2. Re: JTA: Can't find java:jboss/UserTransaction
            spadhi

            I specified those two properties to be explicit. Taking them out, as you suggested, works as well. It doesn't help resolve the Spring4-Hibernate4 session sync issues ( getSessionFactory().getCurrentSession() exception) though and the subsequent issue of a null UserTransaction (in the TransactionManager) if you open a new Hibernate session. Any suggestions on that?

            • 3. Re: JTA: Can't find java:jboss/UserTransaction
              ksreen

              I think the transaction manager class to be used with Hibernate 4 is org.springframework.orm.hibernate4.HibernateTransactionManager.  I quote from the API documentation of this class

              "This transaction manager is appropriate for applications that use a single Hibernate SessionFactory for transactional data access, but it also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource). This allows for mixing services which access Hibernate and services which use plain JDBC (without being aware of Hibernate)! "

               

              The transaction manager org.springframework.transaction.jta.JtaTransactionManager is a generic transaction manager and cannot bind a HibernateSession.

               

              This means you must try the following

              <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager>

                   <property name="sessionFactory" ref="sessionFactory" />

              </bean>

              1 of 1 people found this helpful
              • 4. Re: JTA: Can't find java:jboss/UserTransaction
                spadhi

                Thank you for the suggestion! I tried using the HibernateTransactionManager instead of the JtaTransactionManager and do see some improvements in session binding and usertransaction retrieval. Note that the call getSessionFactory().getCurrentSession() sometimes returns the current session and sometimes the Spring HibernateTemplate catches the exception (mentioned earlier in this thread) and opens a new session; I have not yet been able to identify a pattern as to why. The code I'm referring to is in line 325:

                spring-framework/HibernateTemplate.java at master · spring-projects/spring-framework · GitHub

                 

                I have now unset the transactionManager property on the sessionFactory bean to avoid circular references. As I am seeing some improvements in the code flow, I am going to mark your response as a Helpful Answer.

                 

                I'm not completely out of the woods though. The next problem this uncovers is in the org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl class. Specifically, I'm seeing write transactions return at line 256 because of the check at line 252:

                hibernate-orm/TransactionCoordinatorImpl.java at master · hibernate/hibernate-orm · GitHub

                 

                which leads to org.hibernate.engine.transaction.jta.platform.internal.TransactionManagerBasedSynchronizationStrategy at line 56:

                hibernate-orm/TransactionManagerBasedSynchronizationStrategy.java at master · hibernate/hibernate-orm · GitHub

                 

                The read-only operations seem to be going all the way to line 269 in the TransactionCoordinatorImpl class and executing successfully. What am I missing for the write operations?