camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > Transactional Client
Date Thu, 29 Sep 2011 10:56:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CAMEL&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CAMEL/Transactional+Client">Transactional Client</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~davsclaus">Claus Ibsen</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >{code} <br> <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">h4. OSGi Blueprint <br> <br>If you are using [OSGi Blueprint|Using OSGi blueprint with Camel] then you most likely have to explicit declare a policy and refer to the policy from the transacted in the route. <br>{code:xml} <br>  &lt;bean id=&quot;required&quot; class=&quot;org.apache.camel.spring.spi.SpringTransactionPolicy&quot;&gt; <br>    &lt;property name=&quot;transactionManager&quot; ref=&quot;jmsTransactionManager&quot;/&gt; <br>    &lt;property name=&quot;propagationBehaviorName&quot; value=&quot;PROPAGATION_REQUIRED&quot;/&gt; <br>  &lt;/bean&gt; <br>{code} <br> <br>And then refer to &quot;required&quot; from the route: <br>{code:xml} <br>&lt;route&gt; <br>  &lt;from uri=&quot;activemq:queue:foo&quot;/&gt; <br>  &lt;transacted ref=&quot;required&quot;/&gt; <br>  &lt;to uri=&quot;activemq:queue:bar&quot;/&gt; <br>&lt;/route&gt; <br>{code} <br> <br> <br></td></tr>
            <tr><td class="diff-unchanged" >h3. Camel 1.x - Database Sample <br>In this sample we want to ensure that two endpoints is under transaction control. These two endpoints inserts data into a database. <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h3><a name="TransactionalClient-TransactionalClient"></a>Transactional Client</h3>
<p>Camel recommends supporting the <a href="http://www.enterpriseintegrationpatterns.com/TransactionalClient.html" class="external-link" rel="nofollow">Transactional Client</a> from the <a href="/confluence/display/CAMEL/Enterprise+Integration+Patterns" title="Enterprise Integration Patterns">EIP patterns</a> using spring transactions.</p>

<p><span class="image-wrap" style=""><img src="http://www.enterpriseintegrationpatterns.com/img/TransactionalClientSolution.gif" style="border: 0px solid black" /></span></p>

<p>Transaction Oriented Endpoints (<a href="/confluence/display/CAMEL/What+is+a+Camel+TOE" title="What is a Camel TOE">Camel Toes</a>) like <a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a> support using a transaction for both inbound and outbound message exchanges.  Endpoints that support transactions will participate in the current transaction context that they are called from.</p>

<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Convention over configuration</b><br />In Camel 2.0 onwards we have improved the default configuration reducing the number of Spring XML gobble you need to configure.<br/>
In this wiki page we provide the Camel 1.x examples and the same 2.0 example that requires less XML setup.</td></tr></table></div>

<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Configuration of Redelivery</b><br />The redelivery in transacted mode is <b>not</b> handled by Camel but by the backing system (the transaction manager). In such cases you should resort to the backing system how to configure the redelivery.</td></tr></table></div>

<p>You should use the <a href="http://camel.apache.org/maven/current/camel-spring/apidocs/org/apache/camel/spring/SpringRouteBuilder.html" class="external-link" rel="nofollow">SpringRouteBuilder</a> to setup the routes since you will need to setup the spring context with the <a href="http://www.springframework.org/docs/api/org/springframework/transaction/support/TransactionTemplate.html" class="external-link" rel="nofollow">TransactionTemplate</a>s that will define the transaction manager configuration and policies.</p>

<p>For inbound endpoint to be transacted, they normally need to be configured to use a Spring <a href="http://www.springframework.org/docs/api/org/springframework/transaction/PlatformTransactionManager.html" class="external-link" rel="nofollow">PlatformTransactionManager</a>.  In the case of the JMS component, this can be done by looking it up in the spring context.</p>

<p>You first define needed object in the spring configuration.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
  <span class="code-tag">&lt;bean id=<span class="code-quote">"jmsTransactionManager"</span> class=<span class="code-quote">"org.springframework.jms.connection.JmsTransactionManager"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"jmsConnectionFactory"</span> /&gt;</span>
  <span class="code-tag">&lt;/bean&gt;</span>
  
  <span class="code-tag">&lt;bean id=<span class="code-quote">"jmsConnectionFactory"</span> class=<span class="code-quote">"org.apache.activemq.ActiveMQConnectionFactory"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"brokerURL"</span> value=<span class="code-quote">"tcp://localhost:61616"</span>/&gt;</span>
  <span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>Then you look them up and use them to create the JmsComponent.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
  PlatformTransactionManager transactionManager = (PlatformTransactionManager) spring.getBean(<span class="code-quote">"jmsTransactionManager"</span>);
  ConnectionFactory connectionFactory = (ConnectionFactory) spring.getBean(<span class="code-quote">"jmsConnectionFactory"</span>);
  JmsComponent component = JmsComponent.jmsComponentTransacted(connectionFactory, transactionManager);
  component.getConfiguration().setConcurrentConsumers(1);
  ctx.addComponent(<span class="code-quote">"activemq"</span>, component);
