import javax.sql.XAConnection; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; import com.mysql.jdbc.jdbc2.optional.SuspendableXAConnection; import junit.framework.TestCase; /** * * @author Tony Bussieres * */ public class TestPinnedXAConnection extends TestCase { public void testXAPinnedConnection() throws Exception { MysqlXADataSource xads1 = new MysqlXADataSource(); MysqlXADataSource xads2 = new MysqlXADataSource(); xads1.setPinGlobalTxToPhysicalConnection(true); xads1.setUrl("jdbc:mysql://172.16.13.74:4040/TestDB"); xads1.setUser("testuser"); xads1.setPassword("testpass"); xads1.setLogXaCommands(true); xads2.setPinGlobalTxToPhysicalConnection(true); xads2.setUrl("jdbc:mysql://172.16.13.74:4040/TestDB2"); xads2.setUser("testuser"); xads2.setPassword("testpass"); xads2.setLogXaCommands(true); Xid txid = new MyXid(new byte[] { 0x1 }, new byte[] {0xF}); // fake Xid XAConnection c1 = xads1.getXAConnection(); assertTrue(c1 instanceof SuspendableXAConnection); // start a transaction on one connection c1.getXAResource().start(txid, XAResource.TMNOFLAGS); c1.getXAResource().end(txid, XAResource.TMSUCCESS); XAConnection c2 = xads2.getXAConnection(); assertTrue(c2 instanceof SuspendableXAConnection); // prepare on another one. Since we are using a "pinned" connection we should have the same "currentXAConnection" for both SuspendableXAConnection c2.getXAResource().prepare(txid); // this will fail without the patch. c2.getXAResource().commit(txid,false); /* stack trace generated without the patch : * com.mysql.jdbc.jdbc2.optional.MysqlXAException: XAER_RMFAIL: The command cannot be executed when global transaction is in the NON-EXISTING state at com.mysql.jdbc.jdbc2.optional.MysqlXAConnection.mapXAExceptionFromSQLException(MysqlXAConnection.java:600) at com.mysql.jdbc.jdbc2.optional.MysqlXAConnection.dispatchCommand(MysqlXAConnection.java:583) at com.mysql.jdbc.jdbc2.optional.MysqlXAConnection.prepare(MysqlXAConnection.java:385) at com.mysql.jdbc.jdbc2.optional.SuspendableXAConnection.prepare(SuspendableXAConnection.java:136) at TestXA.testXAPinnedConnection(TestXA.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at junit.framework.TestCase.runTest(TestCase.java:154) at junit.framework.TestCase.runBare(TestCase.java:127) at junit.framework.TestResult$1.protect(TestResult.java:106) at junit.framework.TestResult.runProtected(TestResult.java:124) at junit.framework.TestResult.run(TestResult.java:109) at junit.framework.TestCase.run(TestCase.java:118) at junit.framework.TestSuite.runTest(TestSuite.java:208) at junit.framework.TestSuite.run(TestSuite.java:203) at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) */ } class MyXid implements Xid { byte[] gtxid; byte[] brid; public MyXid(byte[] gtxid, byte[] brid) { this.gtxid = gtxid; this.brid = brid; } public byte[] getBranchQualifier() { return brid; } public int getFormatId() { return 0; } public byte[] getGlobalTransactionId() { return gtxid; } } }