What do you need to set up distributed transactions in Apache Camel correctly?

Mission: Your team have decided that data atomicity and integrity are paramount, and you’ve been tasked with implementing XA transactions in your Camel application.

You’re doing some “recon” (Google searching). But all the sample code for XA transactions seems rather impenetrable.

What does it all actually do? You don’t want to gorge yourself on some tasty 🍝 copy-pasta 🍝 without really understanding what you’re adding to your application.

And you also know that transactions are heavy stuff. If you miss something out, the risks are pretty big. You risk losing messages, or strange things start to happen…

So, before you copy some code that a stranger wrote on the internet, let’s find out what you actually need for XA transactions in Apache Camel.

What you need for XA

If you want to set up XA transactions in your Apache Camel routes, here’s what you need:

  • Configure a JTA transaction manager

    To co-ordinate transactions involving more than one participant (which is what XA transactions are), you need a transaction manager which implements the Java Transaction API (JTA). This is part of the Java EE spec.

    The JTA transaction manager’s job is to manage the participants (called resources) and tell them when to commit, or when to roll back.

    The transaction manager ensures that the whole transaction is atomic, by using two-phase commit on all the resources. Either all actions succeed, or none of them do.

    If you’re running in a Java EE container, then you’ve already got a transaction manager, so check the vendor documentation to find out how to use it.

    But, if you’re not running in a Java EE container (for example, if you’re using Spring Boot), then you can still have XA transactions, you just need to choose a JTA transaction manager, and set it up yourself. Try Narayana or Atomikos TransactionsEssentials.

  • Use XA connection factories (or data sources) for each resource in the transaction

    When defining the connections to your database or message broker, you need to use the XA-specific versions of connection factories.

    You can only have a true XA transaction if you’re using XA connection factories for all of your resources.

    For example:

    • ActiveMQ provides the ActiveMQXAConnectionFactory class

    • Postgresql provides the PGXADataSource class

    • Oracle Advanced Queuing (AQ) provides the AQjmsFactory.getXAConnectionFactory method

    To find how to create an XA connection factory for each of your resources, go to your vendor’s documentation pages.

  • transacted keyword in your Camel route

    The magic keyword transacted, when added to your Camel route, switches Camel’s transactional behaviour on. Adding transacted configures a route (and any following routes) to be transactional.

    You should add the transacted keyword at the start of the transaction, e.g.:

    from("direct:start")
      .transacted()
      //....
    

Summary

So there you have it. When setting up XA transactions for your Camel routes, you need to make sure you have a JTA transaction manager, XA-enabled connection factories for your transaction participants, and the transacted keyword.

If you are missing just one of these things, your application will probably still seem to work, but you won’t have the XA behaviour that you want.

Leave a Comment

You can use Markdown in your comment. To write code, indent lines by 4 spaces.