</pre>
</div></div>


<h4><a name="TransactionalClient-TransactionPolicies"></a>Transaction Policies</h4>

<p>Outbound endpoints will automatically enlist in the current transaction context.  But what if you do not want your outbound endpoint to enlist in the same transaction as your inbound endpoint?  The solution is to add a Transaction Policy to the processing route.  You first have to define transaction policies that you will be using.  The policies use a spring <a href="http://www.springframework.org/docs/api/org/springframework/transaction/support/TransactionTemplate.html" class="external-link" rel="nofollow">TransactionTemplate</a> under the covers for declaring the transaction demarcation to use.  So you will need to add something like the following to your spring xml:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
  <span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRED"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
  <span class="code-tag">&lt;/bean&gt;</span>

  <span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRES_NEW"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"propagationBehaviorName"</span> value=<span class="code-quote">"PROPAGATION_REQUIRES_NEW"</span>/&gt;</span>
  <span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>Then in your <a href="http://camel.apache.org/maven/current/camel-spring/apidocs/org/apache/camel/spring/SpringRouteBuilder.html" class="external-link" rel="nofollow">SpringRouteBuilder</a>, you just need to create new SpringTransactionPolicy objects for each of the templates.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">public</span> void configure() {
   ...
   Policy requried = bean(SpringTransactionPolicy.class, <span class="code-quote">"PROPAGATION_REQUIRED"</span>));
   Policy requirenew = bean(SpringTransactionPolicy.class, <span class="code-quote">"PROPAGATION_REQUIRES_NEW"</span>));
   ...
}
</pre>
</div></div>

<p>Once created, you can use the Policy objects in your processing routes:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">

   <span class="code-comment">// Send to bar in a <span class="code-keyword">new</span> transaction
</span>   from(<span class="code-quote">"activemq:queue:foo"</span>).policy(requirenew).to(<span class="code-quote">"activemq:queue:bar"</span>);

   <span class="code-comment">// Send to bar without a transaction.
</span>   from(<span class="code-quote">"activemq:queue:foo"</span>).policy(notsupported ).to(<span class="code-quote">"activemq:queue:bar"</span>);

</pre>
</div></div>

<h4><a name="TransactionalClient-OSGiBlueprint"></a>OSGi Blueprint</h4>

<p>If you are using <a href="/confluence/display/CAMEL/Using+OSGi+blueprint+with+Camel" title="Using OSGi blueprint with Camel">OSGi Blueprint</a> then you most likely have to explicit declare a policy and refer to the policy from the transacted in the route.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
  <span class="code-tag">&lt;bean id=<span class="code-quote">"required"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"propagationBehaviorName"</span> value=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
  <span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>And then refer to "required" from the route:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;route&gt;</span>
  <span class="code-tag">&lt;from uri=<span class="code-quote">"activemq:queue:foo"</span>/&gt;</span>
  <span class="code-tag">&lt;transacted ref=<span class="code-quote">"required"</span>/&gt;</span>
  <span class="code-tag">&lt;to uri=<span class="code-quote">"activemq:queue:bar"</span>/&gt;</span>
<span class="code-tag">&lt;/route&gt;</span>
</pre>
</div></div>


<h3><a name="TransactionalClient-Camel1.xDatabaseSample"></a>Camel 1.x - Database Sample</h3>
<p>In this sample we want to ensure that two endpoints is under transaction control. These two endpoints inserts data into a database.<br/>
The sample is in its full as a <a href="http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceTest.java?view=log" class="external-link" rel="nofollow">unit test</a>.</p>

<p>First of all we setup the usual spring stuff in its configuration file. Here we have defined a DataSource to the HSQLDB and a most importantly<br/>
the Spring DataSoruce TransactionManager that is doing the heavy lifting of ensuring our transactional policies. You are of course free to use any<br/>
of the Spring based TransactionMananger, eg. if you are in a full blown J2EE container you could use JTA or the WebLogic or WebSphere specific managers.</p>

