Tuesday, December 15, 2009

How to configure Global/Default Interceptor in Struts 2

Global/Default interceptor means to me like the interceptor would be applied to the entire action classes may span accross mutiple packages.

Step 1: Create an interceptor
Step 2: Register the interceptor in interceptors tag.
Step 3: Create an interceptor stack having all the necessary references to the interceptors
Step 4: If there are multiple packages are involved then put the interceptor in the common package and
all other packages would extend it.

For Example:

<struts>
<package name="base-package" extends="struts-default">

<interceptors>
<!-- interceptor used to initialize resource used through out the application-->
<interceptor name="ResourceInit" class="com.test.ResourceInitInterceptor"/>

<!-- interceptor stack composes struts provided interceptors and custody related-->
<interceptor-stack name="base-default-stack">
<interceptor-ref name="ResourceInit"/>
<!-- "defaultStack" defined in struts in struts-default.xml-->
<interceptor-ref name="defaultStack"/>
</interceptor-stack>

</interceptors>

<!-- Default interceptor executed for the entire actions -->
<default-interceptor-ref name="base-default-stack"/>
</package>

<include file="/com/struts_config/struts_module_1.xml" />
<include file="/com/struts_config/struts_module_2.xml" />

</struts>

Note: struts_module_1 and struts_module_2 must extends "base-package"

Sunday, December 13, 2009

XA-DataSource and Non-XA Datasource in Global Transaction

Datasource - XA datasource is a data source that can participate in an XA global transaction.

Non-XA Datasource - Non-XA datasource generally can't participate in a global transaction.

An XA transaction, in the most general terms, is a "global transaction" that may span multiple resources. A non-XA transaction always involves just one resource.

An XA transaction involves a coordinating transaction manager, with one or more databases (or other resources, like JMS) all involved in a single global transaction. Non-XA transactions have no transaction coordinator, and a single resource is doing all its transaction work itself (this is sometimes called local transactions).

When the implementation code surrounded/enclosed by the global (XA) transaction then the entire code must be treated as unit irrespective of number of datasource(s) are involved in the unit. Therefore when you say "commit", the results are committed across all of the resources and when you say "rollback", _everything_ is rolled back across all resources (XA-Enabled Datasource).

If there are non-xa enabled datasource surrounded by global transaction (XA transaction) then it does not participate in the transaction therefore operation associated to the non-xa datasource has to be committed or rollback manually. As
J2EE Specification says that transaction can not be nested here there must not be opened separate transaction for non-xa datasource inside the global transaction. Non-XA datasource is a local datasource which can be commit/rollback without using any transaction boundary for it.

How to configure Global Transaction using Spring AOP:

Add the following configuration in the applicationContext.xml file:

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

<bean id="txManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="javax.transaction.TransactionManager" />
</bean>


<!-- the transactional advice -->
<tx:advice id="defaultTxAdvice" transaction-manager="txManager">
<!--the transactional semantics...-->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true" />
<!-- other methods use the default transaction settings -->
<tx:method name="*" rollback-for="List Checked Business Exception separated by comma" />
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="com.test.operations"
expression="execution(* com.test.service.ServiceImpl.*(..))" />
<aop:advisor advice-ref="defaultTxAdvice" pointcut-ref="com.test.operations" />
</aop:config>

</beans>

Note: If applicaton server Transaction manager specific selected then just change JtaTransactionManager to their respective classes for example for weblogic it's "org.springframework.transaction.jta.WeblogicJtaTransactionManager"

Special configuration for JTA having more that 30 Seconds timeout:
i. Set Timeout to 180 seconds (if plans ) during DataSource Configuration
ii. Goto JTA > Set 180 seconds timeout and restart the app server to be effective.