If you want to influence the way a transactional client creates new transactions, you can do so by specifying a transaction policy for it. In particular, Spring transaction policies enable you to specify a propagation behavior for your transaction. For example, if a transactional client is about to create a new transaction and it detects that a transaction is already associated with the current thread, should it go ahead and create a new transaction, suspending the old one? Or should it simply let the existing transaction take over? These kinds of behavior are regulated by specifying the propagation behavior on a transaction policy.
Transaction policies are instantiated as beans in Spring XML. You can then
reference a transaction policy by providing its bean ID as an argument to the
transacted()
DSL command. For example, if you want to initiate
transactions subject to the behavior, PROPAGATION_REQUIRES_NEW
, you
could use the following route:
from("file:src/data?noop=true") .transacted("PROPAGATION_REQUIRES_NEW") .beanRef("accountService","credit") .beanRef("accountService","debit") .to("file:target/messages");
Where the PROPAGATION_REQUIRES_NEW
argument specifies the bean ID of
a transaction policy bean that is configured with the
PROPAGATION_REQUIRES_NEW
behavior (see Example 5.1).
Fuse Mediation Router lets you define Spring transaction policies using the
org.apache.camel.spring.spi.SpringTransactionPolicy
class (which is
essentially a wrapper around a native Spring class). The
SpringTransactionPolicy
class encapsulates two pieces of
data:
A reference to a transaction manager (of
PlatformTransactionManager
type).A propagation behavior.
For example, you could instantiate a Spring transaction policy bean with
PROPAGATION_MANDATORY
behavior, as follows:
<beans ...> <bean id="PROPAGATION_MANDATORY "class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_MANDATORY"/> </bean> ... </beans>
The following propagation behaviors are supported by Spring (where these values were originally modelled on the propagation behaviors supported by J2EE):
PROPAGATION_MANDATORY
Support a current transaction; throw an exception if no current transaction exists.
PROPAGATION_NESTED
Execute within a nested transaction if a current transaction exists, else behave like
PROPAGATION_REQUIRED
.Note Nested transactions are not supported by all transaction managers.
PROPAGATION_NEVER
Do not support a current transaction; throw an exception if a current transaction exists.
PROPAGATION_NOT_SUPPORTED
Do not support a current transaction; rather always execute non-transactionally.
Note This policy requires the current transaction to be suspended, a feature which is not supported by all transaction managers.
PROPAGATION_REQUIRED
(Default) Support a current transaction; create a new one if none exists.
PROPAGATION_REQUIRES_NEW
Create a new transaction, suspending the current transaction if one exists.
Note Suspending transactions is not supported by all transaction managers.
PROPAGATION_SUPPORTS
Support a current transaction; execute non-transactionally if none exists.
Example 5.1 shows how to define transaction policy beans for all of the supported propagation behaviors. For convenience, each of the bean IDs matches the specified value of the propagation behavior value, but in practice you can use whatever value you like for the bean IDs.
Example 5.1. Transaction Policy Beans
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> ... <bean id="PROPAGATION_MANDATORY "class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_MANDATORY"/> </bean> <bean id="PROPAGATION_NESTED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_NESTED"/> </bean> <bean id="PROPAGATION_NEVER" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_NEVER"/> </bean> <bean id="PROPAGATION_NOT_SUPPORTED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_NOT_SUPPORTED"/> </bean> <!-- This is the default behavior. --> <bean id="PROPAGATION_REQUIRED" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> </bean> <bean id="PROPAGATION_REQUIRES_NEW" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/> </bean> <bean id="PROPAGATION_SUPPORTS" class="org.apache.camel.spring.spi.SpringTransactionPolicy"> <property name="transactionManager" ref="txManager"/> <property name="propagationBehaviorName" value="PROPAGATION_SUPPORTS"/> </bean> </beans>
![]() | Tip |
---|---|
If you want to paste any of these bean definitions into your own Spring XML
configuration, remember to customize the references to the transaction manager.
That is, replace references to |
A simple way of demonstrating that transaction policies have some effect on a
transaction is to insert a PROPAGATION_NEVER
policy into the middle of
an existing transaction, as shown in the following route:
from("file:src/data?noop=true") .transacted() .beanRef("accountService","credit") .transacted("PROPAGATION_NEVER") .beanRef("accountService","debit");
Used in this way, the PROPAGATION_NEVER
policy inevitably aborts
every transaction, leading to a transaction rollback. You should easily be able to
see the effect of this on your application.
![]() | Note |
---|---|
Remember that the string value passed to |
The preceding route can be also be defined in Spring XML, as follows:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ... > <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="file:src/data?noop=true"/> <transacted/> <bean ref="accountService" method="credit"/> <transacted ref="PROPAGATION_NEVER"/> <bean ref="accountService" method="debit"/> </route> </camelContext> </beans>