<p>We use the required transaction policy that we define as the <tt>PROPOGATION_REQUIRED</tt> spring bean. And as last we have our book service bean that does the business logic<br/>
and inserts data in the database as our core business logic.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- datasource to the database --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"dataSource"</span> class=<span class="code-quote">"org.springframework.jdbc.datasource.DriverManagerDataSource"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"driverClassName"</span> value=<span class="code-quote">"org.hsqldb.jdbcDriver"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"url"</span> value=<span class="code-quote">"jdbc:hsqldb:mem:camel"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"username"</span> value=<span class="code-quote">"sa"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"password"</span> value=""/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- spring transaction manager --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"txManager"</span> class=<span class="code-quote">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"dataSource"</span> ref=<span class="code-quote">"dataSource"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- policy for required transaction used in our Camel routes --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRED"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"txManager"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"propagationBehaviorName"</span> value=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- bean for book business logic --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"bookService"</span> class=<span class="code-quote">"org.apache.camel.spring.interceptor.BookService"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"dataSource"</span> ref=<span class="code-quote">"dataSource"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>In our Camel route that is Java DSL based we setup the transactional policy, wrapped as a Policy.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-comment">// Notice that we use the SpringRouteBuilder that has a few more features than
</span><span class="code-comment">// the standard RouteBuilder
</span><span class="code-keyword">return</span> <span class="code-keyword">new</span> SpringRouteBuilder() {
    <span class="code-keyword">public</span> void configure() <span class="code-keyword">throws</span> Exception {
        <span class="code-comment">// lookup the transaction policy
</span>        SpringTransactionPolicy required = lookup(<span class="code-quote">"PROPAGATION_REQUIRED"</span>, SpringTransactionPolicy.class);

        <span class="code-comment">// use <span class="code-keyword">this</span> error handler instead of DeadLetterChannel that is the <span class="code-keyword">default</span>
</span>        <span class="code-comment">// Notice: transactionErrorHandler is in SpringRouteBuilder
</span>        <span class="code-keyword">if</span> (isUseTransactionErrorHandler()) {
            <span class="code-comment">// useTransactionErrorHandler is only used <span class="code-keyword">for</span> unit testing to reuse code
</span>            <span class="code-comment">// <span class="code-keyword">for</span> doing a 2nd test without <span class="code-keyword">this</span> transaction error handler, so ignore
</span>            <span class="code-comment">// <span class="code-keyword">this</span>. For spring based transaction, end users are encouraged to use the
</span>            <span class="code-comment">// transaction error handler instead of the <span class="code-keyword">default</span> DeadLetterChannel.
</span>            errorHandler(transactionErrorHandler(required));
        }
</pre>
</div></div>

<p>Then we are ready to define our Camel routes. We have two routes: 1 for success conditions, and 1 for a forced rollback condition.<br/>
This is after all based on a unit test.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-comment">// set the required policy <span class="code-keyword">for</span> <span class="code-keyword">this</span> route
</span>from(<span class="code-quote">"direct:okay"</span>).policy(required).
    setBody(constant(<span class="code-quote">"Tiger in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>).
    setBody(constant(<span class="code-quote">"Elephant in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>);

<span class="code-comment">// set the required policy <span class="code-keyword">for</span> <span class="code-keyword">this</span> route
</span>from(<span class="code-quote">"direct:fail"</span>).policy(required).
    setBody(constant(<span class="code-quote">"Tiger in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>).
    setBody(constant(<span class="code-quote">"Donkey in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>);
</pre>
</div></div>

<p>As its a unit test we need to setup the database and this is easily done with Spring JdbcTemplate</p>
<div class="error"><span class="error">Error formatting macro: snippet: java.lang.IndexOutOfBoundsException: Index: 20, Size: 20</span> </div>

<p>And our core business service, the book service, will accept any books except the Donkeys.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class BookService {

    <span class="code-keyword">private</span> SimpleJdbcTemplate jdbc;

    <span class="code-keyword">public</span> BookService() {
    }

    <span class="code-keyword">public</span> void setDataSource(DataSource ds) {
        jdbc = <span class="code-keyword">new</span> SimpleJdbcTemplate(ds);
    }

    <span class="code-keyword">public</span> void orderBook(<span class="code-object">String</span> title) <span class="code-keyword">throws</span> Exception {
        <span class="code-keyword">if</span> (title.startsWith(<span class="code-quote">"Donkey"</span>)) {
            <span class="code-keyword">throw</span> <span class="code-keyword">new</span> IllegalArgumentException(<span class="code-quote">"We don't have Donkeys, only Camels"</span>);
        }

        <span class="code-comment">// create <span class="code-keyword">new</span> local datasource to store in DB
</span>        jdbc.update(<span class="code-quote">"insert into books (title) values (?)"</span>, title);
    }
}
</pre>
</div></div>

<p>Then we are ready to fire the tests. First to commit condition:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> void testTransactionSuccess() <span class="code-keyword">throws</span> Exception {
    template.sendBody(<span class="code-quote">"direct:okay"</span>, <span class="code-quote">"Hello World"</span>);

    <span class="code-object">int</span> count = jdbc.queryForInt(<span class="code-quote">"select count(*) from books"</span>);
    assertEquals(<span class="code-quote">"<span class="code-object">Number</span> of books"</span>, 3, count);
}
</pre>
</div></div>

<p>And lastly the rollback condition since the 2nd book is a Donkey book:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> void testTransactionRollback() <span class="code-keyword">throws</span> Exception {
    <span class="code-keyword">try</span> {
        template.sendBody(<span class="code-quote">"direct:fail"</span>, <span class="code-quote">"Hello World"</span>);
    } <span class="code-keyword">catch</span> (RuntimeCamelException e) {
        <span class="code-comment">// expected as we fail
</span>        assertIsInstanceOf(RuntimeCamelException.class, e.getCause());
        assertTrue(e.getCause().getCause() <span class="code-keyword">instanceof</span> IllegalArgumentException);
        assertEquals(<span class="code-quote">"We don't have Donkeys, only Camels"</span>, e.getCause().getCause().getMessage());
    }

    <span class="code-object">int</span> count = jdbc.queryForInt(<span class="code-quote">"select count(*) from books"</span>);
    assertEquals(<span class="code-quote">"<span class="code-object">Number</span> of books"</span>, 1, count);
}
</pre>
</div></div>

<h3><a name="TransactionalClient-Camel1.xJMSSample"></a>Camel 1.x - JMS Sample</h3>
<p>In this sample we want to listen for messages on a queue and process the messages with our business logic java code and send them along. Since its based on a <a href="http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/JMSTransactionalClientTestjava?view=log" class="external-link" rel="nofollow">unit test</a> the destination is a mock endpoint.</p>

<p>This time we want to setup the camel context and routes using the Spring XML syntax.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- here we define our camel context --&gt;</span></span>
<span class="code-tag">&lt;camel:camelContext id=<span class="code-quote">"myroutes"</span>&gt;</span>
    <span class="code-tag"><span class="code-comment">&lt;!-- and now our route using the XML syntax --&gt;</span></span>
    <span class="code-tag">&lt;camel:route errorHandlerRef=<span class="code-quote">"errorHandler"</span>&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 1: from the jms queue --&gt;</span></span>
        <span class="code-tag">&lt;camel:from uri=<span class="code-quote">"activemq:queue:okay"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 2: setup the transactional boundaries to require a transaction --&gt;</span></span>
        <span class="code-tag">&lt;camel:transacted ref=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 3: call our business logic that is myProcessor --&gt;</span></span>
        <span class="code-tag">&lt;camel:process ref=<span class="code-quote">"myProcessor"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 4: if success then send it to the mock --&gt;</span></span>
        <span class="code-tag">&lt;camel:to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/camel:route&gt;</span>
<span class="code-tag">&lt;/camel:camelContext&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- this bean is our business logic --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"myProcessor"</span> class=<span class="code-quote">"org.apache.camel.component.jms.tx.JMSTransactionalClientTest$MyProcessor"</span>/&gt;</span>
</pre>
</div></div>

<p>Since the rest is standard XML stuff its nothing fancy now for the reader:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- the transactional error handler --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"errorHandler"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.TransactionErrorHandlerBuilder"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"springTransactionPolicy"</span> ref=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"poolConnectionFactory"</span> class=<span class="code-quote">"org.apache.activemq.pool.PooledConnectionFactory"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"maxConnections"</span> value=<span class="code-quote">"8"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"jmsConnectionFactory"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"jmsConnectionFactory"</span> class=<span class="code-quote">"org.apache.activemq.ActiveMQConnectionFactory"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"brokerURL"</span> value=<span class="code-quote">"vm://localhost?broker.persistent=false&amp;amp;broker.useJmx=false"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"jmsTransactionManager"</span> class=<span class="code-quote">"org.springframework.jms.connection.JmsTransactionManager"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"poolConnectionFactory"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"jmsConfig"</span> class=<span class="code-quote">"org.apache.camel.component.jms.JmsConfiguration"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"poolConnectionFactory"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transacted"</span> value=<span class="code-quote">"true"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"concurrentConsumers"</span> value=<span class="code-quote">"1"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"activemq"</span> class=<span class="code-quote">"org.apache.activemq.camel.component.ActiveMQComponent"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"configuration"</span> ref=<span class="code-quote">"jmsConfig"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRED"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>Our business logic is set to handle the incomming messages and fail the first two times. When its a success it responds with a <tt>Bye World</tt> message.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-keyword">static</span> class MyProcessor <span class="code-keyword">implements</span> Processor {
    <span class="code-keyword">private</span> <span class="code-object">int</span> count;

    <span class="code-keyword">public</span> void process(Exchange exchange) <span class="code-keyword">throws</span> Exception {
        <span class="code-keyword">if</span> (++count &lt;= 2) {
            <span class="code-keyword">throw</span> <span class="code-keyword">new</span> IllegalArgumentException(<span class="code-quote">"Forced Exception number "</span> + count + <span class="code-quote">", please retry"</span>);
        }
        exchange.getIn().setBody(<span class="code-quote">"Bye World"</span>);
        exchange.getIn().setHeader(<span class="code-quote">"count"</span>, count);
    }
}
</pre>
</div></div>

<p>And our unit test is tested with this java code. Notice that we expect the <tt>Bye World</tt> message to be delivered at the 3rd attempt.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">MockEndpoint mock = getMockEndpoint(<span class="code-quote">"mock:result"</span>);
mock.expectedMessageCount(1);
mock.expectedBodiesReceived(<span class="code-quote">"Bye World"</span>);
<span class="code-comment">// success at 3rd attempt
</span>mock.message(0).header(<span class="code-quote">"count"</span>).isEqualTo(3);

template.sendBody(<span class="code-quote">"activemq:queue:okay"</span>, <span class="code-quote">"Hello World"</span>);

mock.assertIsSatisfied();
</pre>
</div></div>

<h3><a name="TransactionalClient-Camel1.xSpringbasedconfiguration"></a>Camel 1.x - Spring based configuration</h3>
<p>In Camel 1.4 we have introduced the concept of configuration of the error handlers using spring XML configuration. The sample below demonstrates that you can configure transaction error handlers in Spring XML as spring beans. These can then be set as global, per route based or per policy based error handler. The latter has been demonstrated in the samples above. This sample is the database sample configured in Spring XML.</p>

<p>Notice that we have defined two error handler, one per route. The first route uses the transaction error handler, and the 2nd uses no error handler at all.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- here we define our camel context --&gt;</span></span>
<span class="code-tag">&lt;camel:camelContext id=<span class="code-quote">"myroutes"</span>&gt;</span>

    <span class="code-tag"><span class="code-comment">&lt;!-- first route with transaction error handler --&gt;</span></span>
    <span class="code-tag"><span class="code-comment">&lt;!-- here we refer to our transaction error handler we define in this Spring XML file --&gt;</span></span>
    <span class="code-tag"><span class="code-comment">&lt;!-- in this route the transactionErrorHandler is used --&gt;</span></span>
    <span class="code-tag">&lt;camel:route errorHandlerRef=<span class="code-quote">"transactionErrorHandler"</span>&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 1: from the jms queue --&gt;</span></span>
        <span class="code-tag">&lt;camel:from uri=<span class="code-quote">"activemq:queue:okay"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 2: setup the transactional boundaries to require a transaction --&gt;</span></span>
        <span class="code-tag">&lt;camel:transacted ref=<span class="code-quote">"required"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 3: call our business logic that is myProcessor --&gt;</span></span>
        <span class="code-tag">&lt;camel:process ref=<span class="code-quote">"myProcessor"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 4: if success then send it to the mock --&gt;</span></span>
        <span class="code-tag">&lt;camel:to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/camel:route&gt;</span>

    <span class="code-tag"><span class="code-comment">&lt;!-- 2nd route with no error handling --&gt;</span></span>
    <span class="code-tag"><span class="code-comment">&lt;!-- this route doens't use error handler, in fact the spring bean with id noErrorHandler --&gt;</span></span>
    <span class="code-tag">&lt;camel:route errorHandlerRef=<span class="code-quote">"noErrorHandler"</span>&gt;</span>
        <span class="code-tag">&lt;camel:from uri=<span class="code-quote">"activemq:queue:bad"</span>/&gt;</span>
        <span class="code-tag">&lt;camel:to uri=<span class="code-quote">"log:bad"</span>/&gt;</span>
    <span class="code-tag">&lt;/camel:route&gt;</span>

<span class="code-tag">&lt;/camel:camelContext&gt;</span>
</pre>
</div></div>

<p>The following snippet is the Spring XML configuration to setup the error handlers in pure spring XML:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- camel policy we refer to in our route --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"required"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionTemplate"</span> ref=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- the standard spring transaction template for required --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRED"</span> class=<span class="code-quote">"org.springframework.transaction.support.TransactionTemplate"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- the transaction error handle we refer to from the route --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"transactionErrorHandler"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.TransactionErrorHandlerBuilder"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionTemplate"</span> ref=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- the no error handler --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"noErrorHandler"</span> class=<span class="code-quote">"org.apache.camel.builder.NoErrorHandlerBuilder"</span>/&gt;</span>
</pre>
</div></div>

<h4><a name="TransactionalClient-DelayPolicy%28@deprecated%29"></a>DelayPolicy (@deprecated)</h4>
<p><a href="http://camel.apache.org/maven/camel-core/apidocs/org/apache/camel/processor/DelayPolicy.html" class="external-link" rel="nofollow">DelayPolicy</a> is a new policy introduced in Camel 1.5, to replaces the RedeliveryPolicy used in Camel 1.4. Notice the <tt>transactionErrorHandler</tt> can be configured with a DelayPolicy to set a fixed delay in millis between each redelivery attempt. Camel does this by sleeping the delay until transaction is marked for rollback and the caused exception is rethrown.</p>

<p>This allows a simple redelivery interval that can be configured for development mode or light production to avoid a rapid redelivery strategy that can exhaust a system that constantly fails. </p>

<p>The DelayPolicy is @deprecated and removed in Camel 2.0. All redelivery configuration should be configured on the back system.</p>

<p><b>We strongly recommend that you configure the backing system for correct redelivery policy in your environment.</b></p>

<h3><a name="TransactionalClient-Camel2.0DatabaseSample"></a>Camel 2.0 - Database Sample</h3>
<p>In this sample we want to ensure that two endpoints is under transaction control. These two endpoints inserts data into a database.<br/>
The sample is in its full as a <a href="http://svn.apache.org/viewvc/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientDataSourceMinimalConfigurationTest.java?view=log" class="external-link" rel="nofollow">unit test</a>.</p>

<p>First of all we setup the usual spring stuff in its configuration file. Here we have defined a DataSource to the HSQLDB and a most importantly<br/>
the Spring DataSoruce TransactionManager that is doing the heavy lifting of ensuring our transactional policies. You are of course free to use any<br/>
of the Spring based TransactionMananger, eg. if you are in a full blown J2EE container you could use JTA or the WebLogic or WebSphere specific managers.</p>

<p>As we use the new convention over configuration we do <b>not</b> need to configure a transaction policy bean, so we do not have any <tt>PROPAGATION_REQUIRED</tt> beans.<br/>
All the beans needed to be configured is <b>standard</b> Spring beans only, eg. there are no Camel specific configuration at all.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- this example uses JDBC so we define a data source --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"dataSource"</span> class=<span class="code-quote">"org.springframework.jdbc.datasource.DriverManagerDataSource"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"driverClassName"</span> value=<span class="code-quote">"org.hsqldb.jdbcDriver"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"url"</span> value=<span class="code-quote">"jdbc:hsqldb:mem:camel"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"username"</span> value=<span class="code-quote">"sa"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"password"</span> value=""/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- spring transaction manager --&gt;</span></span>
<span class="code-tag"><span class="code-comment">&lt;!-- this is the transaction manager Camel will use for transacted routes --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"txManager"</span> class=<span class="code-quote">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"dataSource"</span> ref=<span class="code-quote">"dataSource"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- bean for book business logic --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"bookService"</span> class=<span class="code-quote">"org.apache.camel.spring.interceptor.BookService"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"dataSource"</span> ref=<span class="code-quote">"dataSource"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>Then we are ready to define our Camel routes. We have two routes: 1 for success conditions, and 1 for a forced rollback condition.<br/>
This is after all based on a unit test. Notice that we mark each route as transacted using the <b>transacted</b> tag.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag">&lt;camelContext xmlns=<span class="code-quote">"http://camel.apache.org/schema/spring"</span>&gt;</span>
    <span class="code-tag">&lt;route&gt;</span>
        <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:okay"</span>/&gt;</span>
        &lt;!-- we mark this route as transacted. Camel will lookup the spring transaction manager
             and use it by default. We can optimally pass in arguments to specify a policy to use
             that is configured with a spring transaction manager of choice. However Camel supports
             convention over configuration as we can just use the defaults out of the box and Camel
             that suites in most situations --&gt;
        <span class="code-tag">&lt;transacted/&gt;</span>
        <span class="code-tag">&lt;setBody&gt;</span>
            <span class="code-tag">&lt;constant&gt;</span>Tiger in Action<span class="code-tag">&lt;/constant&gt;</span>
        <span class="code-tag">&lt;/setBody&gt;</span>
        <span class="code-tag">&lt;bean ref=<span class="code-quote">"bookService"</span>/&gt;</span>
        <span class="code-tag">&lt;setBody&gt;</span>
            <span class="code-tag">&lt;constant&gt;</span>Elephant in Action<span class="code-tag">&lt;/constant&gt;</span>
        <span class="code-tag">&lt;/setBody&gt;</span>
        <span class="code-tag">&lt;bean ref=<span class="code-quote">"bookService"</span>/&gt;</span>
    <span class="code-tag">&lt;/route&gt;</span>

    <span class="code-tag">&lt;route&gt;</span>
        <span class="code-tag">&lt;from uri=<span class="code-quote">"direct:fail"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- we mark this route as transacted. See comments above. --&gt;</span></span>
        <span class="code-tag">&lt;transacted/&gt;</span>
        <span class="code-tag">&lt;setBody&gt;</span>
            <span class="code-tag">&lt;constant&gt;</span>Tiger in Action<span class="code-tag">&lt;/constant&gt;</span>
        <span class="code-tag">&lt;/setBody&gt;</span>
        <span class="code-tag">&lt;bean ref=<span class="code-quote">"bookService"</span>/&gt;</span>
        <span class="code-tag">&lt;setBody&gt;</span>
            <span class="code-tag">&lt;constant&gt;</span>Donkey in Action<span class="code-tag">&lt;/constant&gt;</span>
        <span class="code-tag">&lt;/setBody&gt;</span>
        <span class="code-tag">&lt;bean ref=<span class="code-quote">"bookService"</span>/&gt;</span>
    <span class="code-tag">&lt;/route&gt;</span>
<span class="code-tag">&lt;/camelContext&gt;</span>
</pre>
</div></div>

<p>That is all that is needed to configure a Camel route as being transacted. Just remember to use the <b>transacted</b> DSL. The rest is standard Spring XML to setup the transaction manager.</p>

<h3><a name="TransactionalClient-Camel2.0JMSSample"></a>Camel 2.0 - JMS Sample</h3>
<p>In this sample we want to listen for messages on a queue and process the messages with our business logic java code and send them along. Since its based on a <a href="http://svn.apache.org/viewvc/camel/trunk/components/camel-jms/src/test/java/org/apache/camel/component/jms/tx/TransactionMinimalConfigurationTest.java?view=log" class="external-link" rel="nofollow">unit test</a> the destination is a mock endpoint.</p>

<p>First we configure the standard Spring XML to declare a JMS connection factory, a JMS transaction manager and our ActiveMQ component that we use in our routing.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag"><span class="code-comment">&lt;!-- setup JMS connection factory --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"poolConnectionFactory"</span> class=<span class="code-quote">"org.apache.activemq.pool.PooledConnectionFactory"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"maxConnections"</span> value=<span class="code-quote">"8"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"jmsConnectionFactory"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"jmsConnectionFactory"</span> class=<span class="code-quote">"org.apache.activemq.ActiveMQConnectionFactory"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"brokerURL"</span> value=<span class="code-quote">"vm://localhost?broker.persistent=false&amp;amp;broker.useJmx=false"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- setup spring jms TX manager --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"jmsTransactionManager"</span> class=<span class="code-quote">"org.springframework.jms.connection.JmsTransactionManager"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"poolConnectionFactory"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag"><span class="code-comment">&lt;!-- define our activemq component --&gt;</span></span>
<span class="code-tag">&lt;bean id=<span class="code-quote">"activemq"</span> class=<span class="code-quote">"org.apache.activemq.camel.component.ActiveMQComponent"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"connectionFactory"</span> ref=<span class="code-quote">"poolConnectionFactory"</span>/&gt;</span>
    <span class="code-tag"><span class="code-comment">&lt;!-- define the jms consumer/producer as transacted --&gt;</span></span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transacted"</span> value=<span class="code-quote">"true"</span>/&gt;</span>
    <span class="code-tag"><span class="code-comment">&lt;!-- setup the transaction manager to use --&gt;</span></span>
    &lt;!-- if not provided then Camel will automatic use a JmsTransactionManager, however if you
         for instance use a JTA transaction manager then you must configure it --&gt;
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"jmsTransactionManager"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>And then we configure our routes. Notice that all we have to do is mark the route as transacted using the <b>transacted</b> tag.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag">&lt;camelContext xmlns=<span class="code-quote">"http://camel.apache.org/schema/spring"</span>&gt;</span>
    <span class="code-tag"><span class="code-comment">&lt;!-- disable JMX during testing --&gt;</span></span>
    <span class="code-tag">&lt;jmxAgent id=<span class="code-quote">"agent"</span> disabled=<span class="code-quote">"true"</span>/&gt;</span>
    <span class="code-tag">&lt;route&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 1: from the jms queue --&gt;</span></span>
        <span class="code-tag">&lt;from uri=<span class="code-quote">"activemq:queue:okay"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 2: mark this route as transacted --&gt;</span></span>
        <span class="code-tag">&lt;transacted/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 3: call our business logic that is myProcessor --&gt;</span></span>
        <span class="code-tag">&lt;process ref=<span class="code-quote">"myProcessor"</span>/&gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- 4: if success then send it to the mock --&gt;</span></span>
        <span class="code-tag">&lt;to uri=<span class="code-quote">"mock:result"</span>/&gt;</span>
    <span class="code-tag">&lt;/route&gt;</span>
<span class="code-tag">&lt;/camelContext&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"myProcessor"</span> class=<span class="code-quote">"org.apache.camel.component.jms.tx.JMSTransactionalClientTest$MyProcessor"</span>/&gt;</span>
</pre>
</div></div>

<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="/confluence/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Transaction error handler</b><br />When a route is marked as transacted using <b>transacted</b> Camel will automatic use the <a href="/confluence/display/CAMEL/TransactionErrorHandler" title="TransactionErrorHandler">TransactionErrorHandler</a> as <a href="/confluence/display/CAMEL/Error+Handler" title="Error Handler">Error Handler</a>. It supports basically the same feature set as the <a href="/confluence/display/CAMEL/DefaultErrorHandler" title="DefaultErrorHandler">DefaultErrorHandler</a>, so you can for instance use <a href="/confluence/display/CAMEL/Exception+Clause" title="Exception Clause">Exception Clause</a> as well.</td></tr></table></div>

<h2><a name="TransactionalClient-Usingmultiplerouteswithdifferentpropagationbehaviors"></a>Using multiple routes with different propagation behaviors</h2>
<p><b>Available as of Camel 2.2</b><br/>
Suppose you want to route a message through two routes and by which the 2nd route should run in its own transaction. How do you do that? You use propagation behaviors for that where you configure it as follows:</p>
<ul class="alternate" type="square">
	<li>The first route use <tt>PROPAGATION_REQUIRED</tt></li>
	<li>The second route use <tt>PROPAGATION_REQUIRES_NEW</tt></li>
</ul>


<p>This is configured in the Spring XML file:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml"><span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRED"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"txManager"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"propagationBehaviorName"</span> value=<span class="code-quote">"PROPAGATION_REQUIRED"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>

<span class="code-tag">&lt;bean id=<span class="code-quote">"PROPAGATION_REQUIRES_NEW"</span> class=<span class="code-quote">"org.apache.camel.spring.spi.SpringTransactionPolicy"</span>&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"transactionManager"</span> ref=<span class="code-quote">"txManager"</span>/&gt;</span>
    <span class="code-tag">&lt;property name=<span class="code-quote">"propagationBehaviorName"</span> value=<span class="code-quote">"PROPAGATION_REQUIRES_NEW"</span>/&gt;</span>
<span class="code-tag">&lt;/bean&gt;</span>
</pre>
</div></div>

<p>Then in the routes you use transacted DSL to indicate which of these two propagations it uses.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">from(<span class="code-quote">"direct:mixed"</span>)
    <span class="code-comment">// using required
</span>    .transacted(<span class="code-quote">"PROPAGATION_REQUIRED"</span>)
    <span class="code-comment">// all these steps will be okay
</span>    .setBody(constant(<span class="code-quote">"Tiger in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>)
    .setBody(constant(<span class="code-quote">"Elephant in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>)
    <span class="code-comment">// <span class="code-keyword">continue</span> on route 2
</span>    .to(<span class="code-quote">"direct:mixed2"</span>);

from(<span class="code-quote">"direct:mixed2"</span>)
    <span class="code-comment">// tell Camel that <span class="code-keyword">if</span> <span class="code-keyword">this</span> route fails then only rollback <span class="code-keyword">this</span> last route
</span>    <span class="code-comment">// by using (rollback only *last*)
</span>    .onException(Exception.class).markRollbackOnlyLast().end()
    <span class="code-comment">// using a different propagation which is requires <span class="code-keyword">new</span>
</span>    .transacted(<span class="code-quote">"PROPAGATION_REQUIRES_NEW"</span>)
    <span class="code-comment">// <span class="code-keyword">this</span> step will be okay
</span>    .setBody(constant(<span class="code-quote">"Lion in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>)
    <span class="code-comment">// <span class="code-keyword">this</span> step will fail with donkey
</span>    .setBody(constant(<span class="code-quote">"Donkey in Action"</span>)).beanRef(<span class="code-quote">"bookService"</span>);
</pre>
</div></div>

<p>Notice how we have configured the <tt>onException</tt> in the 2nd route to indicate in case of any exceptions we should handle it and just rollback this transaction. <br/>
This is done using the <tt>markRollbackOnlyLast</tt> which tells Camel to only do it for the current transaction and not globally.</p>

<h4><a name="TransactionalClient-SeeAlso"></a>See Also</h4>
<ul>
	<li><a href="/confluence/display/CAMEL/Error+handling+in+Camel" title="Error handling in Camel">Error handling in Camel</a></li>
	<li><a href="/confluence/display/CAMEL/TransactionErrorHandler" title="TransactionErrorHandler">TransactionErrorHandler</a></li>
	<li><a href="/confluence/display/CAMEL/Error+Handler" title="Error Handler">Error Handler</a></li>
	<li><a href="/confluence/display/CAMEL/JMS" title="JMS">JMS</a></li>
</ul>


<h4><a name="TransactionalClient-UsingThisPattern"></a>Using This Pattern</h4>

<p>If you would like to use this EIP Pattern then please read the <a href="/confluence/display/CAMEL/Getting+Started" title="Getting Started">Getting Started</a>, you may also find the <a href="/confluence/display/CAMEL/Architecture" title="Architecture">Architecture</a> useful particularly the description of <a href="/confluence/display/CAMEL/Endpoint" title="Endpoint">Endpoint</a> and <a href="/confluence/display/CAMEL/URIs" title="URIs">URIs</a>. Then you could try out some of the <a href="/confluence/display/CAMEL/Examples" title="Examples">Examples</a> first before trying this pattern out.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Transactional+Client">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=52967&revisedVersion=25&originalVersion=24">View Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Transactional+Client?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message