13 Replies Latest reply: Nov 10, 2011 4:32 PM by Mark Little RSS

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

Paul Baker Novice

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!
    Wolf-Dieter Fink Master

    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!
    Paul Baker Novice

    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!
    Mark Little Master

    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!
    Paul Baker Novice

    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!
    Jonathan Halliday Master

    > 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!
    Andrew Dinn Master

    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.

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

    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!
    Mark Little Master

    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!
    Paul Baker Novice

    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!
    Mark Little Master

    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!
    Paul Baker Novice

    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!
    Mark Little Master

    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.