Getting XA Transactions Working in Glassfish 2.1

In the spirit of following my own advice, I am writing up the blog post I wished I could have found today to help me with a nasty, obscure problem I encountered working on the day job.

The original error that was reported and that I was asked to investigate was this:

java.lang.RuntimeException: Cannot export transaction having non-XA resource: 2-phase commit not possible.

The code in our application that raised this exception was trying to do a remote JNDI lookup and a call to the remote Session bean reference returned from that lookup. We do this in the cluster to centralize a few critical operations to a single node in the cluster. Otherwise, everything in a JEE cluster, especially in Glassfish 2.1, basically just occurs either locally or in a random node. This is not acceptable for managing external resources like a Lucene search index.

A bit of digging hinted that the problem was that our JDBC DataSource was not an XA capable one. We are using PostgreSQL 8.3 and the 603 build of the JDBC 3 drivers for that database. I tried just changing the Datasource Classname for our connection pool in Glassfish’s console to “org.postgresql.xa.PGXADAtaSource” but on restarted and re-deploying got the following error:

java.lang.AbstractMethodError: org.postgresql.jdbc3.Jdbc3Connection.getClientInfo()Ljava/util/Properties;

I had no idea what this meant. Looking up Sun’s API docs for AbstractMethodError, it claims this should be caught at compilation, it refers to a call to a purely virtual, or abstract, method. It’s one of those “this should never happen” errors. I suspected it was a difference in the interfaces bundled in Glassfish 2.1’s database support and the actual concrete classes from the PostgreSQL JDBC driver jar.

I first tried upgrading that jar to build 604, still using the JDBC 3 drivers. Same error occurred at deployment. On a whim, I tried upgrading the driver to JDBC 4. When I did so, bounced the cluster, and re-deployed our application, then the error did not occur.

Nowhere did I find a simple bit of documentation that suggested if you are trying to use XA, or distributed transactions, in a Glassfish 2.1 cluster that you need to use JDBC 4 capable drivers. Seems like a pretty basic requirement. I also could not find any simple documentation that made it clear that making a remote call from one node to another physical node in a cluster requires XA transactions to use transactions at all. That latter point is pretty self evident in retrospect but it is the kind of rule that can stand being repeated and clarified at every opportunity.

Hopefully this is a clear enough description of this weird little problem with enough specifics to save the next person encountering this problem the hassle I had to go through to get it working without error.

5 Replies to “Getting XA Transactions Working in Glassfish 2.1”

  1. This is the kind of thing that I would be looking on StackOverflow.com for if I were having such an issue..
    People are much more likely to find it, others can vote this answer up, or add better answers..

    Now I’d be quite surprised if you hadn’t heard of this website already (as I’ve compared your podcast to the stackoverflow podcast in the past (on twitter)..
    jbd

  2. Hi All,
    I am new to EJB and facing same prob while looking up the rms connection factory. Can any one knw whts going wrong
    Following line gives the excetion
    QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup(“qConnFactory”);
    Exception
    javax.naming.CommunicationException: Can’t find SerialContextProvider [Root exception is java.lang.RuntimeException: Cannot export transaction having non-XA resource: 2-phase commit not possible.]
    at com.sun.enterprise.naming.SerialContext.getProvider(SerialContext.java:164)
    at com.sun.enterprise.naming.SerialContext.lookup(SerialContext.java:409)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)

    1. Is the connection factory in question XA capable? In the web console, if you edit the connection factory under Resources -> JMS Resources -> Connection Factories, there is a Transaction Support setting you can change to “XATransaction”. That is the first thing I would try. Also, where are you executing the sample code? In the container, in a managed component? If so, say in a Session bean, is it within the scope of a container managed transaction? That may also make a difference if you are trying to connect to a destination that is transactional from some code that is outside of the transaction managers reach or outside of even a manual transaction.

  3. Thanks Thomas , i got
    JTS5064: Unexpected exception occurred while delisting the resource
    javax.transaction.xa.XAException: Invalid transaction state (Status = 0x0)
    at com.jbase.jremote.io.JConnectionImpl.end(Unknown Source)
    at com.sun.jts.jta.TransactionState.beforeCompletion(TransactionState.java:160)
    at com.sun.jts.jta.SynchronizationImpl.before_completion(SynchronizationImpl.java:135)
    error and finally i changed the Connection factories as per your advice now it was working fine.

Leave a Reply

Your email address will not be published. Required fields are marked *