1 2 Previous Next 17 Replies Latest reply on Feb 2, 2012 1:04 PM by Claus Ibsen

    JMS and Database interactions under the same  transactional context

    Mark S Newbie

      I am currently using ServiceMix 4.3 out-of-the-box and I am hoping someone can give me a straightforward concrete example of how I would wrap a process that includes JMS and Database interactions under the same transactional context?

       

      I have looked at the following resources, though I am looking for more of a working example.

       

      http://fusesource.com/docs/esb/4.2/deploy_osgi/ESBOSGiIntro-Txn.html

      http://fusesource.com/docs/esb/4.4/esb_deploy_osgi/ESBOSGiIntro-Txn.html

       

       

      Also, is there a best practice to configure and use an XA Transactions that spans a JMS resource and a Database resource?

        • 1. Re: JMS and Database interactions under the same  transactional context
          Mark S Newbie

          My specific environment configuration is that I have Microsoft SQL Server 2008 and ActiveMq.

           

          Does anyone have an XA examples?  Any information, tutorial will be greatly appreciated.

          • 3. Re: JMS and Database interactions under the same  transactional context
            Mark S Newbie

            Thanks for that reply.

             

            I ended up finding the example that goes with that book:

             

            http://camelinaction.googlecode.com/svn/trunk/chapter9/xa/src/test/resources/spring-context.xml

             

            Ideally, I am looking for an example that combines the following resources in blueprint or spring configuration file:

             

             

            • 4. Re: JMS and Database interactions under the same  transactional context
              Mark S Newbie

              I am using ServiceMix and I am attempting to use XA transactions correctly.  Basically, I want my route wrapped in an XA transaction in a way that ActiveMQ and Microsoft SqlServer persistance is atomic.

               

              Ideally, I want all transactions that fail X amount of times to move into a Dead Letter Queue for later processing.

               

              -


               

              Currently for the class "ServiceMixXaRollbackTest" below...

               

              If a transactions is to fail more than 2 times it will move to the Dead Letter Queue:  "DLQ.my_test_thirdparty".

               

              However if I comment out the code:

               

              onException(IllegalArgumentException.class).maximumRedeliveries(2).useOriginalMessage().to( "activemq:queue:DLQ.my_test_thirdparty" );

               

              Then the JMS XML message that has been dropped into "my_test_thirdparty" will get consumed and disappear after 4 retries.

               

               

              -


               

              Is the way in which I undertake my Camel Error Handling correct?  Any help would be much appreciated.

               

               

               

              Regards,

              Mark

               

               

               

              -


              Below are some of the articles that may be related.

               

               

              http://servicemix.396122.n5.nabble.com/smx4-camel2-2-transactional-error-handling-td420449.html

              http://camel.465427.n5.nabble.com/Transaction-Error-Handler-with-Dead-Letter-Channel-td3232320.html

              http://tmielke.blogspot.com/2011/07/error-handling-in-camel-for-jms.html

              http://weblog.plexobject.com/?p=1672

              http://camel.apache.org/transactionerrorhandler.html

              http://camel.apache.org/transactional-client.html

               

              -


               

               

               

               

                                   

                                   

               

               

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

              • I have a one "src/main/resources/META-INF/spring/resource-context.xml" file:

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               

               

               

               

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

              • I have one properties file "src/main/resouces/jta.properties" file:

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               

              com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory

              com.atomikos.icatch.console_file_name = tm-dev.out

              com.atomikos.icatch.log_base_name = tmlog-dev

              com.atomikos.icatch.tm_unique_name = tmdev

              com.atomikos.icatch.serial_jta_transactions=false

              com.atomikos.icatch.automatic_resource_registration=true

              com.atomikos.icatch.max_actives=15000

              com.atomikos.icatch.max_timeout=3600000

              com.atomikos.icatch.output_dir=atomikosxatm/

              com.atomikos.icatch.log_base_dir=atomikosxatm/

               

               

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

              • I use the embedded ServiceMix 4.3 ActiveMq instance, otherwise you could use the following file "src/test/resources/broker-context.xml":

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               

               

               

               

               

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

              • I have one java test class to test successful XA Commit.

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               

              package test.xa;

               

              import javax.sql.DataSource;

               

              import org.apache.activemq.ActiveMQXAConnectionFactory;

              import org.apache.camel.CamelContext;

              import org.apache.camel.builder.ErrorHandlerBuilder;

              import org.apache.camel.builder.RouteBuilder;

              import org.apache.camel.component.jms.JmsComponent;

              import org.apache.camel.language.XPath;

              import org.apache.camel.processor.RedeliveryPolicy;

              import org.apache.camel.spring.SpringRouteBuilder;

              import org.apache.camel.spring.spi.TransactionErrorHandlerBuilder;

              import org.apache.camel.test.CamelSpringTestSupport;

              import org.springframework.context.support.AbstractXmlApplicationContext;

              import org.springframework.context.support.ClassPathXmlApplicationContext;

              import org.springframework.jdbc.core.JdbcTemplate;

              import org.testng.Assert;

              import org.testng.annotations.AfterMethod;

              import org.testng.annotations.BeforeMethod;

              import org.testng.annotations.Test;

               

               

              public class ServiceMixXaCommitTest extends CamelSpringTestSupport

              {

                  protected JdbcTemplate jdbc;

               

                  @BeforeMethod

                  public void setupDatabase() throws Exception {

                      super.setUp();

                      DataSource ds = context.getRegistry().lookup("dataSourceRaw", DataSource.class);

                      jdbc = new JdbcTemplate(ds);

               

              //        jdbc = context.getRegistry().lookup("jdbc", JdbcTemplate.class);

                      try

                      {

                          jdbc.execute( "drop table messaging.my_test_thirdparty" );

                      }

                      catch ( Exception e )

                      {

                          // ignore

                      }

                      jdbc.execute("create table messaging.my_test_thirdparty ( thirdparty_id varchar(10), name varchar(128), created varchar(20), status_code varchar(3) )");

                  }

               

                  @AfterMethod

                  public void restoreDatabase() throws Exception {

                      jdbc.execute("drop table messaging.my_test_thirdparty");

                  }

               

                  @Override

                  protected CamelContext createCamelContext() throws Exception {

                      CamelContext camelContext = super.createCamelContext();

               

                      ActiveMQXAConnectionFactory connectionFactory = applicationContext.getBean("activemq", ActiveMQXAConnectionFactory.class);

                      camelContext.addComponent("activemq", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));

                      camelContext.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));

               

              //        DataSource dataSource = applicationContext.getBean("dataSource", DataSource.class);

              //

              //        JdbcComponent jdbcComponent = new JdbcComponent();

              //        jdbcComponent.setDataSource(dataSource);

              //        camelContext.addComponent("jdbc", jdbcComponent);

               

               

                      camelContext.addRoutes( createRouteBuilder() );

               

                      return camelContext;

                  }

               

               

               

                  @Override

                  protected AbstractXmlApplicationContext createApplicationContext() {

                      return new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/resource-context.xml"});

                  }

               

                  @Test

                  public void testXaRollbackAfterDb() throws Exception {

               

                      // This database table should be empty

                      Assert.assertEquals(jdbc.queryForInt("select count(*) from my_test_thirdparty"), 0);

               

                      String xml = "";

                      template.sendBody("activemq:queue:my_test_thirdparty", xml);

               

                      // Wait for route to fail

                      Thread.sleep(15000);

               

                      // There should be 1 row in the database

                      Assert.assertEquals(jdbc.queryForInt("select count(*) from my_test_thirdparty"), 1);

               

                      // Check ActiveMq to ensure final state

                      String dlq = consumer.receiveBodyNoWait("activemq:queue:DLQ.my_test_thirdparty", String.class);

                      Assert.assertNull(dlq, "Should not find message message");

               

                  }

               

                  @Override

                  protected RouteBuilder createRouteBuilder() throws Exception {

                      return new SpringRouteBuilder() {

               

                          @Override

                          public void configure() throws Exception {

               

               

              //              Non-transactional dead letter queue.

              //                errorHandler(deadLetterChannel("activemq:queue:ActiveMQ.DLQ").maximumRedeliveries(2).redeliveryDelay(500));

               

               

                              ErrorHandlerBuilder errorHandlerBuilder = transactionErrorHandler();

               

                              RedeliveryPolicy redeliveryPolicy = ((TransactionErrorHandlerBuilder)errorHandlerBuilder).getRedeliveryPolicy();

                              redeliveryPolicy.setRedeliveryDelay( 500 );

                              redeliveryPolicy.setBackOffMultiplier(2);

                              redeliveryPolicy.setUseExponentialBackOff(true);

                              redeliveryPolicy.setMaximumRedeliveryDelay( 30 * 60 * 1000 ); // Max = 30 minutes

                              redeliveryPolicy.setMaximumRedeliveries(4);

               

                              errorHandler(errorHandlerBuilder);

               

                              // Without the below onException call, the JMS Queue Message gets consumed and disappears.

                              onException(IllegalArgumentException.class).maximumRedeliveries(2).useOriginalMessage().to( "activemq:queue:DLQ.my_test_thirdparty" );

               

               

                              from("activemq:queue:my_test_thirdparty")

                                  .transacted()

                                  .log("+++ Before Database Call +++")

                                  .bean(ServiceMixXaCommitTest.class, "toSql")

                                  .to("jdbc:dataSource")

                                  .log("+++ After Database Call +++")

                                  ;

               

               

                          }

               

                      };

                  }

               

               

                  /*

                    

              • <?xml version="1.0"?><thirdparty id="123"><name>Foo Bar</name><date>201110140815</date><code>200</code></thirdparty>

                   *

                   */

                  public static String toSql(@XPath("thirdparty/@id") int thirdpartyId,

                                      @XPath("thirdparty/name/text()") String name,

                                      @XPath("thirdparty/date/text()") long created,

                                      @XPath("thirdparty/code/text()") int status_code) {

               

                      if (thirdpartyId <= 0) {

                          throw new IllegalArgumentException("ThirdPartyId is invalid, was " + thirdpartyId);

                      }

               

                      StringBuilder sb = new StringBuilder();

                      sb.append("INSERT INTO messaging.my_test_thirdparty (thirdparty_id, name, created, status_code) VALUES (");

                      sb.append("'").append(thirdpartyId).append("', ");

                      sb.append("'").append(name).append("', ");

                      sb.append("'").append(created).append("', ");

                      sb.append("'").append(status_code).append("') ");

               

                      return sb.toString();

                  }

               

               

              }

               

               

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

              • I have one java test class to test successful XA Rollback.

              +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

               

              package test.xa;

               

              import javax.sql.DataSource;

               

              import org.apache.activemq.ActiveMQXAConnectionFactory;

              import org.apache.camel.CamelContext;

              import org.apache.camel.builder.ErrorHandlerBuilder;

              import org.apache.camel.builder.RouteBuilder;

              import org.apache.camel.component.jms.JmsComponent;

              import org.apache.camel.language.XPath;

              import org.apache.camel.processor.RedeliveryPolicy;

              import org.apache.camel.spring.SpringRouteBuilder;

              import org.apache.camel.spring.spi.TransactionErrorHandlerBuilder;

              import org.apache.camel.test.CamelSpringTestSupport;

              import org.springframework.context.support.AbstractXmlApplicationContext;

              import org.springframework.context.support.ClassPathXmlApplicationContext;

              import org.springframework.jdbc.core.JdbcTemplate;

              import org.testng.Assert;

              import org.testng.annotations.AfterMethod;

              import org.testng.annotations.BeforeMethod;

              import org.testng.annotations.Test;

               

               

              public class ServiceMixXaRollbackTest extends CamelSpringTestSupport

              {

                  protected JdbcTemplate jdbc;

               

                  @BeforeMethod

                  public void setupDatabase() throws Exception {

                      super.setUp();

                      DataSource ds = context.getRegistry().lookup("dataSourceRaw", DataSource.class);

                      jdbc = new JdbcTemplate(ds);

               

              //        jdbc = context.getRegistry().lookup("jdbc", JdbcTemplate.class);

               

                      try

                      {

                          jdbc.execute( "drop table messaging.my_test_thirdparty" );

                      }

                      catch ( Exception e )

                      {

                          // ignore

                      }

                      jdbc.execute("create table messaging.my_test_thirdparty ( thirdparty_id varchar(10), name varchar(128), created varchar(20), status_code varchar(3) )");

                  }

               

                  @AfterMethod

                  public void restoreDatabase() throws Exception {

                      jdbc.execute("drop table messaging.my_test_thirdparty");

                  }

               

                  @Override

                  protected CamelContext createCamelContext() throws Exception {

                      CamelContext camelContext = super.createCamelContext();

               

                      ActiveMQXAConnectionFactory connectionFactory = applicationContext.getBean("activemq", ActiveMQXAConnectionFactory.class);

                      camelContext.addComponent("activemq", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));

                      camelContext.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));

               

              //        DataSource dataSource = applicationContext.getBean("dataSource", DataSource.class);

              //

              //        JdbcComponent jdbcComponent = new JdbcComponent();

              //        jdbcComponent.setDataSource(dataSource);

              //        camelContext.addComponent("jdbc", jdbcComponent);

               

               

                      camelContext.addRoutes( createRouteBuilder() );

               

                      return camelContext;

                  }

               

               

               

                  @Override

                  protected AbstractXmlApplicationContext createApplicationContext() {

                      return new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/resource-context.xml"});

                  }

               

                  @Test

                  public void testXaRollbackAfterDb() throws Exception {

               

                      // This database table should be empty

                      Assert.assertEquals(jdbc.queryForInt("select count(*) from my_test_thirdparty"), 0);

               

                      String xml = "";

                      template.sendBody("activemq:queue:my_test_thirdparty", xml);

               

                      // Wait for route to fail

                      Thread.sleep(15000);

               

                      // The database should NOT have any new rows inserted to it.

                      Assert.assertEquals(jdbc.queryForInt("select count(*) from my_test_thirdparty"), 0);

               

                      // Check ActiveMq to ensure final state

                      String dlq = consumer.receiveBodyNoWait("activemq:queue:DLQ.my_test_thirdparty", String.class);

                      Assert.assertNotNull(dlq, "Should not lose message");

                  }

               

                  @Override

                  protected RouteBuilder createRouteBuilder() throws Exception {

                      return new SpringRouteBuilder() {

               

                          @Override

                          public void configure() throws Exception {

               

               

              //              Non-transactional dead letter queue.

              //                errorHandler(deadLetterChannel("activemq:queue:ActiveMQ.DLQ").maximumRedeliveries(2).redeliveryDelay(500));

               

               

                              ErrorHandlerBuilder errorHandlerBuilder = transactionErrorHandler();

               

                              RedeliveryPolicy redeliveryPolicy = ((TransactionErrorHandlerBuilder)errorHandlerBuilder).getRedeliveryPolicy();

                              redeliveryPolicy.setRedeliveryDelay( 500 );

                              redeliveryPolicy.setBackOffMultiplier(2);

                              redeliveryPolicy.setUseExponentialBackOff(true);

                              redeliveryPolicy.setMaximumRedeliveryDelay( 30 * 60 * 1000 ); // Max = 30 minutes

                              redeliveryPolicy.setMaximumRedeliveries(4);

               

                              errorHandler(errorHandlerBuilder);

               

                              // Without the below onException call, the JMS Queue Message gets consumed and disappears.

                              onException(IllegalArgumentException.class).maximumRedeliveries(2).useOriginalMessage().to( "activemq:queue:DLQ.my_test_thirdparty" );

               

               

                              from("activemq:queue:my_test_thirdparty")

                                  .transacted()

                                  .log("+++ Before Database Call +++")

                                  .bean(ServiceMixXaRollbackTest.class, "toSql")

                                  .to("jdbc:dataSource")

                                  .log("+++ After Database Call +++")

                                  .throwException(new IllegalArgumentException("Unexpected Exception"))

                                  ;

               

               

                          }

               

                      };

                  }

               

               

                  /*

                    

              • <?xml version="1.0"?><thirdparty id="123"><name>Foo Bar</name><date>201110140815</date><code>200</code></thirdparty>

                   *

                   */

                  public static String toSql(@XPath("thirdparty/@id") int thirdpartyId,

                                      @XPath("thirdparty/name/text()") String name,

                                      @XPath("thirdparty/date/text()") long created,

                                      @XPath("thirdparty/code/text()") int status_code) {

               

                      if (thirdpartyId <= 0) {

                          throw new IllegalArgumentException("ThirdPartyId is invalid, was " + thirdpartyId);

                      }

               

                      StringBuilder sb = new StringBuilder();

                      sb.append("INSERT INTO messaging.my_test_thirdparty (thirdparty_id, name, created, status_code) VALUES (");

                      sb.append("'").append(thirdpartyId).append("', ");

                      sb.append("'").append(name).append("', ");

                      sb.append("'").append(created).append("', ");

                      sb.append("'").append(status_code).append("') ");

               

                      return sb.toString();

                  }

               

               

              }

              • 5. Re: JMS and Database interactions under the same  transactional context
                Claus Ibsen Master

                Hi

                 

                You may want to checkout 2-part webinar that Charles Moulliard is to give the next 2 months about using database and transactions with Fuse ESB.

                 

                See details at

                http://fusesource.com/resources/video-archived-webinars/

                • 6. Re: JMS and Database interactions under the same  transactional context
                  Claus Ibsen Master

                  Also check the Camel transactional guide

                  http://fusesource.com/products/enterprise-camel/#documentation

                   

                  And as ActiveMQ also supports redelivery you should generally configure redelivery and dead letter channel in ActiveMQ and not Camel.

                  http://activemq.apache.org/message-redelivery-and-dlq-handling.html

                  http://activemq.apache.org/redelivery-policy.html

                   

                  The Camel in Action book chapter 9 also convers transactions and using XA etc. The sample source code for the book is free, so you may find some inspiration there.

                  • 7. Re: JMS and Database interactions under the same  transactional context
                    Mark S Newbie

                    Thanks once again for replying to these posts and I am very appreciative.

                     

                     

                    I had a close look at the Camel in Action Example I updated my Spring resource xml, and still was unable to get Transaction Rollback working as expected.

                     

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    It seems that on rollback the ActiveMq message gets consumed and does NOT end up in the Dead Letter Queue.

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                     

                    I have tried the default ActiveMq broker configuration that comes with ServiceMix 4.3 (etc/activemq-broker.xml) and also the broker configuration as it exists in the Camel in Action example (http://code.google.com/p/camelinaction/source/browse/trunk/chapter9/xa/src/test/resources/spring-context.xml).

                     

                     

                     

                     

                     

                     

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    My console logs definitely indicated that rollback has occurred.

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    Pipeline                       DEBUG Message exchange has failed so breaking out of pipeline for exchange: Exchange[JmsMessage: null] Exception: java.lang.IllegalArgumentException: Unexpected Exception

                                        Atomikos:3 atomikos                       INFO  XAResource.rollback ( 746D64657630303030313030323434:746D64657631 ) on resource ds1 represented by XAResource instance  XAResourceID:2

                    atomikos                       INFO  rollback() done of transaction tmdev0000100244

                    TransactionErrorHandler        WARN  Transaction rollback (0x4f88f506) for ExchangeId: ID:user-63311-1319148563241-0:5:1:1:1 due exception: java.lang.IllegalArgumentException: Unexpected Exception

                    EndpointMessageListener        ERROR Caused by: org.apache.camel.RuntimeCamelException - java.lang.IllegalArgumentException: Unexpected Exception

                    org.apache.camel.RuntimeCamelException: java.lang.IllegalArgumentException: Unexpected Exception

                     

                     

                     

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                    My Test Case extends CamelSpringTestSupport, and the following is my route:

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                     

                        @Override

                        protected RouteBuilder createRouteBuilder() throws Exception {

                            return new SpringRouteBuilder() {

                     

                                @Override

                                public void configure() throws Exception {

                     

                                    from("activemq:queue:my_test_thirdparty")

                                        .transacted()

                                        .log("+++ Before Database Call +++")

                                        .bean(ServiceMixXaRollbackTest.class, "toSql")

                                        .to("jdbc:dataSource")

                                        .log("+++ After Database Call +++")

                                        .throwException(new RuntimeException("Unexpected Exception"))

                                        ;

                                }

                     

                            };

                        }

                     

                     

                     

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                     

                    "src/main/resources/META-INF/spring/resource-context.xml" file:

                     

                    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                     

                     

                    • 8. Re: JMS and Database interactions under the same  transactional context
                      Claus Ibsen Master

                      Are you running inside Apache ServiceMix 4.3, or Fuse ESB? If so what version exactly are you using?

                       

                      SMX/Fuse ESB already comes with TX manager support (from Aries/Geronimo). See for example the org.apache.aries.transaction.cfg in the etc folder of the SMX/ESB

                      • 9. Re: JMS and Database interactions under the same  transactional context
                        Mark S Newbie

                        From your comments it seems I should change the way I am attempting to setup the transaction management of my Database (Microsoft SQL Server) and Message Broker (ActiveMq) to use the out-of-the-box TX manager support (from Aries/Geronimo).

                         

                        While the following link highlights what you are saying:

                        http://fusesource.com/docs/esb/4.4.1/esb_deploy_osgi/ESBOSGiIntro-Txn.html

                         

                         

                        From my understanding for what I want, I am looking for an examples that uses an JMS XA Connection Factory class (ActiveMQXAConnectionFactory) and an XA Datasource class (SQLServerXADataSource) to complete this XA/JTA transaction.

                         

                         

                        I even found the source code that is for the upcoming Fuse Webinars "Database Integration with Apache Camel" talks, though am quite bewildered without the presentation talk and slides.

                         

                        https://github.com/cmoulliard/sparks/tree/master/fuse-webinars/camel-persistence-part1

                         

                        https://github.com/cmoulliard/sparks/tree/master/fuse-webinars/camel-persistence-part2

                         

                         

                        Is there any specific examples that you know of that would be able to help me along here?

                        • 10. Re: JMS and Database interactions under the same  transactional context
                          Mark S Newbie

                          I did find a reference to ActiveMq configuration on combing "JMS and JDBC operations in one transaction with Spring/Jencks/ActiveMQ":

                           

                          http://activemq.apache.org/jms-and-jdbc-operations-in-one-transaction.html

                           

                          Though, I am still searching for the relevant configuration I to achieve ensure my ServiceMix 4.3 Camel routes can have transactional integrity.

                          • 11. Re: JMS and Database interactions under the same  transactional context
                            Mark S Newbie

                            So I have discovered some issues with my code.  The following code seems to be a working example with Atomikos (resource-context.xml) with Test Case (ServiceMixXaRollbackTest) using a ServiceMix 4.3 ActiveMq instance (activemq-broker.xml).

                             

                             

                             

                            Quick point:

                            davsclaus wrote:

                            >SMX/Fuse ESB already comes with TX manager support (from Aries/Geronimo). See for example the org.apache.aries.transaction.cfg in the etc folder of the SMX/ESB

                             

                            ++ Thanks for highlighting this, and I am working on a solution that uses this as well.  Now back to the Atomikos example.

                             

                            Quick point:

                            davsclaus wrote:

                            And as ActiveMQ also supports redelivery you should generally configure redelivery and dead letter channel in ActiveMQ and not Camel.

                            http://activemq.apache.org/message-redelivery-and-dlq-handling.html

                            http://activemq.apache.org/redelivery-policy.html

                             

                            ++ I will attempt to move this logic to ActiveMq.

                             

                             

                            Unfortunately, on transaction rollback (and retry exhaustion) I am expecting my ActiveMq message to move to the Dead Letter Queue "DLQ.my_test_thirdparty" as specified in the activemq-broker.xml, since I don't override any message redelivery and dlq handling behaviour in Camel.  Instead I am finding that the ActiveMq message lands in the queue "ActiveMQ.DLQ".

                             

                            What am I missing in my understanding on the behaviour of ActiveMq and Camel ?

                             

                             

                             

                             

                             

                            Updated code below.

                             

                             

                            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                             

                            Start code snippet:  "src/main/resources/META-INF/spring/resource-context.xml"

                             

                            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                             

                             

                             

                             

                             

                            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                             

                            End code snippet:  "apache-servicemix-4.3.0/etc/activemq-broker.xml"

                             

                            +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

                            • 12. Re: JMS and Database interactions under the same  transactional context
                              Mark S Newbie
                              davsclaus wrote:

                              Also check the Camel transactional guide

                              http://fusesource.com/products/enterprise-camel/#documentation

                               

                              And as ActiveMQ also supports redelivery you should generally configure redelivery and dead letter channel in ActiveMQ and not Camel.

                              http://activemq.apache.org/message-redelivery-and-dlq-handling.html

                              http://activemq.apache.org/redelivery-policy.html

                               

                              The Camel in Action book chapter 9 also convers transactions and using XA etc. The sample source code for the book is free, so you may find some inspiration there.

                               

                               

                              Thank you very much for your help.  It did take a while to understand this, though your help has been pinpoint accurate.

                               

                               

                              ++++++++++++++++++++++++++++++++++++++++++++++++++++++

                               

                               

                              Turns out that I didn't reload the ServiceMix ActiveMq bundle via the osgi:update command.  This meant that the following text that I added was being ignored.

                               

                               

                               

                              Edited by: marks1900 on Oct 26, 2011 7:45 PM

                              • 13. Re: JMS and Database interactions under the same  transactional context
                                Mark S Newbie

                                I have managed to get JMS and Database interactions under the same transactional context using ActiveMq for JMS and Microsoft SQL Server as the Database.

                                • 14. Re: JMS and Database interactions under the same  transactional context
                                  Claus Ibsen Master

                                  Glad you got it working. Yeah TX is not easy.

                                  1 2 Previous Next