Andriy Nastyn
Andriy Nastyn

Reputation: 218

JtaTransactionManager no rollback after failed commit during "flush"


Update: I was testing it with Bitronix TM and it rollbacks perfectly, so the issue is in JBoss TM (arjuna) or in my configuration.

Update 2: It looks like transactions are not global, I've tried different datasources, Bitronix datasource has allowLocalTransactions property and after setting it my application throws an exception that something tried to use it in local mode. If I use Bitronix with this datasource it works without any errors. I believe there is something wrong in configs.

I have an issue with JTA transactions. I'm using Tomcat 7 + Hibernate 4 + Spring 3 + JBoss TS 4 and JTA transactions.

Suppose there is the following method:

@Transactional(propagation = Propagation.REQUIRED)
public void testMethod() {
    insertOfSomeNewEntityInstance();
    updateOfAnotherEntity();
}

private void insertOfSomeNewEntityInstance() {
    SomeEntity entity = new SomeEntity();
    someEntityDAO.save(entity);
}

private void updateOfAnotherEntity() {
    AnotherEntity anotherEntity = anotherEntityDAO.findBySomeProperty(1L);
    anotherEntity.incrementSomeValue();
    anotherEntityDAO.save(anotherEntity);
}

If this method throws "org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)" during "updateOfAnotherEntity()" method execution or any other runtime exception that might happen during "flush" (Hibernate also shows: HHH000346: Error during managed flush [Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect). then the result of insertOfSomeNewEntityInstance() execution is not rolled back.

After debugging this issue I found "doCommit" method in org.springframework.transaction.jta.JtaTransaction Manager

@Override
    protected void doCommit(DefaultTransactionStatus status) {
        JtaTransactionObject txObject = (JtaTransactionObject) status.getTransaction();
        try {
            int jtaStatus = txObject.getUserTransaction().getStatus();
            if (jtaStatus == Status.STATUS_NO_TRANSACTION) {
                throw new UnexpectedRollbackException("JTA transaction already completed - probably rolled back");
            }
            if (jtaStatus == Status.STATUS_ROLLEDBACK) {
                try {
                    txObject.getUserTransaction().rollback();
                }
                catch (IllegalStateException ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Rollback failure with transaction already marked as rolled back: " + ex);
                    }
                }
                throw new UnexpectedRollbackException("JTA transaction already rolled back (probably due to a timeout)");
            }
            txObject.getUserTransaction().commit();
        }
        catch (RollbackException ex) {
            throw new UnexpectedRollbackException(
                    "JTA transaction unexpectedly rolled back (maybe due to a timeout)", ex);
        }
        catch (HeuristicMixedException ex) {
            throw new HeuristicCompletionException(HeuristicCompletionException.STATE_MIXED, ex);
        }
        catch (HeuristicRollbackException ex) {
            throw new HeuristicCompletionException(HeuristicCompletionException.STATE_ROLLED_BACK, ex);
        }
        catch (IllegalStateException ex) {
            throw new TransactionSystemException("Unexpected internal transaction state", ex);
        }
        catch (SystemException ex) {
            throw new TransactionSystemException("JTA failure on commit", ex);
        }
    }

If "txObject.getUserTransaction().commit();" fails with RollbackException then this method throws UnexpectedRollbackException and here is the part of org.springframework.transaction.support.AbstractPl atformTransactionManager processCommit(...) that catches it:

}
 catch (UnexpectedRollbackException ex) {
                // can only be caused by doCommit
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
                throw ex;
    }

I do not see any rollbacks in triggerAfterCompletion() method and after this method everything else just cleans up resources.

To sum up, spring/jboss just commits the result of insertOfSomeNewEntityInstance(), fails to execute updateOfAnotherEntity() because of concurrent modification error, and does not rollback anything. If I manually throw any runtime or checked exception from updateOfAnotherEntity() it rollbacks correctly, the issue occurs only when Hibernate throws some runtime exception during "flush".

hibernate.cfg

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
    <property name="dialect">${dialect}</property>
    <property name="max_fetch_depth">1</property>
    <property name="hibernate.jdbc.batch_size">25</property>
    <property name="show_sql">false</property>
    <property name="format_sql">false</property>
    <property name="use_sql_comments">false</property>
    <property name="hibernate.session_factory_name">TestSessionFactory</property>
    <property name="hibernate.session_factory_name_is_jndi">false</property>
    <property name="hibernate.current_session_context_class">jta</property>
    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
    <property name="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.JBossStandAloneJtaPlatform</property>
    <property name="hibernate.id.new_generator_mappings">true</property>
    <property name="hibernate.cache.infinispan.cfg">infinispan.xml</property>
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.infinispan.InfinispanRegionFactory</property>
</session-factory>
</hibernate-configuration>

jbossts-properties.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <entry key="CoordinatorEnvironmentBean.commitOnePhase">YES</entry>
    <entry key="CoordinatorEnvironmentBean.defaultTimeout">300</entry>
    <entry key="ObjectStoreEnvironmentBean.transactionSync">ON</entry>
    <entry key="CoreEnvironmentBean.nodeIdentifier">1</entry>
    <entry key="JTAEnvironmentBean.xaRecoveryNodes">1</entry>
    <entry key="JTAEnvironmentBean.xaResourceOrphanFilterClassNames">
        com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter
        com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter
    </entry>

    <entry key="CoreEnvironmentBean.socketProcessIdPort">0</entry>

    <entry key="RecoveryEnvironmentBean.recoveryModuleClassNames">
        com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule
        com.arjuna.ats.internal.txoj.recovery.TORecoveryModule
        com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule
    </entry>

    <entry key="RecoveryEnvironmentBean.expiryScannerClassNames">
        com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner
    </entry>

    <entry key="RecoveryEnvironmentBean.recoveryPort">4712</entry>

    <entry key="RecoveryEnvironmentBean.recoveryAddress"></entry>

    <entry key="RecoveryEnvironmentBean.transactionStatusManagerPort">0</entry>
    <entry key="RecoveryEnvironmentBean.transactionStatusManagerAddress"></entry>

    <entry key="RecoveryEnvironmentBean.recoveryListener">YES</entry>

</properties>

Part of applicationContext.xml

<bean class="com.arjuna.ats.jta.TransactionManager" factory-method="transactionManager" id="arjunaTransactionManager"></bean>
    <bean class="com.arjuna.ats.jta.UserTransaction" factory-method="userTransaction" id="arjunaUserTransaction"></bean>

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" >
        <property name="transactionManager" ref="arjunaTransactionManager"/>
        <property name="userTransaction" ref="arjunaUserTransaction"/>
    </bean>

    <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.XADataSource" destroy-method="close">
        <property name="url" value="${database.url}" />
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="username" value="${database.user}" />
        <property name="password" value="${database.password}" />
    </bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" destroy-method="destroy">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation"><value>classpath:hibernate.cfg.xml</value></property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.cache.use_second_level_cache">false</prop>
                <prop key="hibernate.cache.use_query_cache">false</prop>
            </props>
        </property>
    </bean>

    <tx:annotation-driven mode="proxy" proxy-target-class="false" transaction-manager="transactionManager"/>

And the log:

Completing transaction for [...testMethod]
Triggering beforeCommit synchronization
Triggering beforeCompletion synchronization
BaseTransaction.getStatus
TransactionImple.getStatus
Initiating transaction commit
BaseTransaction.getStatus
TransactionImple.getStatus
BaseTransaction.commit
TransactionImple.commitAndDisassociate
SynchronizationImple.beforeCompletion
BaseTransaction.getStatus
TransactionImple.getStatus

insert into .....
update ... set ...

