Monday, August 30, 2010

Declarative Transaction Defintion With Spring

In the current project i was working we were using spring 2.0 and was declaring transactions the old way using a ProxyFactoryBean and injecting the transaction interceptor to the Proxy. Although this works fine it just clutters your spring configuration IMO. Recently we migrated our application to Spring 3.0 and i thought we should move away from the old ways of doing things with Spring. Following i show you the old way of how we did transaction injection and the new way of doing it with less XML configuration.

First of all i present the OLD WAY:

<bean name="transactionInterceptor"
  class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
   <ref bean="transactionManager" />
  </property>
  <property name="transactionAttributes">
   <props>
    <prop key="create*">PROPAGATION_REQUIRED</prop>
    <prop key="remove*">PROPAGATION_REQUIRED</prop>
    <prop key="*">PROPAGATION_SUPPORTS,readOnly
    </prop>
   </props>
  </property>
 </bean>


 <bean id="myTestDAOTarget" class="com.test.dao.hibernate.MyTestDAOImpl" scope="prototype">
         <property name="sessionFactory">
            <ref local="mySessionFactory"/>
        </property>
    </bean>

    <bean id="myTestDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="proxyInterfaces">
            <value>com.test.dao.MyTestDAO</value>
        </property>
        <property name="interceptorNames">
         <list>
          <value>transactionInterceptor</value>
          <value>myTestDAOTarget</value>
            </list>            
        </property>
    </bean>


As you can see here we have defined the transaction interceptor and injected the same within our myTestDAOProxy bean definition under the "interceptorNames" property. The thing with this is if you want to define a new DAO you have to define two bean definitions because we are dealing with proxying manually. Ofcourse we can write an XDoclet to generate this. But then again what we are trying to achieve is clarity.

So now i present the NEW way of doing the same with less code;

<?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:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
 xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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
    http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
    
    
    <aop:aspectj-autoproxy />

  <tx:advice id="tx-advice">
  <tx:attributes>
   <tx:method name="create*" propagation="REQUIRED" />
   <tx:method name="remove*" propagation="REQUIRED" />
   <tx:method name="update*" propagation="REQUIRED" />
   <tx:method name="*" propagation="SUPPORTS"/>
  </tx:attributes>
 </tx:advice>

 <aop:config>

  <aop:pointcut id="advice" expression="target(com.test.dao.MyTestDAO)" />
   <aop:advisor pointcut-ref="advice" advice-ref="tx-advice" />

 </aop:config>

 <bean id="myTestDAO" class="com.test.dao.hibernate.MyTestDAOImpl" scope="prototype">
         <property name="sessionFactory">
            <ref local="mySessionFactory"/>
        </property>
    </bean>


</beans>

Thats it. Now the proxy is created for you automatically. One thing to note hear is i have given the AOP expression as target(com.test.dao.MyTestDAO). What this tells is to weave into any class that implements the interface 'MyTestDAO'. You can of course have a BaseDAO in your DAO layer code so that you can specify that in this place which will enable to you to inject transaction capabilities to all your DAO classes.

Thats all folks. If you have any queries or suggestions pls do drop a comment which is always highly appreciated.