Search This Blog

Thursday, 4 October 2012

tx:advise

We saw in our earlier posts how working with TransactionProxyFactoryBean resulted in large configuration files. Even with the abstract bean technique we still are dealing with verbose configuration. As of version 2.0. Spring has come up with using advises to manage transactions.
For its new elements Spring has defined a new schema with namespace "http://www.springframework.org/schema/tx". As the technique is based on aspects we have also included Springs AOP namespace.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 

            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context  
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/tx  
            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/aop  
            http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="c3pDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="org.gjt.mm.mysql.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost/trans" />
        <property name="user" value="root" />
        <property name="password" value="root" />
    </bean>


    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="c3pDataSource" />
    </bean>

    <bean id="simplePersonDAO" class="com.data.dao.SimplePersonDAO">
        <property name="jdbcTemplate" ref="jdbcTemplate" />
    </bean>

    <bean id="testTxAdviseClient" class="com.test.TestTxAdviseClient" />

    <!-- transaction-manager default value is transactionManager -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
         <tx:attributes>
            <tx:method name="get*" read-only="true" />
            <tx:method name="test*" propagation="REQUIRED" read-only="false"
                rollback-for="java.lang.RuntimeException" />
        </tx:attributes>
    </tx:advice>

    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="c3pDataSource" />
    </bean>

    <aop:config>
        <aop:pointcut id="testMethods"
            expression="execution(* com.test.TestTxAdviseClient.test*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="testMethods" />
    </aop:config>

</beans>
The initial beans are those that are needed to run the code. The first XML element of interest is the advice element. It specifies the methods that need to be executed in a transactional context The method names are specified as regular expressions while other attributes specify the behaviour for the transaction.
The aspect elements are then used to apply the above advice to specified methods of specific beans. In this case the TestTxAdviseClient bean:
public class TestTxAdviseClient {
    @Autowired
    private IPersonDAO personDAO;
    
    
    public void testPersonLifecycle() {
        //code
    }
    
    public void testPersonForRollback() {
        //code
    }
}

2 comments:

  1. Hi nice post,I need some more info using this aop based transaction.

    1: is it possible i directly use the simplePersonDAO in the regular expressions?

    2: if there are more than one DAO in application then is it possible to make one single element for all the DAO. If not what is the other way.

    Thanks

    ReplyDelete
    Replies
    1. Hi Noman,
      To your first question, yes it is possible to apply transactions directly to the DAO. In fact you can apply it to any bean.
      As for the second question, I didn't quite get it. If you are wondering whether you can use the same advise for multiple beans, it should be doable - make the expression attribute's regular expression more generic. (Never tried it though :) )

      Delete