Announcement Announcement Module
Collapse
No announcement yet.
Distributed Transaction in Standalone Application Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Distributed Transaction in Standalone Application

    Hi,

    I am developing a standalone Java application using Oracle. In order to have distributed transaction, I looked up a JTA transaction manager from WebLogic server and bind the data source to it. Shown below is the configuration:

    <bean id="dataSourceAbstract" class="javax.sql.DataSource" abstract="true">
    <property name="driverClassName">
    <value>${jdbc.driverClassName}</value>
    </property>
    <property name="url">
    <value>${jdbc.url}</value>
    </property>
    <property name="username">
    <value>${jdbc.username}</value>
    </property>
    <property name="password">
    <value>${jdbc.password}</value>
    </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    lazy-init="true" parent="dataSourceAbstract">

    </bean>

    <bean id="transactionManager"
    class="org.springframework.transaction.jta.JtaTran sactionManager">
    <property name="jndiTemplate">
    <ref bean="jndiTemplate" />
    </property>
    </bean>

    <bean id="txProxyTemplate" abstract="true"
    class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager">
    <ref bean="transactionManager" />
    </property>
    <property name="transactionAttributes">
    <props>
    <prop key="*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>

    <bean id="customerContractCache" parent="txProxyTemplate" singleton="true">
    <property name="target">
    <bean class="foo.Test">
    <property name="clientManager">
    <ref bean="clientManager" />
    </property>
    </property>
    </bean>

    <bean id="clientManager" parent="txProxyTemplate" singleton="true">
    <property name="target">
    <bean class="foo.clientManagerImpl">
    <property name="clientDAO">
    <ref bean="clientDAO" />
    </property>
    </property>
    </bean>

    <bean id="sqlMapClient"
    class="org.springframework.orm.ibatis.SqlMapClient FactoryBean">
    <property name="configLocation">
    <value>
    classpath:/foo/sql-map-config.xml
    </value>
    </property>
    </bean>

    <bean id="clientDAO"
    class="foo.ClientDAOImpl">
    <property name="dataSource">
    <ref bean="dataSource" />
    </property>
    <property name="sqlMapClient">
    <ref bean="sqlMapClient" />
    </property>
    </bean>


    However, I found that transaction is committed each time function in foo.Test is executed. Even thought a RuntimeException was thrown intentionally at the end of a function, transaction is not rollback.

    I would like to know what's wrong with the configuration?

    Thanks.

    Regards,
    Koala Lam

  • #2
    You are trying to use a local datasource with jta transaction manager, and that can't work. You need to use XADatasource, XA capable driver and XA capable db server.

    Comment


    • #3
      Koala, this topic has been discussed quite a lot on the forum - search for JTA and distribution transactions and you'll find plenty of posts.

      Comment


      • #4
        Hi Koala

        This section of the Spring reference documentation, although quite small, does state the relationship between the DataSource and the concrete PlatformTransactionManager type.

        Cheers
        Rick

        Comment


        • #5
          Hi,

          I am actually using a XADataSource. Shown below is the JDBC configuration which is loaded using a PropertyPlaceholderConfigurer:

          jdbc.driverClassName=oracle.jdbc.xa.client.OracleX ADataSource
          jdbc.url=jdbc:oracle:thin:@192.168.88.229:1521:tes t3
          jdbc.username=test
          jdbc.password=test

          The log shows that transaction is rollback, however, changes are indeed committed:

          2006-10-18 11:21:21,222 [main] DEBUG org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute.rollbackOn(119) - Applying rules to determine whether transaction should rollback on java.lang.RuntimeException
          2006-10-18 11:21:21,222 [main] DEBUG org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute.rollbackOn(137) - Winning rollback rule is: null
          2006-10-18 11:21:21,222 [main] DEBUG org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute.rollbackOn(143) - No relevant rollback rule found: applying superclass default
          2006-10-18 11:21:21,222 [main] DEBUG org.springframework.transaction.interceptor.Transa ctionInterceptor.doCloseTransactionAfterThrowing(2 81) - Invoking rollback for transaction on foo.Test.test due to throwable [java.lang.RuntimeException]
          2006-10-18 11:21:21,222 [main] DEBUG org.springframework.transaction.jta.JtaTransaction Manager.processRollback(588) - Participating transaction failed - marking existing transaction as rollback-only
          2006-10-18 11:21:21,222 [main] DEBUG org.springframework.transaction.jta.JtaTransaction Manager.doSetRollbackOnly(819) - Setting JTA transaction rollback-only
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute.rollbackOn(119) - Applying rules to determine whether transaction should rollback on java.lang.RuntimeException
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute.rollbackOn(137) - Winning rollback rule is: null
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.interceptor.RuleBa sedTransactionAttribute.rollbackOn(143) - No relevant rollback rule found: applying superclass default
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.interceptor.Transa ctionInterceptor.doCloseTransactionAfterThrowing(2 81) - Invoking rollback for transaction on foo.Test.test.test2 due to throwable [java.lang.RuntimeException]
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.jta.JtaTransaction Manager.triggerBeforeCompletion(673) - Triggering beforeCompletion synchronization
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.support.Transactio nSynchronizationManager.unbindResource(185) - Removed value [org.springframework.jdbc.datasource.ConnectionHold er@39474b] for key [org.apache.commons.dbcp.BasicDataSource@1696452] from thread [main]
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.jdbc.datasource.DataSourceUtil s.doReleaseConnection(285) - Returning JDBC Connection to DataSource
          2006-10-18 11:21:21,237 [main] DEBUG org.springframework.transaction.jta.JtaTransaction Manager.processRollback(581) - Initiating transaction rollback
          2006-10-18 11:21:21,253 [main] DEBUG org.springframework.transaction.jta.JtaTransaction Manager.triggerAfterCompletion(697) - Triggering afterCompletion synchronization
          2006-10-18 11:21:21,253 [main] DEBUG org.springframework.transaction.support.Transactio nSynchronizationManager.clearSynchronization(265) - Clearing transaction synchronization

          Thanks.

          Regards,
          Koala Lam

          Comment


          • #6
            What you are using is a XA driver, not a datasource. The datasource is DBCP and it's not XA. I suggest you download JOTM and give it a spin.

            Comment


            • #7
              Hi,

              Thanks for your information. However, what about if I want to use transaction manager from J2EE container (in my case, the WebLogic Server)? What I need is a XA DataSource, right ? So, where can I find an open source XA DataSource? Is XAPool from ObjectWeb is a good choice?

              Thanks a lot.

              Regards,
              Koala Lam

              Comment


              • #8
                XAPool is the implementation that's used by JOTM. Will it work with Weblogic JTA or not is hard to say.

                Comment


                • #9
                  Hi,

                  I have tried using XAPool with JTA looked up from WebLogic Server as well as JOTM. In both cases, I got the following strange behavior:

                  2006-10-18 18:23:29,636 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - StandardPoolDataSource:getConnection
                  2006-10-18 18:23:29,636 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - StandardPoolDataSource:getConnection must configure the pool...
                  2006-10-18 18:23:29,636 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - StandardXADataSource:getXAConnection(user, password)
                  2006-10-18 18:23:29,698 [main] ERROR org.enhydra.jdbc.xapool.error(55) - Error Exception in GenericPool:start java.sql.SQLException: Error trying to load driver: oracle.jdbc.xa.client.OracleXADataSource : null
                  2006-10-18 18:23:29,698 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - StandardXADataSource:getXAConnection(user, password)
                  2006-10-18 18:23:29,698 [main] ERROR org.enhydra.jdbc.xapool.error(55) - Error Exception in GenericPool:start java.sql.SQLException: Error trying to load driver: oracle.jdbc.xa.client.OracleXADataSource : null
                  2006-10-18 18:23:29,698 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - GenericPool:start pool started
                  2006-10-18 18:23:29,698 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - StandardPoolDataSource:getConnection pool config :
                  GenericPool:
                  num of element =<2>
                  minSize =<2>
                  maxSize =<2>
                  lifeTime =<600000>
                  ngeneration =<1>
                  getLockedObjectCount() =<0>
                  getUnlockedObjectCount() =<0>
                  getDeadLockMaxWait() =<300000>
                  getDeadLockRetryWait() =<10000>
                  Unlocked pool:
                  Locked pool:

                  2006-10-18 18:23:29,698 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - StandardPoolDataSource:getConnection Try to give a connection (checkOut)
                  2006-10-18 18:23:29,714 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - GenericPool:checkOut an object
                  2006-10-18 18:23:29,714 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - GenericPool:checkOut UnlockedObjectCount=0
                  2006-10-18 18:23:29,714 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - GenericPool:checkOut LockedObjectCount=0
                  2006-10-18 18:23:29,714 [main] DEBUG org.enhydra.jdbc.xapool.debug(37) - GenericPool:checkOut count=2 maxSize=2
                  2006-10-18 18:23:29,714 [main] INFO org.enhydra.jdbc.xapool.info(43) - GenericPool:checkOut waiting for an object :StandardXAPoolDataSource:
                  StandardXADataSource:
                  connection count=<0>
                  number of dead connection=<0>
                  dead lock max wait=<300000>
                  dead lock retry wait=<10000>
                  driver name=<oracle.jdbc.xa.client.OracleXADataSource>
                  number of *free* connections=<0>
                  max con=<0>
                  min con=<50>
                  prepared stmt cache size=<16>
                  transaction manager=<org.objectweb.jotm.Current@13a34af>
                  xid connection size=<0>
                  StandardConnectionPoolDataSource:
                  master prepared stmt cache size=<0>
                  prepared stmt cache size =<16>
                  StandardDataSource:
                  driver=<null>
                  url=<jdbc:oracle:thin:@192.168.88.229:1521:test>
                  user=<null>
                  CoreDataSource :
                  debug =<false>
                  description =<null>
                  login time out =<60>
                  user =<null>
                  verbose =<false>
                  StandardPoolDataSource:
                  data source name=<null>
                  jdbc test stmt=<null>
                  user=<test>
                  GenericPool:
                  num of element =<2>
                  minSize =<2>
                  maxSize =<2>
                  lifeTime =<600000>
                  ngeneration =<1>
                  getLockedObjectCount() =<0>
                  getUnlockedObjectCount() =<0>
                  getDeadLockMaxWait() =<300000>
                  getDeadLockRetryWait() =<10000>
                  Unlocked pool:
                  Locked pool:

                  2006-10-18 18:23:39,714 [main] INFO org.enhydra.jdbc.xapool.info(43) - GenericPool:checkOut waiting for an object :StandardXAPoolDataSource:
                  StandardXADataSource:
                  connection count=<0>
                  number of dead connection=<0>
                  dead lock max wait=<300000>
                  dead lock retry wait=<10000>
                  driver name=<oracle.jdbc.xa.client.OracleXADataSource>
                  number of *free* connections=<0>
                  max con=<0>
                  min con=<50>
                  prepared stmt cache size=<16>
                  transaction manager=<org.objectweb.jotm.Current@13a34af>
                  xid connection size=<0>
                  StandardConnectionPoolDataSource:
                  master prepared stmt cache size=<0>
                  prepared stmt cache size =<16>
                  StandardDataSource:
                  driver=<null>
                  url=<jdbc:oracle:thin:@192.168.88.229:1521:bmtp3>
                  user=<null>
                  CoreDataSource :
                  debug =<false>
                  description =<null>
                  login time out =<60>
                  user =<null>
                  verbose =<false>
                  StandardPoolDataSource:
                  data source name=<null>
                  jdbc test stmt=<null>
                  user=<test>
                  GenericPool:
                  num of element =<2>
                  minSize =<2>
                  maxSize =<2>
                  lifeTime =<600000>
                  ngeneration =<1>
                  getLockedObjectCount() =<0>
                  getUnlockedObjectCount() =<0>
                  getDeadLockMaxWait() =<300000>
                  getDeadLockRetryWait() =<10000>
                  Unlocked pool:
                  Locked pool:

                  And my program turns out to be never end. Shown below is the new configuration:

                  <bean id="jotm" name="jtaTransactionManager" class="org.springframework.transaction.jta.JotmFac toryBean">
                  </bean>

                  <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTran sactionManager" lazy-init="false">
                  <property name="userTransaction"><ref local="jotm"/></property>
                  </bean>

                  <bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSou rce" destroy-method="shutdown">
                  <property name="transactionManager" ref="jotm"/>
                  <property name="driverName">
                  <value>${jdbc.driverClassName}</value>
                  </property>
                  <property name="url">
                  <value>${jdbc.url}</value>
                  </property>
                  </bean>

                  <bean id="dataSource_XAPool"
                  class="org.enhydra.jdbc.pool.StandardXAPoolDataSou rce"
                  destroy-method="shutdown">
                  <property name="dataSource" ref="innerDataSource"/>
                  <property name="user">
                  <value>${jdbc.username}</value>
                  </property>
                  <property name="password">
                  <value>${jdbc.password}</value>
                  </property>
                  <property name="maxSize" value="2"/>
                  </bean>

                  Still, I am using XA JDBC driver "oracle.jdbc.xa.client.OracleXADataSource".

                  Thanks a lot.

                  Regards,
                  Koala Lam

                  Comment


                  • #10
                    No idea really, but the error seems to be:

                    2006-10-18 18:23:29,698 [main] ERROR org.enhydra.jdbc.xapool.error(55) - Error Exception in GenericPool:start java.sql.SQLException: Error trying to load driver: oracle.jdbc.xa.client.OracleXADataSource : null

                    Comment


                    • #11
                      Hello,

                      I tried to do the same some time ago and I noticed I have to specify user/pass in both the innerDS and the Pool:

                      Code:
                      <bean id="jotm"
                      		class="org.springframework.transaction.jta.JotmFactoryBean" />
                      
                      	<bean id="transactionManager"
                      		class="org.springframework.transaction.jta.JtaTransactionManager">
                      		<property name="userTransaction" ref="jotm" />
                      	</bean>
                      
                      	<bean id="oracleDataSource"
                      		class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"
                      		destroy-method="shutdown">
                      		<property name="dataSource" ref="innerOracleDataSource" />
                      		<property name="minSize" value="2" />
                      		<property name="maxSize" value="5" />
                      		<property name="user" value="${username}" />
                      		<property name="password" value="${password}" />
                      
                      	</bean>
                      
                      	<bean id="innerOracleDataSource"
                      		class="org.enhydra.jdbc.standard.StandardXADataSource"
                      		destroy-method="shutdown">
                      		<property name="transactionManager" ref="jotm" />
                      		<property name="driverName" value="${jdbcDriverClass}" />
                      		<property name="url" value="${jdbcUrl}" />
                      		<property name="user" value="${username}" />
                      		<property name="password" value="${password}" />
                      	</bean>
                      Perhaps this will solve your problem...

                      -Patrick

                      Comment


                      • #12
                        config example

                        Hi,
                        Im trying to use spring + ibatis in a jta transaction. I got some doubts about the spring config file (dao config + datasource etc). Does anyone can send a spring config example?

                        tks!

                        Comment


                        • #13
                          See the petclinic/jpetstore example from the main Spring distribution. They indicate how to properly configure the datasource and ibatis. For configuring the datasource against the JTA manager you have to look at the TM documentation.
                          Beside JOTM (you can find several examples on this forum also) I recommend you look at Atomikos which has recently been open-sourced.

                          Comment


                          • #14
                            Originally posted by koalalam View Post
                            Hi,

                            I am developing a standalone Java application using Oracle. In order to have distributed transaction, I looked up a JTA transaction manager from WebLogic server and bind the data source to it. ...
                            Do you use separate connect for each participating database or you connect to a single database and access other participating databases over DBLinks
                            from database to which you connect?

                            In latter case you need not to mess-up with JTA transaction manager, XA datasources etc.

                            Use any datasource of your choice (pooled or unpooled, depending on your application needs) and plain DataSourceTransactionManager. Oracle will deal with distribution transactions absolutely transparently for you.

                            Regards,
                            Oleksandr

                            Comment


                            • #15
                              Did you ever find a way to do standalone application that requires distributed transaction ? We have a similar requirement and are trying to use jta from weblogic server but having problems.

                              Comment

                              Working...
                              X