/* * JBoss, Home of Professional Open Source * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.messaging.jms; import java.util.ArrayList; import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.ServerSession; import javax.jms.ServerSessionPool; import javax.jms.Session; import javax.jms.TextMessage; import javax.jms.XAConnection; import javax.jms.XASession; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import org.jboss.messaging.core.client.impl.ClientSessionImpl; import org.jboss.messaging.core.logging.Logger; import org.jboss.messaging.core.transaction.impl.XidImpl; import org.jboss.messaging.jms.client.JBossConnectionFactory; import org.jboss.test.messaging.JBMServerTestCase; import org.jboss.test.messaging.tools.ServerManagement; import org.jboss.tm.TransactionManagerLocator; import org.jboss.tm.TxUtils; import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple; /** * * A XATestBase * * @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a> * @author <a href="mailto:clebert.suconic@jboss.com">Clebert Suconic</a> * @version <tt>$Revision: 1.1 $</tt> * * $Id$ * */ public class XATest extends JBMServerTestCase { // Constants ----------------------------------------------------- // Static -------------------------------------------------------- // Attributes ---------------------------------------------------- protected TransactionManager tm; protected Transaction suspendedTx; protected JBossConnectionFactory cf; // Constructors -------------------------------------------------- public XATest(String name) { super(name); } // TestCase overrides ------------------------------------------- public void setUp() throws Exception { super.setUp(); cf = getConnectionFactory(); tm = TransactionManagerLocator.getInstance().getTransactionManager();//this.getTransactionManager(); assertTrue(tm instanceof TransactionManagerImple); if (!ServerManagement.isRemote()) { suspendedTx = tm.suspend(); } } public void tearDown() throws Exception { if (TxUtils.isUncommitted(tm)) { //roll it back try { tm.rollback(); } catch (Throwable ignore) { //The connection will probably be closed so this may well throw an exception } } if (tm.getTransaction() != null) { Transaction tx = tm.suspend(); if (tx != null) log.warn("Transaction still associated with thread " + tx + " at status " + TxUtils.getStatusAsString(tx.getStatus())); } if (suspendedTx != null) { tm.resume(suspendedTx); } super.tearDown(); } // Public -------------------------------------------------------- // See http://jira.jboss.org/jira/browse/JBMESSAGING-825 // Need to test that ids with trailing zeros are dealt with properly - sybase has the habit // of truncating trailing zeros in varbinary columns public void testXidsWithTrailingZeros() throws Exception { if (!ServerManagement.isRemote()) { return; } XAConnection conn1 = null; try { conn1 = cf.createXAConnection(); XASession sess1 = conn1.createXASession(); XAResource res1 = sess1.getXAResource(); byte[] branchQualifier = new byte[] { 1, 2, 3, 4, 5, 6, 0, 0, 0, 0 }; byte[] globalTxId = new byte[] { 6, 5, 4, 3, 2, 1, 0, 0, 0, 0 }; Xid trailing = new XidImpl(branchQualifier, 12435, globalTxId); res1.start(trailing, XAResource.TMNOFLAGS); MessageProducer prod1 = sess1.createProducer(queue1); TextMessage tm1 = sess1.createTextMessage("testing1"); prod1.send(tm1); res1.end(trailing, XAResource.TMSUCCESS); res1.prepare(trailing); //Now "crash" the server stopServerPeer(); startServerPeer(); deployAndLookupAdministeredObjects(); conn1.close(); conn1 = cf.createXAConnection(); XAResource res = conn1.createXASession().getXAResource(); Xid[] xids = res.recover(XAResource.TMSTARTRSCAN); assertEquals(1, xids.length); Xid[] xids2 = res.recover(XAResource.TMENDRSCAN); assertEquals(0, xids2.length); Xid trailing2 = xids[0]; assertTrue(trailing.getFormatId() == trailing2.getFormatId()); assertEqualByteArrays(trailing.getGlobalTransactionId(), trailing2.getGlobalTransactionId()); assertEqualByteArrays(trailing.getBranchQualifier(), trailing2.getBranchQualifier()); res.commit(trailing, false); } finally { removeAllMessages(queue1.getQueueName(), true, 0); if (conn1 != null) { try { conn1.close(); } catch (Exception e) { //Ignore } } } } public void test2PCSendCommit1PCOptimization() throws Exception { //Since both resources have same RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(1000); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(1000); assertNotNull(m2); assertEquals("XATest2", m2.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCSendCommit() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); XAResource res2 = new DummyXAResource(); //To prevent 1PC optimization being used //res.setForceNotSameRM(true); Transaction tx = tm.getTransaction(); log.info("res is " + res); log.info("res2 is " + res2); log.info("Enlisting reousrce1"); tx.enlistResource(res); log.info("enlisting resource2"); tx.enlistResource(res2); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); log.info("Committing***"); tm.commit(); log.info("Committed****"); conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCSendRollback1PCOptimization() throws Exception { //Since both resources have some RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.rollback(); conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); Message m2 = cons.receive(MIN_TIMEOUT); assertNull(m2); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCSendFailOnPrepare() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); //prevent 1Pc optimisation //res.setForceNotSameRM(true); XAResource res2 = new DummyXAResource(true); XAResource res3 = new DummyXAResource(); XAResource res4 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); tx.enlistResource(res3); tx.enlistResource(res4); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tx.delistResource(res3, XAResource.TMSUCCESS); tx.delistResource(res4, XAResource.TMSUCCESS); try { tm.commit(); fail("should not get here"); } catch (Exception e) { //We should expect this } conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); Message m2 = cons.receive(MIN_TIMEOUT); assertNull(m2); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCSendRollback() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); //prevent 1Pc optimisation //res.setForceNotSameRM(true); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.rollback(); conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); Message m2 = cons.receive(MIN_TIMEOUT); assertNull(m2); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCReceiveCommit1PCOptimization() throws Exception { //Since both resources have some RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn2 = cf.createConnection(); conn2.start(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("XATest1"); prod.send(m); m = sessProducer.createTextMessage("XATest2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageConsumer cons = sess.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); //New tx tm.begin(); tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); Message m3 = cons.receive(MIN_TIMEOUT); assertNull(m3); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCReceiveCommit() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn2 = cf.createConnection(); conn2.start(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("XATest1"); prod.send(m); m = sessProducer.createTextMessage("XATest2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = (XAResource)sess.getXAResource(); //res.setForceNotSameRM(true); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageConsumer cons = sess.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); //New tx tm.begin(); tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); Message m3 = cons.receive(MIN_TIMEOUT); assertNull(m3); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCReceiveRollback1PCOptimization() throws Exception { //Since both resources have some RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("XATest1"); prod.send(m); m = sessProducer.createTextMessage("XATest2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageConsumer cons = sess.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); log.info("rolling back"); tm.rollback(); //Message should be redelivered //New tx tm.begin(); tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); TextMessage m3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m3); assertEquals("XATest1", m3.getText()); m3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m3); assertEquals("XATest2", m3.getText()); assertTrue(m3.getJMSRedelivered()); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test2PCReceiveRollback() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("XATest1"); prod.send(m); m = sessProducer.createTextMessage("XATest2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); //res.setForceNotSameRM(true); XAResource res2 = new DummyXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); MessageConsumer cons = sess.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.rollback(); //Message should be redelivered //New tx tm.begin(); tx = tm.getTransaction(); tx.enlistResource(res); tx.enlistResource(res2); TextMessage m3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m3); assertEquals("XATest1", m3.getText()); m3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m3); assertEquals("XATest2", m3.getText()); assertTrue(m3.getJMSRedelivered()); tx.delistResource(res, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.commit(); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test1PCSendCommit() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tm.commit(); conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test1PCSendRollback() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); MessageProducer prod = sess.createProducer(queue1); prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT); Message m = sess.createTextMessage("XATest1"); prod.send(queue1, m); m = sess.createTextMessage("XATest2"); prod.send(queue1, m); tx.delistResource(res, XAResource.TMSUCCESS); tm.rollback(); conn2 = cf.createConnection(); conn2.start(); Session sessReceiver = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sessReceiver.createConsumer(queue1); Message m2 = cons.receive(MIN_TIMEOUT); assertNull(m2); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test1PCReceiveCommit() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn2 = cf.createConnection(); conn2.start(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("XATest1"); prod.send(m); m = sessProducer.createTextMessage("XATest2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); MessageConsumer cons = sess.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); tx.delistResource(res, XAResource.TMSUCCESS); tm.commit(); //New tx tm.begin(); tx = tm.getTransaction(); tx.enlistResource(res); Message m3 = cons.receive(MIN_TIMEOUT); assertNull(m3); tx.delistResource(res, XAResource.TMSUCCESS); tm.commit(); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void test1PCReceiveRollback() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("XATest1"); prod.send(m); m = sessProducer.createTextMessage("XATest2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess = conn.createXASession(); XAResource res = sess.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res); MessageConsumer cons = sess.createConsumer(queue1); TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest1", m2.getText()); m2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m2); assertEquals("XATest2", m2.getText()); tx.delistResource(res, XAResource.TMSUCCESS); tm.rollback(); //Message should be redelivered //New tx tm.begin(); tx = tm.getTransaction(); tx.enlistResource(res); TextMessage m3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m3); assertEquals("XATest1", m3.getText()); m3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(m3); assertEquals("XATest2", m3.getText()); assertTrue(m3.getJMSRedelivered()); tx.delistResource(res, XAResource.TMSUCCESS); tm.commit(); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxCommitAcknowledge1PCOptimization() throws Exception { XAConnection conn = null; Connection conn2 = null; //Since both resources have some RM, TM will probably use 1PC optimization try { //First send 2 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); XASession sess2 = conn.createXASession(); XAResource res2 = sess2.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); //Receive the messages, one on each consumer MessageConsumer cons1 = sess1.createConsumer(queue1); TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); cons1.close(); MessageConsumer cons2 = sess2.createConsumer(queue1); TextMessage r2 = (TextMessage)cons2.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish2", r2.getText()); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //commit tm.commit(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r3 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r3); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxCommitAcknowledge() throws Exception { XAConnection conn = null; Connection conn2 = null; try { //First send 2 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); ClientSessionImpl res1 = (ClientSessionImpl)sess1.getXAResource(); XASession sess2 = conn.createXASession(); ClientSessionImpl res2 = (ClientSessionImpl)sess2.getXAResource(); res1.setForceNotSameRM(true); res2.setForceNotSameRM(true); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); //Receive the messages, one on each consumer MessageConsumer cons1 = sess1.createConsumer(queue1); TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); cons1.close(); MessageConsumer cons2 = sess2.createConsumer(queue1); TextMessage r2 = (TextMessage)cons2.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish2", r2.getText()); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //commit tm.commit(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r3 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r3); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxRollbackAcknowledge1PCOptimization() throws Exception { XAConnection conn = null; Connection conn2 = null; //Since both resources have some RM, TM will probably use 1PC optimization try { //First send 2 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); m = sessProducer.createTextMessage("jellyfish3"); prod.send(m); m = sessProducer.createTextMessage("jellyfish4"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); ClientSessionImpl res1 = (ClientSessionImpl)sess1.getXAResource(); XASession sess2 = conn.createXASession(); ClientSessionImpl res2 = (ClientSessionImpl)sess2.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); //Receive the messages, two on each consumer MessageConsumer cons1 = sess1.createConsumer(queue1); TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish2", r1.getText()); cons1.close(); MessageConsumer cons2 = sess2.createConsumer(queue1); TextMessage r2 = (TextMessage)cons2.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish3", r2.getText()); r2 = (TextMessage)cons2.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish4", r2.getText()); cons2.close(); //rollback tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.rollback(); //Rollback causes cancel which is asynch Thread.sleep(1000); //We cannot assume anything about the order in which the transaction manager rollsback //the sessions - this is implementation dependent Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); boolean session1First = false; if (r.getText().equals("jellyfish1")) { session1First = true; } else if (r.getText().equals("jellyfish3")) { session1First = false; } else { fail("Unexpected message"); } if (session1First) { r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish2", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish3", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish4", r.getText()); } else { r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish4", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish1", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish2", r.getText()); } r = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxRollbackAcknowledge() throws Exception { XAConnection conn = null; Connection conn2 = null; try { //First send 2 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); m = sessProducer.createTextMessage("jellyfish3"); prod.send(m); m = sessProducer.createTextMessage("jellyfish4"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); ClientSessionImpl res1 = (ClientSessionImpl)sess1.getXAResource(); XASession sess2 = conn.createXASession(); ClientSessionImpl res2 = (ClientSessionImpl)sess2.getXAResource(); res1.setForceNotSameRM(true); res2.setForceNotSameRM(true); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); //Receive the messages, two on each consumer MessageConsumer cons1 = sess1.createConsumer(queue1); TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish2", r1.getText()); cons1.close(); //Cancel is asynch Thread.sleep(500); MessageConsumer cons2 = sess2.createConsumer(queue1); TextMessage r2 = (TextMessage)cons2.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish3", r2.getText()); r2 = (TextMessage)cons2.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish4", r2.getText()); //rollback cons2.close(); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); tm.rollback(); // Rollback causes cancel which is asynch Thread.sleep(1000); //We cannot assume anything about the order in which the transaction manager rollsback //the sessions - this is implementation dependent Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); boolean session1First = false; if (r.getText().equals("jellyfish1")) { session1First = true; } else if (r.getText().equals("jellyfish3")) { session1First = false; } else { fail("Unexpected message"); } if (session1First) { r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish2", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish3", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish4", r.getText()); } else { r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish4", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish1", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish2", r.getText()); } r = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxRollbackAcknowledgeForceFailureInCommit() throws Exception { XAConnection conn = null; Connection conn2 = null; try { //First send 4 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); m = sessProducer.createTextMessage("jellyfish3"); prod.send(m); m = sessProducer.createTextMessage("jellyfish4"); prod.send(m); conn = cf.createXAConnection(); conn.start(); tm.begin(); XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); DummyXAResource res2 = new DummyXAResource(true); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); MessageConsumer cons1 = sess1.createConsumer(queue1); TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish2", r1.getText()); r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish3", r1.getText()); r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish4", r1.getText()); r1 = (TextMessage)cons1.receive(1000); assertNull(r1); cons1.close(); //try and commit - and we're going to make the dummyxaresource throw an exception on commit, //which should cause rollback to be called on the other resource tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //rollback will cause an attemp to deliver messages locally to the original consumers. //the original consumer has closed, so it will cancelled to the server //the server cancel is asynch, so we need to sleep for a bit to make sure it completes log.trace("Forcing failure"); try { tm.commit(); fail("should not get here"); } catch (Exception e) { //We should expect this } Thread.sleep(1000); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish1", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish2", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish3", r.getText()); r = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r); assertEquals("jellyfish4", r.getText()); r = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxCommitSend1PCOptimization() throws Exception { //Since both resources have some RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); XASession sess2 = conn.createXASession(); XAResource res2 = sess2.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); // Send 2 messages - one from each session MessageProducer prod1 = sess1.createProducer(queue1); MessageProducer prod2 = sess2.createProducer(queue1); prod1.send(sess1.createTextMessage("echidna1")); prod2.send(sess2.createTextMessage("echidna2")); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //commit tm.commit(); //Messages should be in queue conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r1 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("echidna1", r1.getText()); TextMessage r2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("echidna2", r2.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxCommitSend() throws Exception { //Since both resources have some RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); ClientSessionImpl res1 = (ClientSessionImpl)sess1.getXAResource(); XASession sess2 = conn.createXASession(); ClientSessionImpl res2 = (ClientSessionImpl)sess2.getXAResource(); res1.setForceNotSameRM(true); res2.setForceNotSameRM(true); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); // Send 2 messages - one from each session MessageProducer prod1 = sess1.createProducer(queue1); MessageProducer prod2 = sess2.createProducer(queue1); prod1.send(sess1.createTextMessage("echidna1")); prod2.send(sess2.createTextMessage("echidna2")); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //commit tm.commit(); //Messages should be in queue conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r1 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("echidna1", r1.getText()); TextMessage r2 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("echidna2", r2.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxRollbackSend1PCOptimization() throws Exception { //Since both resources have some RM, TM will probably use 1PC optimization XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); XASession sess2 = conn.createXASession(); XAResource res2 = sess2.getXAResource(); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); // Send 2 messages - one from each session MessageProducer prod1 = sess1.createProducer(queue1); MessageProducer prod2 = sess2.createProducer(queue1); prod1.send(sess1.createTextMessage("echidna1")); prod2.send(sess2.createTextMessage("echidna2")); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //rollback tm.rollback(); //Messages should not be in queue conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r1 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r1); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testMultipleSessionsOneTxRollbackSend() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); conn.start(); tm.begin(); //Create 2 sessions and enlist them XASession sess1 = conn.createXASession(); ClientSessionImpl res1 = (ClientSessionImpl)sess1.getXAResource(); XASession sess2 = conn.createXASession(); ClientSessionImpl res2 = (ClientSessionImpl)sess2.getXAResource(); res1.setForceNotSameRM(true); res2.setForceNotSameRM(true); Transaction tx = tm.getTransaction(); tx.enlistResource(res1); tx.enlistResource(res2); // Send 2 messages - one from each session MessageProducer prod1 = sess1.createProducer(queue1); MessageProducer prod2 = sess2.createProducer(queue1); prod1.send(sess1.createTextMessage("echidna1")); prod2.send(sess2.createTextMessage("echidna2")); tx.delistResource(res1, XAResource.TMSUCCESS); tx.delistResource(res2, XAResource.TMSUCCESS); //rollback tm.rollback(); //Messages should not be in queue conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons = sess.createConsumer(queue1); conn2.start(); TextMessage r1 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r1); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testOneSessionTwoTransactionsCommitAcknowledge() throws Exception { XAConnection conn = null; Connection conn2 = null; try { //First send 2 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); conn = cf.createXAConnection(); //Create a session XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); conn.start(); MessageConsumer cons1 = sess1.createConsumer(queue1); tm.begin(); Transaction tx1 = tm.getTransaction(); tx1.enlistResource(res1); //Receive one message in one tx TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); tx1.delistResource(res1, XAResource.TMSUCCESS); //suspend the tx log.info("Calling suspend"); Transaction suspended = tm.suspend(); log.info("Called suspend"); tm.begin(); Transaction tx2 = tm.getTransaction(); tx2.enlistResource(res1); //Receive 2nd message in a different tx TextMessage r2 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish2", r2.getText()); tx2.delistResource(res1, XAResource.TMSUCCESS); //commit this transaction tm.commit(); //verify that no messages are available conn2.close(); conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); conn2.start(); MessageConsumer cons = sess.createConsumer(queue1); TextMessage r3 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r3); //now resume the first tx and then commit it tm.resume(suspended); tm.commit(); log.info("Got to end"); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testOneSessionTwoTransactionsRollbackAcknowledge() throws Exception { XAConnection conn = null; Connection conn2 = null; try { //First send 2 messages conn2 = cf.createConnection(); Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod = sessProducer.createProducer(queue1); Message m = sessProducer.createTextMessage("jellyfish1"); prod.send(m); m = sessProducer.createTextMessage("jellyfish2"); prod.send(m); conn = cf.createXAConnection(); //Create a session XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); conn.start(); MessageConsumer cons1 = sess1.createConsumer(queue1); tm.begin(); Transaction tx1 = tm.getTransaction(); tx1.enlistResource(res1); //Receive one message in one tx TextMessage r1 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("jellyfish1", r1.getText()); tx1.delistResource(res1, XAResource.TMSUCCESS); //suspend the tx Transaction suspended = tm.suspend(); tm.begin(); Transaction tx2 = tm.getTransaction(); tx2.enlistResource(res1); //Receive 2nd message in a different tx TextMessage r2 = (TextMessage)cons1.receive(MAX_TIMEOUT); assertNotNull(r2); assertEquals("jellyfish2", r2.getText()); cons1.close(); tx2.delistResource(res1, XAResource.TMSUCCESS); //rollback this transaction tm.rollback(); //verify that second message is available conn2.close(); conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); conn2.start(); MessageConsumer cons = sess.createConsumer(queue1); TextMessage r3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r3); assertEquals("jellyfish2", r3.getText()); r3 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r3); //rollback the other tx tm.resume(suspended); tm.rollback(); //Verify the first message is now available r3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r3); assertEquals("jellyfish1", r3.getText()); r3 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r3); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testOneSessionTwoTransactionsCommitSend() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); //Create a session XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); MessageProducer prod1 = sess1.createProducer(queue1); tm.begin(); Transaction tx1 = tm.getTransaction(); tx1.enlistResource(res1); //Send a message prod1.send(sess1.createTextMessage("kangaroo1")); tx1.delistResource(res1, XAResource.TMSUCCESS); //suspend the tx Transaction suspended = tm.suspend(); tm.begin(); //Send another message in another tx using the same session Transaction tx2 = tm.getTransaction(); tx2.enlistResource(res1); //Send a message prod1.send(sess1.createTextMessage("kangaroo2")); tx2.delistResource(res1, XAResource.TMSUCCESS); //commit this transaction tm.commit(); //verify only kangaroo2 message is sent conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); conn2.start(); MessageConsumer cons = sess.createConsumer(queue1); TextMessage r1 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r1); assertEquals("kangaroo2", r1.getText()); TextMessage r2 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r2); //now resume the first tx and then commit it tm.resume(suspended); tm.commit(); //verify that the first text message is received TextMessage r3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r3); assertEquals("kangaroo1", r3.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } public void testOneSessionTwoTransactionsRollbackSend() throws Exception { XAConnection conn = null; Connection conn2 = null; try { conn = cf.createXAConnection(); //Create a session XASession sess1 = conn.createXASession(); XAResource res1 = sess1.getXAResource(); MessageProducer prod1 = sess1.createProducer(queue1); tm.begin(); Transaction tx1 = tm.getTransaction(); tx1.enlistResource(res1); //Send a message prod1.send(sess1.createTextMessage("kangaroo1")); //suspend the tx Transaction suspended = tm.suspend(); tm.begin(); //Send another message in another tx using the same session Transaction tx2 = tm.getTransaction(); tx2.enlistResource(res1); //Send a message prod1.send(sess1.createTextMessage("kangaroo2")); tx2.delistResource(res1, XAResource.TMSUCCESS); //rollback this transaction tm.rollback(); //verify no messages are sent conn2 = cf.createConnection(); Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); conn2.start(); MessageConsumer cons = sess.createConsumer(queue1); TextMessage r1 = (TextMessage)cons.receive(MIN_TIMEOUT); assertNull(r1); //now resume the first tx and then commit it tm.resume(suspended); tx1.delistResource(res1, XAResource.TMSUCCESS); tm.commit(); //verify that the first text message is received TextMessage r3 = (TextMessage)cons.receive(MAX_TIMEOUT); assertNotNull(r3); assertEquals("kangaroo1", r3.getText()); } finally { if (conn != null) { conn.close(); } if (conn2 != null) { conn2.close(); } } } // Package protected --------------------------------------------- // Protected ----------------------------------------------------- // Private ------------------------------------------------------- private void assertEqualByteArrays(byte[] b1, byte[] b2) { log.info("b1 length: " + b1.length + " b2 length " + b2.length); if (b1.length != b2.length) { fail("Lengths not the same"); } for (int i = 0; i < b1.length; i++) { if (b1[i] != b2[i]) { fail("Not same at index " + i); } } } // Inner classes ------------------------------------------------- static class DummyListener implements MessageListener { protected Logger log = Logger.getLogger(getClass()); public ArrayList messages = new ArrayList(); public void onMessage(Message message) { log.info("Message received on DummyListener " + message); messages.add(message); } } static class MockServerSessionPool implements ServerSessionPool { private ServerSession serverSession; MockServerSessionPool(Session sess) { serverSession = new MockServerSession(sess); } public ServerSession getServerSession() throws JMSException { return serverSession; } } static class MockServerSession implements ServerSession { Session session; MockServerSession(Session sess) { this.session = sess; } public Session getSession() throws JMSException { return session; } public void start() throws JMSException { session.run(); } } static class DummyXAResource implements XAResource { boolean failOnPrepare; DummyXAResource() { } DummyXAResource(boolean failOnPrepare) { this.failOnPrepare = failOnPrepare; } public void commit(Xid arg0, boolean arg1) throws XAException { } public void end(Xid arg0, int arg1) throws XAException { } public void forget(Xid arg0) throws XAException { } public int getTransactionTimeout() throws XAException { return 0; } public boolean isSameRM(XAResource arg0) throws XAException { return false; } public int prepare(Xid arg0) throws XAException { if (failOnPrepare) { throw new XAException(XAException.XAER_RMFAIL); } return XAResource.XA_OK; } public Xid[] recover(int arg0) throws XAException { return null; } public void rollback(Xid arg0) throws XAException { } public boolean setTransactionTimeout(int arg0) throws XAException { return false; } public void start(Xid arg0, int arg1) throws XAException { } } }