I'm entering the world of JTA, due to need of distributed transactions, and I'm uncertain about the differences between javax.jms.ConnectionFactory
and javax.jms.XAConnectionFactory
or more accurately how can it be that javax.jms.ConnectionFactory
performed what I expected only javax.jms.XAConnectionFactory
can do for me.
The details: I'm using Atomikos essentials as my transaction manager and my app is running on Apache Tomcat 6.
I'm running a small POC with a dummy app where I have my JMS provider (OpenMQ
) registered as a JNDI
resource.
<Resource name="jms/myConnectionFactory" auth="Container"
type="com.atomikos.jms.AtomikosConnectionFactoryBean"
factory="com.atomikos.tomcat.EnhancedTomcatAtomikosBeanFactory"
uniqueResourceName="jms/myConnectionFactory"
xaConnectionFactoryClassName="com.sun.messaging.XAConnectionFactory"
maxPoolSize="3"/>
And the strange issue is that in my code I do this:
Context ctx = new InitialContext();
ConnectionFactory queueConnectionFactory =
(ConnectionFactory)ctx.lookup("java:comp/env/jms/myQueueFactory");
javax.jms.Connection connection = queueConnectionFactory.createConnection();
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
And later in the code I use this session in a UserTransaction
and it performs flawlessly with two MessageProducer
s with either Commit
or Rollback
.
What I don't understand is how can it be that I'm using javax.jms.XAConnectionFactory.createConnection()
method and I get a Session
which does the job? What's javax.jms.XAConnectionFactory
role?
I'll also add that I've looked at the source code of both classes (and javax.jms.BasicConnectionFactory
) and I verified that the XA class does not override createConnection
.
The core of the difference between ConnectionFactory and XAConnectionFactory is that the XAConnectionFactory creates XAConnections which create XASessions. XASessions represent the real difference because (to quote from the JMS JavaDocs:)
The XASession interface extends the capability of Session by adding access to a JMS provider's support for the Java Transaction API (JTA) (optional). This support takes the form of a javax.transaction.xa.XAResource object.
In other words, the XASession is what gives the XA instances their transactional awareness. However, this specific implementation is optional, even for a fully compliant JMS provider. From the same JavaDoc:
An XAResource provides some fairly sophisticated facilities for interleaving work on multiple transactions, recovering a list of transactions in progress, and so on. A JTA aware JMS provider must fully implement this functionality. This could be done by using the services of a database that supports XA, or a JMS provider may choose to implement this functionality from scratch. A client of the application server is given what it thinks is a regular JMS Session. Behind the scenes, the application server controls the transaction management of the underlying XASession.
In other words, the provider may require that you specify an XA or non-XA JMS resource, or, as would seem to be in your case, the provider may perform all the JTA plumbing transparently with what appears to be a regular JMS Session.