Announcement Announcement Module
Collapse
No announcement yet.
HELP: jotm standalone w/ JdbcTemplate rollback not working Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HELP: jotm standalone w/ JdbcTemplate rollback not working

    First, let me apologize for the length of this post, but I thought that giving detailed information was the only way anybody might be able to help me. This actually is a very simplified test case.

    I'm having trouble getting proper transaction behavior using the Spring JTA transaction manager in conjunction with JOTM standalone, using XAPool's datasource, and oracle's jdbc driver on a 10g database.

    As far as I understand from reading J2EE w/o EJB and the reference guide and forums, I should be able to use JOTM standalone with the JtaTransactionManager, and when using an XADataSource (XAPool) that is wired to the JtaTransactionManager, the JdbcTemplate should participate in jta-managed transactions automatically.

    My logs seem fine to me, and there is every indication that synchronization is occurring correctly and the the transaction gets rolled back before the connection is closed, but the deleted rows that should have been rolled back do not get rolled back.

    Here are the relevant bean definitions I'm using:

    Code:
    <bean id="appXaDataSource"
        class="org.enhydra.jdbc.oracle.OracleXADataSource" singleton="false" destroy-method="shutdown">
        <property name="transactionManager">
            <ref local="jotm"/>
        </property>     
    </bean>
    <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="userTransaction">
            <ref local="jotm"/>
        </property>
        <property name="transactionManager">
            <ref local="jotm"/>
        </property>
    </bean>
    <bean id="txTestProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="target"><bean class="com.thatone.archie.transactions.TransactionTestor"/></property>
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="delete*">PROPAGATION_REQUIRED,-RuntimeException</prop>
            </props>
        </property>
        <property name="proxyTargetClass"><value>true</value></property>
    </bean>
    The test class that throws the exception contains the following method:

    Code:
        public void deleteWithFailure&#40;JdbcTemplate template, String table, String idColumnName, Object&#91;&#93; ids&#41; &#123;
            final String query = QueryUtils.createDeleteQuery&#40;table, new Object&#91;&#93; &#123;
                ids&#91;0&#93;
            &#125;, idColumnName&#41;;
    
            // delete only the first id, then throw an exception
    
            int rowsAffected = template.update&#40;query&#41;;
            System.out.println&#40;"\t\tDeleted " + rowsAffected + " rows."&#41;;
            assert rowsAffected == 1 &#58; "1 row should have been deleted, not " + rowsAffected;
            System.out.println&#40;"\t\tThrowing exception to check rollback."&#41;;
            throw new RuntimeException&#40;"Throwing exception to check rollback."&#41;;
        &#125;
    The JdbcTemplate that I pass in is created using the datasource constructor, and the datasource object that is passed in is the bean above where id="appXaDataSource". I get it from the context, set its properties, then create the JdbcTemplate, which is then used for the test above.

    The unittest is very simple. It just gets the transaction proxy ("txTestProxy") from the context, counts the rows in a table in 1 transaction, calls deleteWithFailure in a 2nd transaction (passing in the JdbcTemplate and other parameters), and then counts the rows in a 3rd transaction. The result is that 1 row is deleted, even though the logs show that a rollback occurred on the transaction that deleted the row.

    At the risk of giving too much information, here are the log messages I see from when the transaction proxy gets the transaction object until the completion of the transaction in question:

    (First line in each is the message, second line is class and method that logged the message)


    Code:
    Getting transaction for method 'deleteWithFailure' in class &#91;com.thatone.archie.transactions.TransactionTestor&#93;
    org.springframework.transaction.interceptor.TransactionAspectSupport#getTransaction
    
    Current.getStatus&#40;&#41;
    org.objectweb.jotm.Current#getStatus
    
    Creating new transaction
    org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction
    
    Beginning JTA transaction
    org.springframework.transaction.jta.JtaTransactionManager#doBegin
    
    begin transaction
    org.objectweb.jotm.Current#begin
    
    serverName=, ipAddr=0
    org.objectweb.jotm.XidImpl#<init>
    
    new Xid &#40;uuid= 403646f851002&#41;
    org.objectweb.jotm.XidImpl#<init>
    
    xid=bb14111130343033363436663835313030325f305f...0, timeout=60
    org.objectweb.jotm.TransactionImpl#<init>
    
    myXid=bb14111130343033363436663835313030325f305f...0
    org.objectweb.jotm.TransactionImpl#getXid
    
    tx=bb14111130343033363436663835313030325f305f...0
    org.objectweb.jotm.Current#begin
    
    flag=TMJOIN
    org.objectweb.jotm.TransactionImpl#doAttach
    
    number of enlisted=0
    org.objectweb.jotm.TransactionImpl#doAttach
    
    Associate tx to xid &#40;xid=bb14111130343033363436663835313030325f305f...0&#41;
    org.objectweb.jotm.Current#putTxXid
    
    myXid=bb14111130343033363436663835313030325f305f...0
    org.objectweb.jotm.TransactionImpl#getXid
    
    set timer for tx &#40;timer=org.objectweb.jotm.TimerEvent@8d5485, tx=bb14111130343033363436663835313030325f305f...0&#41;
    org.objectweb.jotm.TransactionImpl#setTimer
    
    Initializing transaction synchronization
    org.springframework.transaction.support.TransactionSynchronizationManager#initSynchronization
    
    Executing SQL update &#91;DELETE FROM order_item_details WHERE id IN &#40;'00000000000000000000000000000047'&#41;&#93;
    org.springframework.jdbc.core.JdbcTemplate#update
    
    Opening JDBC connection
    org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
    
    StandardDataSource&#58;getConnection Connection from DriverManager is returned
    org.enhydra.jdbc.util.Logger#debug
    
    Registering transaction synchronization for JDBC connection
    org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
    
    Bound value &#91;org.springframework.jdbc.datasource.ConnectionHolder@193a6a5&#93; for key &#91;&#91;driver=oracle.jdbc.OracleDriver@126f816, url=jdbc&#58;oracle&#58;thin&#58;@//localhost&#58;1521/archie, user=testDb1&#93;&#93; to thread &#91;main&#93;
    org.springframework.transaction.support.TransactionSynchronizationManager#bindResource
    
    Retrieved value &#91;org.springframework.jdbc.datasource.ConnectionHolder@193a6a5&#93; for key &#91;&#91;driver=oracle.jdbc.OracleDriver@126f816, url=jdbc&#58;oracle&#58;thin&#58;@//localhost&#58;1521/archie, user=testDb1&#93;&#93; bound to thread &#91;main&#93;
    org.springframework.transaction.support.TransactionSynchronizationManager#getResource
    
    SQL update affected 1 rows
    org.springframework.jdbc.core.JdbcTemplate$1UpdateStatementCallback#doInStatement
    
    Retrieved value &#91;org.springframework.jdbc.datasource.ConnectionHolder@193a6a5&#93; for key &#91;&#91;driver=oracle.jdbc.OracleDriver@126f816, url=jdbc&#58;oracle&#58;thin&#58;@//localhost&#58;1521/archie, user=testDb1&#93;&#93; bound to thread &#91;main&#93;
    org.springframework.transaction.support.TransactionSynchronizationManager#getResource
    
    Applying rules to determine whether transaction should rollback on java.lang.RuntimeException&#58; Throwing exception to check rollback.
    org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn
    
    Winning rollback rule is&#58; RollbackRule with pattern &#91;RuntimeException&#93;
    org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn
    
    Invoking rollback for transaction on method 'deleteWithFailure' in class &#91;com.thatone.archie.transactions.TransactionTestor&#93; due to throwable &#91;java.lang.RuntimeException&#58; Throwing exception to check rollback.&#93;
    org.springframework.transaction.interceptor.TransactionAspectSupport#doCloseTransactionAfterThrowing
    
    Triggering beforeCompletion synchronization
    org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerBeforeCompletion
    
    Removed value &#91;org.springframework.jdbc.datasource.ConnectionHolder@193a6a5&#93; for key &#91;&#91;driver=oracle.jdbc.OracleDriver@126f816, url=jdbc&#58;oracle&#58;thin&#58;@//localhost&#58;1521/archie, user=testDb1&#93;&#93; from thread &#91;main&#93;
    org.springframework.transaction.support.TransactionSynchronizationManager#unbindResource
    
    Closing JDBC connection
    org.springframework.jdbc.datasource.DataSourceUtils#doCloseConnectionIfNecessary
    
    Initiating transaction rollback
    org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback
    
    Rolling back JTA transaction
    org.springframework.transaction.jta.JtaTransactionManager#doRollback
    
    Current.rollback&#40;&#41;
    org.objectweb.jotm.Current#rollback
    
    TransactionImpl.rollback&#40;&#41;
    org.objectweb.jotm.TransactionImpl#rollback
    
    myXid=bb14111130343033363436663835313030325f305f...0
    org.objectweb.jotm.TransactionImpl#getXid
    
    unset timer for tx &#40;timer=org.objectweb.jotm.TimerEvent@8d5485, tx=bb14111130343033363436663835313030325f305f...0&#41;
    org.objectweb.jotm.TransactionImpl#unsetTimer
    
    Triggering afterCompletion synchronization
    org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerAfterCompletion
    
    Clearing transaction synchronization
    org.springframework.transaction.support.TransactionSynchronizationManager#clearSynchronization
    I'm hoping somebody who has worked with JOTM/JTA and Spring (best of all would be Oracle too) could sanity check my setup above and see if anything obvious is wrong.

    Thanks very much for any pointers.

    -calvin

  • #2
    I'm trying to do a similar thing but using Hibernate to do the bulk delete... Did yiu figure it out what's happening ?

    Comment


    • #3
      The Datasource must be a JNDI bound datasource exposed by the application server then only it will participate in the a JTA Transaction...

      Comment


      • #4
        Originally posted by pagipunit View Post
        The Datasource must be a JNDI bound datasource exposed by the application server then only it will participate in the a JTA Transaction...
        Did anyone find the solution? We have a similar issues with using a JNDI bound datasource (weblogic) together with JDBCTemplate.

        It looks as though the JDBCTemplate is doing the operation on a different connection which doesn't get rolled back when the transaction is rolled back

        Comment

        Working...
        X