13 Replies Latest reply on Nov 10, 2011 4:32 PM by marklittle

    Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!

    pbaker01

      I would like to use nested transactions in a webservice but I am getting error:

      ARJUNA-16082 Synchronizations are not allowed! Transaction status isActionStatus.RUNNING

       

      I'm using: JBoss AS6 - Final and MySQL 5.5

       

      The error occurs when I am saving an entity in the inner transaction.

       

      My code looks like:

      package com.mytest.service;
      import javax.jws.WebService;
      import javax.naming.InitialContext;
      import javax.transaction.Status;
      import javax.transaction.SystemException;
      import javax.transaction.UserTransaction;
      import org.apache.log4j.Logger;
      import org.orm.PersistentException;
      import org.orm.PersistentSession;
      import com.arjuna.ats.arjuna.coordinator.TxStats;
      import com.mytestdata1.model.Test1entitya;
      import com.mytestdata1.model.impl.Test1entityaDAOImpl;
      import com.mytestdata1model.orm.TestDataBase1PersistentManager;
      import com.mytestdata2.model.Test2entitya;
      import com.mytestdata2.model.impl.Test2entityaDAOImpl;
      import com.mytestdata2.model.orm.TestDataBase2PersistentManager;
      /**
       * @author pbaker
       * 
       */
      @WebService(endpointInterface = "com.mytest.service.TestService")
      public class TestServiceImpl implements TestService {
          protected final static Logger logger = Logger.getRootLogger();
          @Override
          public String hello(String pName) {
              // TODO Auto-generated method stub
              return "Hello " + pName;
          }
          @Override
          public String testCommit() {
              String status = "Success";
              PersistentSession s1 = null;
              PersistentSession s2 = null;
              UserTransaction outerTxn = null;
              UserTransaction innerTxn = null;
              try {
                  outerTxn = (UserTransaction) new InitialContext()
                          .lookup("java:comp/UserTransaction");
                  // Get session for entity 1 (outer)
                  s1 = TestDataBase1PersistentManager.instance().getSession();
                  // Start outer transaction
                  // Set timeout to 2 minutes to allow for debugging...
                  outerTxn.setTransactionTimeout(120);
                  outerTxn.begin();
                  logTxStatus("Outer txn status after begin(): ",outerTxn);
                  // Save entity 2 within inner transaction
                  try {
                      // get session for entity 2 (inner)
                      s2 = TestDataBase2PersistentManager.instance().getSession();
                      // Get inner transaction
                      innerTxn = (UserTransaction) new InitialContext()
                              .lookup("java:comp/UserTransaction");
                      innerTxn.begin();
                      logTxStatus("Inner txn status after begin(): ",innerTxn);
                      // Entity for Database 2
                      Test2entitya test2a = new Test2entitya();
                      test2a.setData("test");
                      // Save entity in Database 2
                      Test2entityaDAOImpl test2EntityaDAOImpl = new Test2entityaDAOImpl();
                      test2EntityaDAOImpl.save(test2a); // <<<<<<<<<< Exception thrown here...
                      TestDataBase2PersistentManager.instance().getSession().flush();
                      logTxStatus("Inner txn status before commit(): ",innerTxn);
                      innerTxn.commit();
                  } catch (Exception ex1) {
                      try {
                          innerTxn.rollback();
                      } catch (Exception ex2) {
                          ex2.printStackTrace();
                      }
                  } finally {
                      if (s2 != null && s2.isOpen())
                          s2.close();
                  }
                  // Entity for Database 1
                  Test1entitya test1a = new Test1entitya();
                  test1a.setData("test");
                  // Save entity within outer transaction (occurs regardless if inner
                  // txn succeeded
                  Test1entityaDAOImpl test1EntityaDAOImpl = new Test1entityaDAOImpl();
                  test1EntityaDAOImpl.save(test1a);
                  logTxStatus("Outer txn status before commit(): ",outerTxn);
                  outerTxn.commit();
              } catch (Exception ex1) {
                  try {
                      outerTxn.rollback();
                  } catch (Exception ex2) {
                      ex2.printStackTrace();
                  }
                  status = "Failed";
              } finally {
                  try {
                      if (s1 != null && s1.isOpen())
                          s1.close();
                  } catch (PersistentException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
              }
              return status;
          }
          /**
           * Log transaction status.
           * 
           * @since Oct 17, 2011
           * @return void
           * @param pTxnString
           * @param pTxn
           */
          private void logTxStatus(String pTxnString, UserTransaction pTxn) {
              int status;
              String statusString;
              try {
                  status = pTxn.getStatus();
                  if (status == Status.STATUS_ACTIVE) {
                      statusString = "Status Active";
                  } else if (status == Status.STATUS_COMMITTED) {
                      statusString = "Status Committed";
                  } else if (status == Status.STATUS_COMMITTING) {
                      statusString = "Status Committing";
                  } else if (status == Status.STATUS_MARKED_ROLLBACK) {
                      statusString = "Status Marked Rollback";
                  } else if (status == Status.STATUS_NO_TRANSACTION) {
                      statusString = "Status No Transaction";
                  } else if (status == Status.STATUS_PREPARED) {
                      statusString = "Status Prepared";
                  } else if (status == Status.STATUS_PREPARING) {
                      statusString = "Status Preparing";
                  } else if (status == Status.STATUS_ROLLEDBACK) {
                      statusString = "Status Rolledback";
                  } else if (status == Status.STATUS_ROLLING_BACK) {
                      statusString = "Status Rolling Back";
                  } else if (status == Status.STATUS_UNKNOWN) {
                      statusString = "Status Unknown";
                  } else
                      statusString = "Status undefined";
              } catch (SystemException e) {
                  statusString = "Status unable to getStatus";
              }
              logger.debug(pTxnString + statusString);
              return;
          }
          /**
           * Log JBoss Transaction Stats.
           * 
           * @since Oct 17, 2011
           * @return void
           * @param pLogId
           */
          private void logTxStats(String pLogId) {
              logger.debug(" ***** " + pLogId + "*****\n"
                      + "  NumberOfAbortedTransactions: "
                      + TxStats.getInstance().getNumberOfAbortedTransactions() + "\n"
                      + " NumberOfApplicationRollbacks: "
                      + TxStats.getInstance().getNumberOfApplicationRollbacks()
                      + "\n" + "NumberOfCommittedTransactions: "
                      + TxStats.getInstance().getNumberOfCommittedTransactions()
                      + "\n" + "           NumberOfHeuristics: "
                      + TxStats.getInstance().getNumberOfHeuristics() + "\n"
                      + " NumberOfInflightTransactions: "
                      + TxStats.getInstance().getNumberOfInflightTransactions()
                      + "\n" + "           NestedTransactions: "
                      + TxStats.getInstance().getNumberOfNestedTransactions() + "\n"
                      + "    NumberOfResourceRollbacks: "
                      + TxStats.getInstance().getNumberOfResourceRollbacks() + "\n"
                      + " NumberOfTimedOutTransactions: "
                      + TxStats.getInstance().getNumberOfTimedOutTransactions()
                      + "\n" + "         NumberOfTransactions: "
                      + TxStats.getInstance().getNumberOfTransactions());
          }
      }
      

       

      Stack Trace:

       

      DEBUG  Outer txn status after begin(): Status Active

      DEBUG  Inner txn status after begin(): Status Active

      ERROR  org.orm.PersistentException: org.hibernate.exception.GenericJDBCException: Cannot open connection

      ERROR   at org.orm.PersistentTransaction.commit(PersistentTransaction.java:36)

      ERROR   at org.orm.PersistentManager.saveObject(PersistentManager.java:276)

      ERROR   at com.mytestdata2.model.impl.Test2entityaDAOImpl.save(Test2entityaDAOImpl.java:262)

      ERROR   at com.mytest.service.TestServiceImpl.testCommit(TestServiceImpl.java:77)

      ERROR   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

      ERROR   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

      ERROR   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

      ERROR   at java.lang.reflect.Method.invoke(Method.java:597)

      ERROR   at org.jboss.wsf.common.invocation.AbstractInvocationHandlerJSE.invoke(AbstractInvocationHandlerJSE.java:102)

      ERROR   at org.jboss.wsf.stack.cxf.AbstractInvoker._invokeInternal(AbstractInvoker.java:164)

      ERROR   at org.jboss.wsf.stack.cxf.AbstractInvoker.invoke(AbstractInvoker.java:112)

      ERROR   at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)

      ERROR   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)

      ERROR   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)

      ERROR   at java.util.concurrent.FutureTask.run(FutureTask.java:138)

      ERROR   at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)

      ERROR   at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:106)

      ERROR   at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:255)

      ERROR   at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:113)

      ERROR   at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:97)

      ERROR   at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:461)

      ERROR   at org.jboss.wsf.stack.cxf.ServletControllerExt.invoke(ServletControllerExt.java:172)

      ERROR   at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:57)

      ERROR   at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:156)

      ERROR   at org.jboss.wsf.stack.cxf.CXFNonSpringServletExt.invoke(CXFNonSpringServletExt.java:90)

      ERROR   at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:179)

      ERROR   at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:103)

      ERROR   at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)

      ERROR   at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:159)

      ERROR   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324)

      ERROR   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)

      ERROR   at com.mytestdata2.model.orm.TestDataBase2Filter.doFilter(TestDataBase2Filter.java:63)

      ERROR   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274)

      ERROR   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)

      ERROR   at com.mytestdata1model.orm.TestDataBase1Filter.doFilter(TestDataBase1Filter.java:63)

      ERROR   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274)

      ERROR   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)

      ERROR   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)

      ERROR   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

      ERROR   at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181)

      ERROR   at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.event(CatalinaContext.java:285)

      ERROR   at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.invoke(CatalinaContext.java:261)

      ERROR   at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88)

      ERROR   at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100)

      ERROR   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)

      ERROR   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

      ERROR   at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)

      ERROR   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

      ERROR   at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53)

      ERROR   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)

      ERROR   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)

      ERROR   at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654)

      ERROR   at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951)

      ERROR   at java.lang.Thread.run(Thread.java:662)

      ERROR  Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection

      ERROR   at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140)

      ERROR   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128)

      ERROR   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)

      ERROR   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)

      ERROR   at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)

      ERROR   at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)

      ERROR   at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:116)

      ERROR   at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)

      ERROR   at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)

      ERROR   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2393)

      ERROR   at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2856)

      ERROR   at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)

      ERROR   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)

      ERROR   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)

      ERROR   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)

      ERROR   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)

      ERROR   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)

      ERROR   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1218)

      ERROR   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)

      ERROR   at org.hibernate.transaction.JTATransaction.commit(JTATransaction.java:143)

      ERROR   at org.orm.PersistentTransaction.commit(PersistentTransaction.java:34)

      ERROR   ... 53 more

      ERROR  Caused by: org.jboss.util.NestedSQLException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (java.lang.IllegalStateException: ARJUNA-16082 Synchronizations are not allowed! Transaction status isActionStatus.RUNNING); - nested throwable: (org.jboss.resource.JBossResourceException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (java.lang.IllegalStateException: ARJUNA-16082 Synchronizations are not allowed! Transaction status isActionStatus.RUNNING))

      ERROR   at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:110)

      ERROR   at org.hibernate.connection.DatasourceConnectionProvider.getConnection(DatasourceConnectionProvider.java:89)

      ERROR   at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)

      ERROR   ... 69 more

      ERROR  Caused by: org.jboss.resource.JBossResourceException: Could not enlist in transaction on entering meta-aware object!; - nested throwable: (java.lang.IllegalStateException: ARJUNA-16082 Synchronizations are not allowed! Transaction status isActionStatus.RUNNING)

      ERROR   at org.jboss.resource.connectionmanager.TxConnectionManager.managedConnectionReconnected(TxConnectionManager.java:465)

      ERROR   at org.jboss.resource.connectionmanager.BaseConnectionManager2.reconnectManagedConnection(BaseConnectionManager2.java:625)

      ERROR   at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:499)

      ERROR   at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941)

      ERROR   at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:104)

      ERROR   ... 71 more

      ERROR  Caused by: java.lang.IllegalStateException: ARJUNA-16082 Synchronizations are not allowed! Transaction status isActionStatus.RUNNING

      ERROR   at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.registerSynchronizationImple(TransactionImple.java:367)

      ERROR   at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.registerSynchronization(TransactionImple.java:344)

      ERROR   at org.jboss.resource.connectionmanager.TransactionSynchronizer.getRegisteredSynchronizer(TransactionSynchronizer.java:185)

      ERROR   at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:698)

      ERROR   at org.jboss.resource.connectionmanager.TxConnectionManager.managedConnectionReconnected(TxConnectionManager.java:459)

      ERROR   ... 75 more

      DEBUG  Outer txn status before commit(): Status Active

       

      I found a post that stated that "supportSubtransactions" must be set to true. I made the following change in file: transaction-jboss-beans.xml

        <property name="supportSubtransactions">true</property>

       

          <bean name="JTAEnvironmentBean" class="com.arjuna.ats.jta.common.JTAEnvironmentBean">
              <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.jta:name=JTAEnvironmentBean", exposedInterface=com.arjuna.ats.jta.common.JTAEnvironmentBeanMBean.class, registerDirectly=true)</annotation>
              <constructor factoryClass="com.arjuna.ats.jta.common.jtaPropertyManager" factoryMethod="getJTAEnvironmentBean"/>
              <property name="lastResourceOptimisationInterface">org.jboss.tm.LastResource</property>
              <property name="transactionManagerClassName">com.arjuna.ats.jbossatx.jta.TransactionManagerDelegate</property>
        
        <!-- Property Added by Baker: 2011-10-16 -->
        <property name="supportSubtransactions">true</property>
        
              <property name="userTransactionClassName">com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple</property>
              <property name="transactionSynchronizationRegistryClassName">com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple</property>
              <property name="xaRecoveryNodes" preinstantiate="false">
                  <list elementClass="java.lang.String">
                      <value>1</value>
                  </list>
              </property>
              <property name="xaResourceOrphanFilterClassNames" preinstantiate="false">
                  <list elementClass="java.lang.String">
                      <value>com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter</value>
                      <value>com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter</value>
                  </list>
              </property>
          </bean> 
      

       

      Data Sources are Defined as:

       

       

      <?xml version="1.0" encoding="UTF-8"?>
      <!-- See http://www.jboss.org/community/wiki/Multiple1PC for information about local-tx-datasource -->
      <!-- $Id: mysql-ds.xml 97536 2009-12-08 14:05:07Z jesper.pedersen $ -->
      <!--  Datasource config for MySQL using 3.0.9 available from:
      http://www.mysql.com/downloads/api-jdbc-stable.html
      -->
      <datasources>
        <xa-datasource>         
       <jndi-name>TestDatabase1XADS</jndi-name>         
       <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>         
       <xa-datasource-property name="URL">jdbc:mysql://localhost:3306/testdatabase1</xa-datasource-property>         
          <user-name>testdatabase</user-name>
          <password>testdatabase</password>
       <track-connection-by-tx>true</track-connection-by-tx>         
       <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>         
       <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>       
       <min-pool-size>1</min-pool-size>         
       <max-pool-size>10</max-pool-size>    
          <no-tx-separate-pools>true</no-tx-separate-pools>
       <idle-timeout-minutes>10</idle-timeout-minutes>         
       <metadata>             
        <type-mapping>mySQL</type-mapping>         
       </metadata>     
        </xa-datasource>
        
        <xa-datasource>         
       <jndi-name>TestDatabase2XADS</jndi-name>         
       <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>         
       <xa-datasource-property name="URL">jdbc:mysql://localhost:3306/testdatabase2</xa-datasource-property>         
          <user-name>testdatabase</user-name>
          <password>testdatabase</password>
       <track-connection-by-tx>true</track-connection-by-tx>         
       <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name>         
       <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLValidConnectionChecker</valid-connection-checker-class-name>       
       <min-pool-size>1</min-pool-size>         
       <max-pool-size>10</max-pool-size>    
          <no-tx-separate-pools>true</no-tx-separate-pools>
       <idle-timeout-minutes>10</idle-timeout-minutes>         
       <metadata>             
        <type-mapping>mySQL</type-mapping>         
       </metadata>     
        </xa-datasource>
      
      </datasources>
      

       

      Hibernate Config Files look like:

       

      <?xml version="1.0" encoding="utf-8" ?>
      <!--
      Licensee: Paul Baker
      License Type: Purchased
      -->
      <!DOCTYPE hibernate-configuration PUBLIC
              "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
       "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
      <hibernate-configuration>
       <session-factory>
          <!-- properties -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.connection.datasource">java:TestDatabase1XADS</property>
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
        <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
        <property name="hibernate.connection.username">testdatabase</property>
        <property name="hibernate.connection.password">testdatabase</property>
        <property name="hibernate.connection.provider_class">org.hibernate.connection.DatasourceConnectionProvider</property>
        <property name="show_sql">false</property>
        <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
        <!-- mapping files -->
       </session-factory>
      </hibernate-configuration>
      
      <?xml version="1.0" encoding="utf-8" ?>
      <!--
      Licensee: Paul Baker
      License Type: Purchased
      -->
      <!DOCTYPE hibernate-configuration PUBLIC
              "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
       "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
      <hibernate-configuration>
       <session-factory>
          <!-- properties -->
        <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.connection.datasource">java:TestDatabase2XADS</property>
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
        <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
        <property name="hibernate.connection.username">testdatabase</property>
        <property name="hibernate.connection.password">testdatabase</property>
        <property name="hibernate.connection.provider_class">org.hibernate.connection.DatasourceConnectionProvider</property>
        <property name="show_sql">false</property>
        <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>
        <!-- mapping files -->
       </session-factory>
      </hibernate-configuration>
      

       

      What am I doing wrong?  What is causing:

      ERROR  Caused by: java.lang.IllegalStateException: ARJUNA-16082 Synchronizations are not allowed! Transaction status isActionStatus.RUNNING

       

      Envt:

      JBoss AS6 - Final

      MySQL - 5.5

      Windows 7

       

      Thanks in advance....

       

      Paul

        • 1. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
          wdfink

          As you can read in the EJB 3.0 (core) specification chapter 13.1.2, only flat transactions are supported which mean there is no nested child transaction.

          • 2. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
            pbaker01

            Hi Wolf, Thank You for your reply.

             

            This link describes Arjcore

            http://www.jboss.org/jbosstm/resources/arjcore

            What does it offer?

            ArjunaCore offers the following features:

            • Multi-threaded: transactions can have many threads operating within them concurrently.
            • Nested transactions: transactions may be nested within one another. This allows for improved fault-tolerance the failure of a nested transaction does not automatically undo the work of the parent transaction) and modularity (nesting is transparent to applications, such that an object that requires transaction support can be constructed without a requirement that it must be invoked within a transaction - if it is then it's own transactions will simply be nested within the invokers and if it is not then the transactions will be top-level).

             

            Does this article refer to another product (commercial)? 

            Also what does the "supportSubtransactions" do if nesting is not supported.

             

            I'm missing something.. Any help that the community can provide is appreciated..

             

            Paul

            • 3. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
              marklittle

              Nested transactions are an optional part of the JTA standard. Just because EJBs don't allow them doesn't mean that a transaction manager cannot support them. JBossTS has supported nested transactions since 1986 when it was first written in C++. That support continues in Java, though you have to be careful that your resource managers also support nested transactions!

              • 4. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                pbaker01

                Hi Mark, thanks for your reply. 

                I am admittly not an JBoss expert nor am I a database expert..

                 

                I am still confused whether I can or cannot use nested transactions within my WebService.

                ...That support continues in Java, though you have to be careful that your resource managers also support nested transactions!

                 

                If I can use nested transactions then what do I need to do to configure or do to get around the error that I am getting? 

                 

                Any example would be apreciated.

                 

                The business case is that all service requests are audited regardless of the business operation failed or not.  The audits represents the outer transaction and the business DB operations would be captured by the inner transactions.

                 

                Thanks in advance.

                 

                Paul

                • 5. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                  jhalliday

                  > The business case is that all service requests are audited regardless of the business operation failed or not.

                   

                  The audit log write is not a nested transaction in the ArjunaCore sense, it's an independent top level transaction that happens to take place within the same time window as the business logic transaction. Read http://community.jboss.org/thread/172886  and http://stackoverflow.com/questions/7668358/atomikos-vs-bitronix-vs-jbossts-mvcc-and-nested-transactions

                  • 6. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                    adinn

                    Paul Baker wrote:

                     

                    I am still confused whether I can or cannot use nested transactions within my WebService.

                    ...That support continues in Java, though you have to be careful that your resource managers also support nested transactions!

                     

                    Resource manager?????  Where would I define use this...

                     

                    That's a thing like a DBMS or a message system that you access via an XAResource. Only, when you want to do that in a nested transaction the resource manager has to be able to implement nested transaction semantics. i.e. it has to be able to roll forward or roll back back partial changes made in the nested transaction while still retaining the changes committed in prior nested transactions and also while keeping those changes isolated from other TXs until the outermost TX is committed or rolled back. Now there are not exactly many resource managers around which can do that and almost all of them are in laboratories or museums. That was the little joke in Mark's last comment. SO, use nested TXs if you want but you won't have any resource managers you can usefully use them with unless you build them yourself.

                    1 of 1 people found this helpful
                    • 7. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                      pbaker01

                      Ahh - Got it...

                       

                      • 8. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                        pbaker01

                        Jonathan Halliday wrote:

                         

                        > The business case is that all service requests are audited regardless of the business operation failed or not.

                         

                        The audit log write is not a nested transaction in the ArjunaCore sense, it's an independent top level transaction that happens to take place within the same time window as the business logic transaction. Read http://community.jboss.org/thread/172886  and http://stackoverflow.com/questions/7668358/atomikos-vs-bitronix-vs-jbossts-mvcc-and-nested-transactions

                        Hi Jonathan,

                         

                        Thanks.. I was refering to a business audit... The business audits request/response soap messages and entity changes (old/new values).. The business audit occurs regardless if the request message results in a fault or not..

                         

                        Thanks again..

                         

                        Paul

                        • 9. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                          marklittle

                          ArjunaCore supports nested transactions because it also provides nested transaction aware resource managers. You won't be able to use your favourtie databases, but if you're happy to use the file system for durability of your objects then you can use this today.

                          • 10. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                            pbaker01

                            Mark Little wrote:

                             

                            ArjunaCore supports nested transactions because it also provides nested transaction aware resource managers. You won't be able to use your favourtie databases, but if you're happy to use the file system for durability of your objects then you can use this today.

                             

                            Hi Mark, Thank you again for responding... I now have a better idea of what is available wrt nested transactions. 

                             

                            The closest I have been able to come up with is nesting using "suspend" which really is not nested because rolling back the outer transaction has no effect on the committed inner transactions... 

                             

                            I have posted my updated sample code here.   This code suspends the first transaction and then allows a second transaction to be started and the outcome has no effect on the suspended transaction.  However, if I rollback the suspended transaction, it will have no effect on any previously commited inner transactions. 

                             

                            I am not sure if accessing the the TransactionManager as I did is correct and what affect that suspend would have one performance and concurrent processing....  but the code does work..

                             

                            package com.mytest.service;
                            import javax.jws.WebService;
                            import javax.naming.InitialContext;
                            import javax.transaction.Status;
                            import javax.transaction.SystemException;
                            import javax.transaction.Transaction;
                            import javax.transaction.TransactionManager;
                            import javax.transaction.UserTransaction;
                            import org.apache.log4j.Logger;
                            import org.orm.PersistentException;
                            import org.orm.PersistentSession;
                            import com.arjuna.ats.arjuna.coordinator.TxStats;
                            import com.mytestdata1.model.Test1entitya;
                            import com.mytestdata1.model.impl.Test1entityaDAOImpl;
                            import com.mytestdata1model.orm.TestDataBase1PersistentManager;
                            import com.mytestdata2.model.Test2entitya;
                            import com.mytestdata2.model.impl.Test2entityaDAOImpl;
                            import com.mytestdata2.model.orm.TestDataBase2PersistentManager;
                            /**
                             * @author pbaker
                             * 
                             */
                            @WebService(endpointInterface = "com.mytest.service.TestService")
                            public class TestServiceImpl implements TestService {
                                protected final static Logger logger = Logger.getRootLogger();
                                @Override
                                public String hello(String pName) {
                                    // TODO Auto-generated method stub
                                    return "Hello " + pName;
                                }
                                @Override
                                public String testCommit() {
                                    String status = "Success";
                                    // Hibernate sessions
                                    PersistentSession s1 = null;
                                    PersistentSession s2 = null;
                                    // Transaction mansters
                                    TransactionManager outerTxnManager =  null;
                                    TransactionManager innerTxnManager =  null;
                                    Transaction suspendedTransaction;
                                    
                                    // Test Entities
                                    Test1entitya test1entitya;
                                    Test2entitya test2entitya;
                                    
                                    // DAOs
                                    Test1entityaDAOImpl test1entityaDAOImpl;  
                                    Test2entityaDAOImpl test2entityaDAOImpl; 
                                   
                                    try {
                                        
                                        outerTxnManager = this.getTransactionManager();
                                        // Get session for entity 1 (outer)
                                        s1 = TestDataBase1PersistentManager.instance().getSession();
                                        // Start outer transaction
                                        outerTxnManager.begin();
                                        logTxStatus("Outer txn status after begin(): ", outerTxnManager);
                                        
                                        // Create first Entity 1A 
                                        test1entitya = new Test1entitya();
                                        test1entitya.setData("test-before inner");
                                        // Save entity within outer transaction (occurs regardless if inner
                                        // txn succeeded
                                        Test1entityaDAOImpl test1EntityaDAOImpl = new Test1entityaDAOImpl();
                                        test1EntityaDAOImpl.save(test1entitya);
                                        
                                        suspendedTransaction  = outerTxnManager.suspend();
                                        logTxStatus("Outer txn status after suspend(): ", outerTxnManager);
                                        // Save entity 2 within inner transaction
                                        try {
                                            // get session for entity 2 (inner)
                                            s2 = TestDataBase2PersistentManager.instance().getSession();
                                            // Get inner transaction
                                            innerTxnManager = this.getTransactionManager();
                                            innerTxnManager.begin();
                                            logTxStatus("Inner txn status after begin(): ", innerTxnManager);
                                            // Entity 2 for Database 2
                                            Test2entitya test2a = new Test2entitya();
                                            test2a.setData("test");
                                            // Save entity in Database 2
                                            test2entityaDAOImpl = new Test2entityaDAOImpl();
                                            test2entityaDAOImpl.save(test2a);
                                            TestDataBase2PersistentManager.instance().getSession().flush();
                                            logTxStatus("Inner txn status before commit(): ", innerTxnManager);
                                            innerTxnManager.rollback();
                                        } catch (Exception ex1) {
                                            try {
                                                if (innerTxnManager.getStatus() == Status.STATUS_ACTIVE) {
                                                    innerTxnManager.rollback();
                                                }
                                            } catch (Exception ex2) {
                                                ex2.printStackTrace();
                                            }
                                        } finally {
                                            if (s2 != null && s2.isOpen())
                                                s2.close();
                                        }
                                        outerTxnManager.resume(suspendedTransaction);
                                        logTxStatus("Outer txn status after resume(): ", outerTxnManager);
                            
                                        // Create second Entity 1B
                                        Test1entitya test1a = new Test1entitya();
                                        test1a.setData("test-after inner");
                                        // Save entity within outer transaction (occurs regardless if inner
                                        // txn succeeded
                                        test1entityaDAOImpl = new Test1entityaDAOImpl();
                                        test1entityaDAOImpl.save(test1a);
                                        logTxStatus("Outer txn status before commit(): ", outerTxnManager);
                                        // Commit save to Entity A and Entity B
                                        outerTxnManager.commit();
                                    } catch (Exception ex1) {
                                        try {
                                            if (outerTxnManager.getStatus() == Status.STATUS_ACTIVE) {
                                                outerTxnManager.rollback();
                                            }
                                        } catch (Exception ex2) {
                                            ex2.printStackTrace();
                                        }
                                        status = "Failed";
                                    } finally {
                                        try {
                                            if (s1 != null && s1.isOpen())
                                                s1.close();
                                        } catch (PersistentException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }
                                    }
                                    return status;
                                }
                                
                                /**
                                 * 
                                 * http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Web_Platform/5/pdf/Transactions_JTA_Development_Guide/JBoss_Enterprise_Web_Platform-5-Transactions_JTA_Development_Guide-en-US.pdf
                                 * http://onjava.com/onjava/2005/07/20/transactions.html
                                 * @since Oct 18, 2011
                                 * @return TransactionManager
                                 * @return
                                 * @throws Exception
                                 */
                                private TransactionManager getTransactionManager() throws Exception {
                                    InitialContext ctx = new InitialContext();
                                    try {
                                        // JBoss
                                        return (TransactionManager) ctx.lookup("java:/TransactionManager");
                                    } catch (Exception e) {
                                    }
                                    try {
                                        // WebLogic
                                        return (TransactionManager) ctx
                                                .lookup("javax.transaction.TransactionManager");
                                    } catch (Exception e) {
                                    }
                                    
                                    // Unable to load TransactionManager - Abort
                                    throw new Exception();
                                }
                                
                                /**
                                 * 
                                 * 
                                 * @since Oct 18, 2011
                                 * @return UserTransaction
                                 * @return
                                 * @throws Exception
                                 */
                                private UserTransaction getUserTransaction() throws Exception {
                                    
                                    try {
                                        // JBoss
                                        return (UserTransaction) new InitialContext()
                                        .lookup("java:comp/UserTransaction");
                                    } catch (Exception e) {
                                    }
                                    
                                    try {
                                        // WebLogic
                                        return (UserTransaction) new InitialContext()
                                        .lookup("javax.transaction.UserTransaction");
                                    } catch (Exception e) {
                                    }
                                    // Unable to load UserTransaction - Abort
                                    throw new Exception();
                                }
                                /**
                                 * Log transaction status.
                                 * 
                                 * @since Oct 17, 2011
                                 * @return void
                                 * @param pTxnString
                                 * @param pTxn
                                 */
                                private void logTxStatus(String pTxnString, TransactionManager pTxn) {
                                    // If logging is not enabled then just return.
                                    if (!logger.isDebugEnabled()) {
                                        return;
                                    }
                                    int status;
                                    String statusString;
                                    try {
                                        status = pTxn.getStatus();
                                        if (status == Status.STATUS_ACTIVE) {
                                            statusString = "Status Active";
                                        } else if (status == Status.STATUS_COMMITTED) {
                                            statusString = "Status Committed";
                                        } else if (status == Status.STATUS_COMMITTING) {
                                            statusString = "Status Committing";
                                        } else if (status == Status.STATUS_MARKED_ROLLBACK) {
                                            statusString = "Status Marked Rollback";
                                        } else if (status == Status.STATUS_NO_TRANSACTION) {
                                            statusString = "Status No Transaction";
                                        } else if (status == Status.STATUS_PREPARED) {
                                            statusString = "Status Prepared";
                                        } else if (status == Status.STATUS_PREPARING) {
                                            statusString = "Status Preparing";
                                        } else if (status == Status.STATUS_ROLLEDBACK) {
                                            statusString = "Status Rolledback";
                                        } else if (status == Status.STATUS_ROLLING_BACK) {
                                            statusString = "Status Rolling Back";
                                        } else if (status == Status.STATUS_UNKNOWN) {
                                            statusString = "Status Unknown";
                                        } else
                                            statusString = "Status undefined";
                                    } catch (SystemException e) {
                                        statusString = "Status unable to getStatus";
                                    }
                                    logger.debug(pTxnString + statusString);
                                    return;
                                }
                                /**
                                 * Log JBoss Transaction Stats.
                                 * 
                                 * @since Oct 17, 2011
                                 * @return void
                                 * @param pLogId
                                 */
                                private void logTxStats(String pLogId) {
                                    // If logging not enabled or if status is not enabled..
                                    // then just return.
                                    if (!logger.isDebugEnabled() || !TxStats.enabled()) {
                                        return;
                                    }
                                    logger.debug(" ***** " + pLogId + "*****\n"
                                            + "  NumberOfAbortedTransactions: "
                                            + TxStats.getInstance().getNumberOfAbortedTransactions() + "\n"
                                            + " NumberOfApplicationRollbacks: "
                                            + TxStats.getInstance().getNumberOfApplicationRollbacks()
                                            + "\n" + "NumberOfCommittedTransactions: "
                                            + TxStats.getInstance().getNumberOfCommittedTransactions()
                                            + "\n" + "           NumberOfHeuristics: "
                                            + TxStats.getInstance().getNumberOfHeuristics() + "\n"
                                            + " NumberOfInflightTransactions: "
                                            + TxStats.getInstance().getNumberOfInflightTransactions()
                                            + "\n" + "           NestedTransactions: "
                                            + TxStats.getInstance().getNumberOfNestedTransactions() + "\n"
                                            + "    NumberOfResourceRollbacks: "
                                            + TxStats.getInstance().getNumberOfResourceRollbacks() + "\n"
                                            + " NumberOfTimedOutTransactions: "
                                            + TxStats.getInstance().getNumberOfTimedOutTransactions()
                                            + "\n" + "         NumberOfTransactions: "
                                            + TxStats.getInstance().getNumberOfTransactions());
                                }
                            }
                            

                             

                             

                            Thanks again.. I think that my final solution will try and use just one transaction under UserTransaction...

                             

                            Thanks everyone for commenting.

                             

                            Paul

                            • 11. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                              marklittle

                              What you're doing is a nested top-level transaction and it is behaving as expected: the inner transaction is not under the control of the enclosing transaction, since there is no parent/child relationship here. Check out the ArjunaCore Programmers Guide as it discussed nested transactions and nested top-level transactions.

                              • 12. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                                pbaker01

                                Hi Mark, I will look through it again.  I saw the post and your comment:
                                http://planet.jboss.org/post/nested_transactions_101 

                                Mark Little said...

                                It's worth adding that we have helper classes in JBossTS for simplifying the creation of nested top level transactions. I'll leave that as an exercise to the reader.

                                 

                                 

                                I'm stuggling here... So is it possible that I can have a parent txn that, if fails (rolledback), will also roll back the child (nested) transactions. From the comments above I thought that this was not possible..

                                 

                                Paul

                                • 13. Re: Nested Transactions AS6 & MySQL - ARJUNA-16082 Synchronizations are not allowed!
                                  marklittle

                                  If the parent tries to commit before its children have ended then they will be automatically rolled back and the parent will be rolled back too. If the children have committed by the time the parent tries to commit then it will commit, assuming no further faults. If the children have committed by the time the partent tries to roll back then the children will be rolled back too. So basically the rule is: if the child transaction(s) commit(s) then its ultimate outcome is driven by the parent; if the child rolls back then it really doesn't matter what the parent does since the child has gone away.