BaseTransaction.setRollbackOnly
TransactionImple.setRollbackOnly
BasicAction::preventCommit( BasicAction: 0:ffffc0a800ab:8d15:51b6fe47:3 status: ActionStatus.RUNNING)
HHH000346: Error during managed flush [Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [...]]
ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffffc0a800ab:8d15:51b6fe47:4, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@76d7a0b8 >
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [...]
        at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2509) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3228) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3126) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3456) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:287) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:113) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:273) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:93) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1165) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126) [narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1010) [spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) [spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) [spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:387) [spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) [spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) [spring-aop-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) [spring-aop-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at $Proxy126.testMethod(Unknown Source) [na:na]
        ...

BasicAction::preventCommit( BasicAction: 0:ffffc0a800ab:8d15:51b6fe47:3 status: ActionStatus.ABORT_ONLY)
BasicAction::Abort() for action-id 0:ffffc0a800ab:8d15:51b6fe47:3
SynchronizationImple.afterCompletion
TransactionImple.equals
SynchronizationImple.afterCompletion
BasicAction::removeChildThread () action 0:ffffc0a800ab:8d15:51b6fe47:3 removing TSThread:2
BasicAction::removeChildThread () action 0:ffffc0a800ab:8d15:51b6fe47:3 removing TSThread:2 result = true
TransactionReaper::remove ( BasicAction: 0:ffffc0a800ab:8d15:51b6fe47:3 status: ActionStatus.ABORTED )
Triggering afterCompletion synchronization
Clearing transaction synchronization
Exception
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1013) ~[spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) ~[spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) ~[spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:387) ~[spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) ~[spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) ~[spring-aop-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        at $Proxy126.testMethod(Unknown Source) ~[na:na]
        ...
Caused by: javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
        at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1177) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1010) ~[spring-tx-3.1.4.RELEASE.jar:3.1.4.RELEASE]
        ... 32 common frames omitted
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [...]
        at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2509) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3228) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3126) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3456) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:287) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:113) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53) ~[hibernate-core-4.2.2.Final.jar:4.2.2.Final]
        at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:273) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:93) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1165) ~[narayana-jta-4.17.4.Final.jar:4.17.4.Final]
        ... 34 common frames omitted

Upvotes: 3

Views: 16024

Answers (1)

Andriy Nastyn
Andriy Nastyn

Reputation: 218

I've found that the issue was in the configuration. Tomcat XA pool didn't know about JBoss Transaction Manager. I tried to change driverClassName to TransactionalDriver like this:

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.XADataSource" destroy-method="close">
        <property name="defaultAutoCommit" value="false" />
        <property name="url" value="jdbc:arjuna:" />
        <property name="driverClassName">
            <value>com.arjuna.ats.jdbc.TransactionalDriver</value>
        </property>
        <property name="username" value="${database.user}" />
        <property name="password" value="${database.password}" />
        <property name="initialSize" value="${database.pool.initialSize}"/>
        <property name="maxActive" value="${database.pool.maxSize}"/>
        <property name="maxIdle" value="${database.pool.maxSize}"/>
        <property name="connectionProperties" value="DYNAMIC_CLASS=com.example.CustomDatasourceLoader;"/>

Unfortunately it was throwing an exception for subtransactions saying that connection belongs to another transaction, so that I had to find another connection pool.

Oracle UCP pool didn't work properly as well, there is no way to change driverClassName to TransactionalDriver because it is hard-coded to OracleDriver.

The following configuration works for me (DBCP XA pool) and correctly rollbacks, commits, supports subtransactions:

<bean id="oracleXADataSource" class="oracle.jdbc.xa.client.OracleXADataSource">
        <property name="user" value="${database.user}"/>
        <property name="password" value="${database.password}"/>
        <property name="URL" value="${database.url}"/>
    </bean>

    <bean id="dsXAConnectionFactory" class="org.apache.commons.dbcp.managed.DataSourceXAConnectionFactory">
        <constructor-arg><ref bean="arjunaTransactionManager"></ref></constructor-arg>
        <constructor-arg><ref bean="oracleXADataSource"></ref></constructor-arg>
    </bean>

    <bean id="pool" class="org.apache.commons.pool.impl.GenericObjectPool">
        <property name="maxActive" value="${database.pool.maxSize}"/>
        <property name="minIdle" value="${database.pool.initialSize}"/>
    </bean>

    <bean id="poolableConnectionFactory" class="org.apache.commons.dbcp.PoolableConnectionFactory">
        <constructor-arg name="connFactory" ref="dsXAConnectionFactory"/>
        <constructor-arg name="pool" ref="pool"/>
        <constructor-arg name="stmtPoolFactory"><null></null></constructor-arg>
        <constructor-arg name="validationQuery"><null></null></constructor-arg>
        <constructor-arg name="defaultReadOnly" value="false"/>
        <constructor-arg name="defaultAutoCommit" value="false"/>
    </bean>


    <bean id="dataSource" class="org.apache.commons.dbcp.managed.ManagedDataSource" depends-on="poolableConnectionFactory">
        <constructor-arg name="pool" ref="pool"/>
        <constructor-arg name="transactionRegistry" value="#{dsXAConnectionFactory.getTransactionRegistry()}"/>
    </bean>

I have some concerns about using DBCP pool but for now it is the only working solution.

Upvotes: 1

Related Questions