As for JDBC, Atomikos TransactionsEssentials® comes bundled with a XA-compliant JMS connection pool.
A JMS server that supports JMS with XA should ship with a client library that implements the javax.jms.XAConnectionFactory. Refer to the Third-Party JMS/XA Configuration to get information on supported server's XAConnectionFactory.
Unlike the non-XA JMS ConnectionFactory class, XAConnectionFactory is not meant to be directly used by an application programmer. It is supposed to be used internally by XA-compliant connection pools. In clear: you should never use XAConnectionFactory in your code.
As explained in Using an external connection pool with TransactionsEssentials you cannot use a non-XA connection pool so Atomikos TransactionsEssentials® comes bundled with a XA-compliant JMS connection pool represented by the class !AtomikosConnectionFactoryBean.
AtomikosConnectionFactoryBean takes care of resource enlistment and delistment for you. You do not have to call Transaction methods like enlistResource and delistResource. You also don't have to care about recovery as this is also handled fully transparently.
Just remember that if you use an AtomikosConnectionFactoryBean all the complexities of XA are transparenlty taken care of.
The AtomikosConnectionFactoryBean class is - as the name suggests - a pure simple javabean. It wraps a XAConnectionFactory and pools connections while presenting a javax.jms.ConnectionFactory to the application programmer.
It is easy to setup by using its setter methods but can also be easily built from a Spring BeanFactory. Here is an example of code that creates a AtomikosConnectionFactoryBean with 5 connections in the pool:
XAConnectionFactory xacf = ... //construct vendor-specific xa connectionfactory AtomikosConnectionFactoryBean cf = new AtomikosConnectionFactoryBean(); cf.setUniqueResourceName("oracle"); cf.setXaConnectionFactory ( xacf ); cf.setPoolSize ( 5 );
You can then use it like you'd use a normal ConnectionFactory:
Connection c = cf.getConnection(); // ... make use of the connection c.close();
Connections acquired from AtomikosConnectionFactoryBean support both XA and non-XA transactions. XA transactions, make sure to create a Session with transacted=true...
For non-XA transactions, either:
Sometimes the order of commits is important. This See mostly happens if you have the following use case: CommitOrderingWithJms for details...
Now participant no. 1 will be committed before participant no. 2, which means that there’s a race condition between when process B consumes the message and when the database transaction has completed.
Solution: use separate jms connection factories for receive/send: this will give 3 participants, and a commit order (for the participants in the XA transaction) as: (1)jms-receive (2) db (3) jms-send.