Results 1 to 3 of 3

Thread: Transaction Problem

  1. #1
    Join Date
    May 2005
    Posts
    8

    Default Transaction Problem

    I am having some issues using Spring's declarative transaction features. I've created what I thought would be a farily simple example just to get my head around some of Spring's features. But I can't seem to get the transaction manager to work correctly.

    Here is my Spring setup:

    Code:
        <!-- struts actions -->
        <bean name="/getAccounts" class="com.pdsisoft.GetAccountsAction">
            <property name="account">
                <ref bean="account"/>
            </property>
        </bean>
        
        <!-- Business Tier Objects -->
        <bean id="accountTarget" class="com.pdsisoft.AccountImpl">
            <property name="dataSource">
                <ref local="dataSource"/>
            </property>
        </bean>
        <bean id="account" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
            <property name="target">
                <ref local="accountTarget"/>
            </property>
            <property name="transactionAttributes">
                <props>
                    <prop key="updateTestTables*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                </props>
            </property>
        </bean>
    
        <!-- Our transaction manager -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource">
                <ref local="dataSource"/>
            </property>
        </bean>
    
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName">
                <value>com.informix.jdbc.IfxDriver</value>
    	</property>
    	<property name="url">
                <value>&#91;ommitted&#93;</value>
    	</property>
    	<property name="username">
                <value>&#91;ommitted&#93;</value>
    	</property>
    	<property name="password">
                <value>&#91;ommitted&#93;</value>
    	</property>
        </bean>
    My code for the Account business object has three methods that are fairly trivial:

    Code:
        public void updateTestTables&#40;&#41; &#123;
            this.updateTestTableOne&#40;&#41;;
            this.updateTestTableTwo&#40;&#41;;
            int i = 5 / 0;
        &#125;
        
        public void updateTestTableOne&#40;&#41; &#123;
            Connection conn = null;
            PreparedStatement ps = null;
            try &#123;
                conn = dataSource.getConnection&#40;&#41;;
                ps = conn.prepareStatement&#40;"update test_tbl set test_dt = ? where test_no_in = 1"&#41;;
                ps.setTimestamp&#40;1, new java.sql.Timestamp&#40; System.currentTimeMillis&#40;&#41; &#41;&#41;;
                ps.executeUpdate&#40;&#41;;
            &#125;
            catch&#40;Exception e&#41; &#123;
                e.printStackTrace&#40;&#41;;
            &#125;
            finally &#123;
                try &#123; ps.close&#40;&#41;; &#125;catch&#40;Exception d&#41;&#123;&#125;;
                try &#123; conn.close&#40;&#41;; &#125;catch&#40;Exception d&#41;&#123;&#125;;
            &#125;
        &#125;
        
        public void updateTestTableTwo&#40;&#41; &#123;
            Connection conn = null;
            PreparedStatement ps = null;
            try &#123;
                conn = dataSource.getConnection&#40;&#41;;
                ps = conn.prepareStatement&#40;"update test2_tbl set test_dt = ? where test_no_in = 1"&#41;;
                ps.setTimestamp&#40;1, new java.sql.Timestamp&#40; System.currentTimeMillis&#40;&#41; &#41;&#41;;
                ps.executeUpdate&#40;&#41;;
            &#125;
            catch&#40;Exception e&#41; &#123;
                e.printStackTrace&#40;&#41;;
            &#125;
            finally &#123;
                try &#123; ps.close&#40;&#41;; &#125;catch&#40;Exception d&#41;&#123;&#125;;
                try &#123; conn.close&#40;&#41;; &#125;catch&#40;Exception d&#41;&#123;&#125;;
            &#125;
        &#125;
    I have thus wrapped updateTestTables in a transaction, and would expect the two table updates to be rolled back when I purposefully throw the ArithmaticException as my final line of code in that method. But both updates go through and are not rolled back when the exception is thrown.

    I then tried modifying the TransactionProxyFactory to this:

    Code:
        <bean id="account" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
            <property name="target">
                <ref local="accountTarget"/>
            </property>
            <property name="transactionAttributes">
                <props>
                    <prop key="updateTestTables*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                    <prop key="updateTestTableOne*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                    <prop key="updateTestTableTwo*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
                </props>
            </property>
        </bean>
    But it still did not work. Interestingly enough the following output is generated from Tomcat when I run the test:

    Code:
    May 23, 2005 6&#58;00&#58;23 PM org.springframework.jdbc.datasource.JdbcTransactionObjec
    tSupport <clinit>
    INFO&#58; JDBC 3.0 Savepoint class is available
    May 23, 2005 6&#58;00&#58;23 PM org.apache.struts.action.RequestProcessor processExcepti
    on
    WARNING&#58; Unhandled Exception thrown&#58; class java.lang.ArithmeticException
    This would seem to suggest to me that the Transaction is being created before my exception is purposefully thrown, but for some reason the updates are not being rolled back.

    Any help would be appreciated.

    Thanks

  2. #2
    Join Date
    Aug 2004
    Location
    Hong Kong
    Posts
    26

    Default

    Time to let go the habit of dataSource.getConnection()!

    You can read more about how to let Spring to handle all these using DataSourceUtils, just scroll down to near the end of section 7.2:
    http://static.springframework.org/sp...n.html#d0e4501

    Of course, it is even easier to use Spring JDBC abstraction, i.e. JdbcTemplate:
    http://static.springframework.org/sp...ence/jdbc.html

    Lawrence

  3. #3
    Join Date
    May 2005
    Posts
    8

    Default

    That did the trick! I used the DataSourceUtils class and all my connections were enlisted in the transaction and rolled back successfully. Since I will be using the JDBCTemplate class, which hides all of this connection retrieval and releasing for you, this wont be a problem. But its good to know how to use it just in case.

    Thanks again.

Similar Threads

  1. Unit testing with JOTM and JtaTransactionManager
    By lalle in forum Architecture
    Replies: 1
    Last Post: Oct 15th, 2005, 09:05 AM
  2. Replies: 0
    Last Post: Jun 6th, 2005, 06:22 AM
  3. Replies: 3
    Last Post: Nov 19th, 2004, 07:16 PM
  4. Replies: 2
    Last Post: Oct 23rd, 2004, 01:53 PM
  5. Transaction pb Hibernate/MySQL
    By syluser in forum Data
    Replies: 2
    Last Post: Aug 28th, 2004, 02:40 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •