/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* 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 javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.XAConnection;
import javax.jms.XASession;
import javax.naming.InitialContext;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.jboss.jms.client.JBossConnectionFactory;
import org.jboss.jms.tx.ResourceManagerFactory;
import org.jboss.messaging.core.tx.MessagingXid;
import org.jboss.test.messaging.MessagingTestCase;
import org.jboss.test.messaging.tools.ServerManagement;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.jta.xa.XidImple;
/**
*
* A XARecoveryTest
*
* @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
* @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>
* @version <tt>$Revision: 2270 $</tt>
*
* $Id: XARecoveryTest.java 2270 2007-02-11 20:04:36Z timfox $
*
*/
public class XARecoveryTest extends MessagingTestCase
{
// Constants -----------------------------------------------------
// Static --------------------------------------------------------
// Attributes ----------------------------------------------------
protected InitialContext initialContext;
protected JBossConnectionFactory cf;
protected Destination queue, queueA, queueB, queueTX, topicTX;
// Constructors --------------------------------------------------
public XARecoveryTest(String name)
{
super(name);
}
// TestCase overrides -------------------------------------------
public void setUp() throws Exception
{
super.setUp();
ServerManagement.start("all");
initialContext = new InitialContext(ServerManagement.getJNDIEnvironment());
cf = (JBossConnectionFactory)initialContext.lookup("/ConnectionFactory");
ServerManagement.undeployQueue("Queue");
ServerManagement.deployQueue("Queue");
ServerManagement.undeployQueue("QA");
ServerManagement.deployQueue("QA");
ServerManagement.undeployQueue("QB");
ServerManagement.deployQueue("QB");
ServerManagement.undeployQueue("TXQ");
ServerManagement.deployQueue("TXQ");
ServerManagement.undeployTopic("TXTOPIC");
ServerManagement.deployTopic("TXTOPIC");
queue = (Destination)initialContext.lookup("/queue/Queue");
queueA = (Destination)initialContext.lookup("/queue/QA");
queueB = (Destination)initialContext.lookup("/queue/QB");
queueTX = (Destination)initialContext.lookup("/queue/TXQ");
topicTX = (Destination)initialContext.lookup("/topic/TXTOPIC");
drainDestination(cf, queue);
drainDestination(cf, queueA);
drainDestination(cf, queueB);
drainDestination(cf, queueTX);
}
public void tearDown() throws Exception
{
ServerManagement.undeployQueue("Queue");
ServerManagement.undeployQueue("QA");
ServerManagement.undeployQueue("QB");
ServerManagement.undeployQueue("TXQ");
ServerManagement.undeployTopic("TXTOPIC");
ResourceManagerFactory.instance.clear();
super.tearDown();
}
// Public --------------------------------------------------------
/*
* In this test, we have two queues, each with four messages already in them.
*
* We send 4 more messages to each queue, and ack the original 4 in a tx
*
* Then recover it without restarting the server
*
*/
public void testComplexTransactionalRecoveryWithoutRestart() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(queueA);
MessageProducer prod2 = sess1.createProducer(queueB);
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
TextMessage tm5 = sess1.createTextMessage("tm5");
TextMessage tm6 = sess1.createTextMessage("tm6");
TextMessage tm7 = sess1.createTextMessage("tm7");
TextMessage tm8 = sess1.createTextMessage("tm8");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
conn1.close();
conn2 = cf.createXAConnection();
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod3 = sess2.createProducer(queueA);
TextMessage tm9 = sess2.createTextMessage("tm9");
TextMessage tm10 = sess2.createTextMessage("tm10");
TextMessage tm11 = sess2.createTextMessage("tm11");
TextMessage tm12 = sess2.createTextMessage("tm12");
prod3.send(tm9);
prod3.send(tm10);
prod3.send(tm11);
prod3.send(tm12);
MessageProducer prod4 = sess2.createProducer(queueB);
TextMessage tm13 = sess2.createTextMessage("tm13");
TextMessage tm14 = sess2.createTextMessage("tm14");
TextMessage tm15 = sess2.createTextMessage("tm15");
TextMessage tm16 = sess2.createTextMessage("tm16");
prod4.send(tm13);
prod4.send(tm14);
prod4.send(tm15);
prod4.send(tm16);
MessageConsumer cons1 = sess2.createConsumer(queueA);
TextMessage rm1 = (TextMessage)cons1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)cons1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)cons1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)cons1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = cons1.receive(1000);
assertNull(m);
MessageConsumer cons2 = sess2.createConsumer(queueB);
TextMessage rm5 = (TextMessage)cons2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)cons2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)cons2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)cons2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = cons2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
log.trace("Preparing xid " + xid1);
res.prepare(xid1);
log.trace("Prepared xid " + xid1);
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("Committing the tx");
//Commit
res3.commit(xids[0], false);
log.trace("committed the tx");
conn1.close();
conn2.close();
conn1 = cf.createConnection();
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
log.trace("creating a consumer");
cons1 = sess1.createConsumer(queueA);
log.trace("created a consumer");
TextMessage rm9 = (TextMessage)cons1.receive(1000);
assertNotNull(rm9);
assertEquals(tm9.getText(), rm9.getText());
TextMessage rm10 = (TextMessage)cons1.receive(1000);
assertNotNull(rm10);
assertEquals(tm10.getText(), rm10.getText());
TextMessage rm11 = (TextMessage)cons1.receive(1000);
assertNotNull(rm11);
assertEquals(tm11.getText(), rm11.getText());
TextMessage rm12 = (TextMessage)cons1.receive(1000);
assertNotNull(rm12);
assertEquals(tm12.getText(), rm12.getText());
m = cons1.receive(1000);
assertNull(m);
cons2 = sess1.createConsumer(queueB);
TextMessage rm13 = (TextMessage)cons2.receive(1000);
assertNotNull(rm13);
assertEquals(tm13.getText(), rm13.getText());
TextMessage rm14 = (TextMessage)cons2.receive(1000);
assertNotNull(rm14);
assertEquals(tm14.getText(), rm14.getText());
TextMessage rm15 = (TextMessage)cons2.receive(1000);
assertNotNull(rm15);
assertEquals(tm15.getText(), rm15.getText());
TextMessage rm16 = (TextMessage)cons2.receive(1000);
assertNotNull(rm16);
assertEquals(tm16.getText(), rm16.getText());
m = cons2.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
conn1.close();
}
if (conn2 != null)
{
conn2.close();
}
if (conn3 != null)
{
conn3.close();
}
}
}
/*
* In this test, we have two queues, each with four messages already in them.
*
* We send 4 more messages to each queue, and ack the original 4 in a tx
*
* Then recover it without restarting the server, then rollback
*
*/
public void testComplexTransactionalRecoveryWithoutRestartRollback() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(queueA);
MessageProducer prod2 = sess1.createProducer(queueB);
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
TextMessage tm5 = sess1.createTextMessage("tm5");
TextMessage tm6 = sess1.createTextMessage("tm6");
TextMessage tm7 = sess1.createTextMessage("tm7");
TextMessage tm8 = sess1.createTextMessage("tm8");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
conn2 = cf.createXAConnection();
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod3 = sess2.createProducer(queueA);
TextMessage tm9 = sess2.createTextMessage("tm9");
TextMessage tm10 = sess2.createTextMessage("tm10");
TextMessage tm11 = sess2.createTextMessage("tm11");
TextMessage tm12 = sess2.createTextMessage("tm12");
prod3.send(tm9);
prod3.send(tm10);
prod3.send(tm11);
prod3.send(tm12);
MessageProducer prod4 = sess2.createProducer(queueB);
TextMessage tm13 = sess2.createTextMessage("tm13");
TextMessage tm14 = sess2.createTextMessage("tm14");
TextMessage tm15 = sess2.createTextMessage("tm15");
TextMessage tm16 = sess2.createTextMessage("tm16");
prod4.send(tm13);
prod4.send(tm14);
prod4.send(tm15);
prod4.send(tm16);
MessageConsumer cons1 = sess2.createConsumer(queueA);
TextMessage rm1 = (TextMessage)cons1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)cons1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)cons1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)cons1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = cons1.receive(1000);
assertNull(m);
MessageConsumer cons2 = sess2.createConsumer(queueB);
TextMessage rm5 = (TextMessage)cons2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)cons2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)cons2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)cons2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = cons2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
res.prepare(xid1);
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("rolling back the tx");
//rollback
res3.rollback(xids[0]);
log.trace("rolledb back the tx");
Thread.sleep(1000);
conn1.close();
conn2.close();
conn1 = cf.createConnection();
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
log.trace("creating a consumer");
cons1 = sess1.createConsumer(queueA);
log.trace("created a consumer");
TextMessage rm9 = (TextMessage)cons1.receive(1000);
assertNotNull(rm9);
assertEquals(tm1.getText(), rm9.getText());
TextMessage rm10 = (TextMessage)cons1.receive(1000);
assertNotNull(rm10);
assertEquals(tm2.getText(), rm10.getText());
TextMessage rm11 = (TextMessage)cons1.receive(1000);
assertNotNull(rm11);
assertEquals(tm3.getText(), rm11.getText());
TextMessage rm12 = (TextMessage)cons1.receive(1000);
assertNotNull(rm12);
assertEquals(tm4.getText(), rm12.getText());
m = cons1.receive(1000);
assertNull(m);
cons2 = sess1.createConsumer(queueB);
TextMessage rm13 = (TextMessage)cons2.receive(1000);
assertNotNull(rm13);
assertEquals(tm5.getText(), rm13.getText());
TextMessage rm14 = (TextMessage)cons2.receive(1000);
assertNotNull(rm14);
assertEquals(tm6.getText(), rm14.getText());
TextMessage rm15 = (TextMessage)cons2.receive(1000);
assertNotNull(rm15);
assertEquals(tm7.getText(), rm15.getText());
TextMessage rm16 = (TextMessage)cons2.receive(1000);
assertNotNull(rm16);
assertEquals(tm8.getText(), rm16.getText());
m = cons2.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* In this test, we have two queues, each with four messages already in them.
*
* We send 4 more messages to each queue, and ack the original 4 in a tx
*
* Then recover it after restarting the server
*
*/
public void testComplexTransactionalRecoveryWithRestart() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(queueA);
MessageProducer prod2 = sess1.createProducer(queueB);
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
TextMessage tm5 = sess1.createTextMessage("tm5");
TextMessage tm6 = sess1.createTextMessage("tm6");
TextMessage tm7 = sess1.createTextMessage("tm7");
TextMessage tm8 = sess1.createTextMessage("tm8");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
conn2 = cf.createXAConnection();
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod3 = sess2.createProducer(queueA);
TextMessage tm9 = sess2.createTextMessage("tm9");
TextMessage tm10 = sess2.createTextMessage("tm10");
TextMessage tm11 = sess2.createTextMessage("tm11");
TextMessage tm12 = sess2.createTextMessage("tm12");
prod3.send(tm9);
prod3.send(tm10);
prod3.send(tm11);
prod3.send(tm12);
MessageProducer prod4 = sess2.createProducer(queueB);
TextMessage tm13 = sess2.createTextMessage("tm13");
TextMessage tm14 = sess2.createTextMessage("tm14");
TextMessage tm15 = sess2.createTextMessage("tm15");
TextMessage tm16 = sess2.createTextMessage("tm16");
prod4.send(tm13);
prod4.send(tm14);
prod4.send(tm15);
prod4.send(tm16);
MessageConsumer cons1 = sess2.createConsumer(queueA);
TextMessage rm1 = (TextMessage)cons1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)cons1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)cons1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)cons1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = cons1.receive(1000);
assertNull(m);
MessageConsumer cons2 = sess2.createConsumer(queueB);
TextMessage rm5 = (TextMessage)cons2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)cons2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)cons2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)cons2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = cons2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
res.prepare(xid1);
conn1 = null;
conn2 = null;
// Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("QA");
ServerManagement.deployQueue("QB");
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("Committing the tx");
//Commit
res3.commit(xids[0], false);
log.trace("committed the tx");
conn1 = cf.createConnection();
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
log.trace("creating a consumer");
cons1 = sess1.createConsumer(queueA);
log.trace("created a consumer");
TextMessage rm9 = (TextMessage)cons1.receive(1000);
assertNotNull(rm9);
assertEquals(tm9.getText(), rm9.getText());
TextMessage rm10 = (TextMessage)cons1.receive(1000);
assertNotNull(rm10);
assertEquals(tm10.getText(), rm10.getText());
TextMessage rm11 = (TextMessage)cons1.receive(1000);
assertNotNull(rm11);
assertEquals(tm11.getText(), rm11.getText());
TextMessage rm12 = (TextMessage)cons1.receive(1000);
assertNotNull(rm12);
assertEquals(tm12.getText(), rm12.getText());
m = cons1.receive(1000);
assertNull(m);
cons2 = sess1.createConsumer(queueB);
TextMessage rm13 = (TextMessage)cons2.receive(1000);
assertNotNull(rm13);
assertEquals(tm13.getText(), rm13.getText());
TextMessage rm14 = (TextMessage)cons2.receive(1000);
assertNotNull(rm14);
assertEquals(tm14.getText(), rm14.getText());
TextMessage rm15 = (TextMessage)cons2.receive(1000);
assertNotNull(rm15);
assertEquals(tm15.getText(), rm15.getText());
TextMessage rm16 = (TextMessage)cons2.receive(1000);
assertNotNull(rm16);
assertEquals(tm16.getText(), rm16.getText());
m = cons2.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* In this test, we have two queues, each with four messages already in them.
*
* We send 4 more messages to each queue, and ack the original 4 in a tx
*
* Then recover it after restarting the server, then rollback
*
*/
public void testComplexTransactionalRecoveryWithRestartRollback() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(queueA);
MessageProducer prod2 = sess1.createProducer(queueB);
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
TextMessage tm5 = sess1.createTextMessage("tm5");
TextMessage tm6 = sess1.createTextMessage("tm6");
TextMessage tm7 = sess1.createTextMessage("tm7");
TextMessage tm8 = sess1.createTextMessage("tm8");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
conn2 = cf.createXAConnection();
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod3 = sess2.createProducer(queueA);
TextMessage tm9 = sess2.createTextMessage("tm9");
TextMessage tm10 = sess2.createTextMessage("tm10");
TextMessage tm11 = sess2.createTextMessage("tm11");
TextMessage tm12 = sess2.createTextMessage("tm12");
prod3.send(tm9);
prod3.send(tm10);
prod3.send(tm11);
prod3.send(tm12);
MessageProducer prod4 = sess2.createProducer(queueB);
TextMessage tm13 = sess2.createTextMessage("tm13");
TextMessage tm14 = sess2.createTextMessage("tm14");
TextMessage tm15 = sess2.createTextMessage("tm15");
TextMessage tm16 = sess2.createTextMessage("tm16");
prod4.send(tm13);
prod4.send(tm14);
prod4.send(tm15);
prod4.send(tm16);
MessageConsumer cons1 = sess2.createConsumer(queueA);
TextMessage rm1 = (TextMessage)cons1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)cons1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)cons1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)cons1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = cons1.receive(1000);
assertNull(m);
MessageConsumer cons2 = sess2.createConsumer(queueB);
TextMessage rm5 = (TextMessage)cons2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)cons2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)cons2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)cons2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = cons2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
res.prepare(xid1);
conn1 = null;
conn2 = null;
// Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("QA");
ServerManagement.deployQueue("QB");
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("rolling back the tx");
//rollback
res3.rollback(xids[0]);
log.trace("rolled back the tx");
Thread.sleep(1000);
conn1 = cf.createConnection();
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
log.trace("creating a consumer");
cons1 = sess1.createConsumer(queueA);
log.trace("created a consumer");
TextMessage rm9 = (TextMessage)cons1.receive(1000);
assertNotNull(rm9);
assertEquals(tm1.getText(), rm9.getText());
TextMessage rm10 = (TextMessage)cons1.receive(1000);
assertNotNull(rm10);
assertEquals(tm2.getText(), rm10.getText());
TextMessage rm11 = (TextMessage)cons1.receive(1000);
assertNotNull(rm11);
assertEquals(tm3.getText(), rm11.getText());
TextMessage rm12 = (TextMessage)cons1.receive(1000);
assertNotNull(rm12);
assertEquals(tm4.getText(), rm12.getText());
m = cons1.receive(1000);
assertNull(m);
cons2 = sess1.createConsumer(queueB);
TextMessage rm13 = (TextMessage)cons2.receive(1000);
assertNotNull(rm13);
assertEquals(tm5.getText(), rm13.getText());
TextMessage rm14 = (TextMessage)cons2.receive(1000);
assertNotNull(rm14);
assertEquals(tm6.getText(), rm14.getText());
TextMessage rm15 = (TextMessage)cons2.receive(1000);
assertNotNull(rm15);
assertEquals(tm7.getText(), rm15.getText());
TextMessage rm16 = (TextMessage)cons2.receive(1000);
assertNotNull(rm16);
assertEquals(tm8.getText(), rm16.getText());
m = cons2.receive(1000);
assertNull(m);
cons1.close();
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/* Not really necessary - but it does no harm */
public void testComplexTransactional() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(queueA);
MessageProducer prod2 = sess1.createProducer(queueB);
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
TextMessage tm5 = sess1.createTextMessage("tm5");
TextMessage tm6 = sess1.createTextMessage("tm6");
TextMessage tm7 = sess1.createTextMessage("tm7");
TextMessage tm8 = sess1.createTextMessage("tm8");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
conn2 = cf.createXAConnection();
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod3 = sess2.createProducer(queueA);
TextMessage tm9 = sess2.createTextMessage("tm9");
TextMessage tm10 = sess2.createTextMessage("tm10");
TextMessage tm11 = sess2.createTextMessage("tm11");
TextMessage tm12 = sess2.createTextMessage("tm12");
prod3.send(tm9);
prod3.send(tm10);
prod3.send(tm11);
prod3.send(tm12);
MessageProducer prod4 = sess2.createProducer(queueB);
TextMessage tm13 = sess2.createTextMessage("tm13");
TextMessage tm14 = sess2.createTextMessage("tm14");
TextMessage tm15 = sess2.createTextMessage("tm15");
TextMessage tm16 = sess2.createTextMessage("tm16");
prod4.send(tm13);
prod4.send(tm14);
prod4.send(tm15);
prod4.send(tm16);
MessageConsumer cons1 = sess2.createConsumer(queueA);
TextMessage rm1 = (TextMessage)cons1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)cons1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)cons1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)cons1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = cons1.receive(1000);
assertNull(m);
MessageConsumer cons2 = sess2.createConsumer(queueB);
TextMessage rm5 = (TextMessage)cons2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)cons2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)cons2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)cons2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = cons2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
res.prepare(xid1);
res.commit(xid1, false);
conn1.close();
conn2.close();
conn1 = cf.createConnection();
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
cons1 = sess1.createConsumer(queueA);
TextMessage rm9 = (TextMessage)cons1.receive(1000);
assertNotNull(rm9);
assertEquals(tm9.getText(), rm9.getText());
TextMessage rm10 = (TextMessage)cons1.receive(1000);
assertNotNull(rm10);
assertEquals(tm10.getText(), rm10.getText());
TextMessage rm11 = (TextMessage)cons1.receive(1000);
assertNotNull(rm11);
assertEquals(tm11.getText(), rm11.getText());
TextMessage rm12 = (TextMessage)cons1.receive(1000);
assertNotNull(rm12);
assertEquals(tm12.getText(), rm12.getText());
m = cons1.receive(1000);
assertNull(m);
cons2 = sess1.createConsumer(queueB);
TextMessage rm13 = (TextMessage)cons2.receive(1000);
assertNotNull(rm13);
assertEquals(tm13.getText(), rm13.getText());
TextMessage rm14 = (TextMessage)cons2.receive(1000);
assertNotNull(rm14);
assertEquals(tm14.getText(), rm14.getText());
TextMessage rm15 = (TextMessage)cons2.receive(1000);
assertNotNull(rm15);
assertEquals(tm15.getText(), rm15.getText());
TextMessage rm16 = (TextMessage)cons2.receive(1000);
assertNotNull(rm16);
assertEquals(tm16.getText(), rm16.getText());
m = cons2.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/* A simple send in a transaction - recovered without restarting the server */
public void testSimpleTransactionalSendRecoveryWithoutRestart() throws Exception
{
log.trace("starting testSimpleTransactionalDeliveryRecoveryWithoutRestart");
XAConnection conn1 = null;
Connection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XAResource res1 = sess1.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
log.trace("Sending message");
//Send message in tx
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queueTX);
TextMessage tm1 = sess1.createTextMessage("tm1");
prod1.send(tm1);
res1.end(xid1, XAResource.TMSUCCESS);
log.trace("Sent message");
//prepare tx
res1.prepare(xid1);
log.trace("prepared tx");
conn2 = cf.createConnection();
Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons2 = sess2.createConsumer(queueTX);
conn2.start();
//Verify message can't be received
Message m = cons2.receive(1000);
assertNull(m);
//Now recover
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
// Verify message still can't be received
m = cons2.receive(1000);
assertNull(m);
//Commit the tx
res1.commit(xids[0], false);
//The message should now be available
TextMessage rm1 = (TextMessage)cons2.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/* A simple send in a transaction - recovered after restarting the server */
public void testSimpleTransactionalSendRecoveryWithRestart() throws Exception
{
log.trace("starting testSimpleTransactionalDeliveryRecoveryWithRestart");
XAConnection conn1 = null;
Connection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XAResource res1 = sess1.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
log.trace("Sending message");
//Send message in tx
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queueTX);
TextMessage tm1 = sess1.createTextMessage("tm1");
prod1.send(tm1);
res1.end(xid1, XAResource.TMSUCCESS);
log.trace("Sent message");
//prepare tx
res1.prepare(xid1);
log.trace("prepared tx");
conn2 = cf.createConnection();
Session sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons2 = sess2.createConsumer(queueTX);
conn2.start();
//Verify message can't be received
Message m = cons2.receive(1000);
assertNull(m);
conn1 = null;
conn2 = null;
// Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("TXQ");
log.trace("Restarted");
//Now recover
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
log.trace("created connection");
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("recovered");
conn2 = cf.createConnection();
sess2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
cons2 = sess2.createConsumer(queueTX);
conn2.start();
// Verify message still can't be received
m = cons2.receive(1000);
assertNull(m);
log.trace("still can't see message");
//Commit the tx
res3.commit(xids[0], false);
log.trace("committed");
//The message should now be available
TextMessage rm1 = (TextMessage)cons2.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/* A simple acknowledgement in a transaction, recovered without restart */
public void testSimpleTransactionalAcknowledgementRecoveryWithoutRestart() throws Exception
{
log.trace("starting testSimpleTransactionalAcknowledgementRecovery");
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
//First send a message to the queue
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sess1.createProducer(queueTX);
TextMessage tm1 = sess1.createTextMessage("tm1");
prod.send(tm1);
conn2 = cf.createXAConnection();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res1.start(xid1, XAResource.TMNOFLAGS);
MessageConsumer cons = sess2.createConsumer(queueTX);
conn2.start();
//Consume the message
TextMessage rm1 = (TextMessage)cons.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
res1.end(xid1, XAResource.TMSUCCESS);
//prepare the tx
res1.prepare(xid1);
//Now recover
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
//Commit the tx
res1.commit(xids[0], false);
//The message should be acknowldged
conn1.close();
conn2.close();
conn3.close();
conn1 = cf.createConnection();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons1 = sess1.createConsumer(queueTX);
conn1.start();
Message m = cons1.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/* A simple acknowledgement in a transaction, recovered with restart */
public void testSimpleTransactionalAcknowledgementRecoveryWithRestart() throws Exception
{
log.trace("starting testSimpleTransactionalAcknowledgementRecoveryWithRestart");
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
//First send a message to the queue
conn1 = cf.createConnection();
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod = sess1.createProducer(queueTX);
TextMessage tm1 = sess1.createTextMessage("tm1");
prod.send(tm1);
conn2 = cf.createXAConnection();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res1.start(xid1, XAResource.TMNOFLAGS);
MessageConsumer cons = sess2.createConsumer(queueTX);
conn2.start();
//Consume the message
TextMessage rm1 = (TextMessage)cons.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
res1.end(xid1, XAResource.TMSUCCESS);
//prepare the tx
res1.prepare(xid1);
conn1 = null;
conn2 = null;
// Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("TXQ");
//Now recover
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
//Commit the tx
res3.commit(xids[0], false);
//The message should be acknowldged
conn3.close();
conn1 = cf.createConnection();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons1 = sess1.createConsumer(queueTX);
conn1.start();
Message m = cons1.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* In this test, we have 4 messages in a 2 durable subs on the same topic.
*
* We ack them, then add four more messages
*
* This test tests for the recovery when the same message is in multiple channels
*
* We don't restart in this test
*
*/
public void testRecoveryWithTwoDurableSubsWithoutRestart() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
conn1.setClientID("wib1");
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(topicTX);
MessageConsumer sub1 = sess1.createDurableSubscriber((Topic)topicTX, "sub1");
MessageConsumer sub2 = sess1.createDurableSubscriber((Topic)topicTX, "sub2");
//send four messages
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
conn1.close();
//The messages should now be in both durable subs
conn2 = cf.createXAConnection();
conn2.setClientID("wib1");
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
//Now send four more messages in a global tx
MessageProducer prod2 = sess2.createProducer(topicTX);
TextMessage tm5 = sess2.createTextMessage("tm5");
TextMessage tm6 = sess2.createTextMessage("tm6");
TextMessage tm7 = sess2.createTextMessage("tm7");
TextMessage tm8 = sess2.createTextMessage("tm8");
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
//And consume the first four from each in the tx
sub1 = sess2.createDurableSubscriber((Topic)topicTX, "sub1");
sub2 = sess2.createDurableSubscriber((Topic)topicTX, "sub2");
TextMessage rm1 = (TextMessage)sub1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)sub1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)sub1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)sub1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = sub1.receive(1000);
assertNull(m);
rm1 = (TextMessage)sub2.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
rm2 = (TextMessage)sub2.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
rm3 = (TextMessage)sub2.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
rm4 = (TextMessage)sub2.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
m = sub2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
res.prepare(xid1);
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
//recover
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("Committing the tx");
//Commit
res3.commit(xids[0], false);
log.trace("committed the tx");
conn2.close();
conn1 = cf.createConnection();
conn1.setClientID("wib1");
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
//Should now see the last 4 messages
sub1 = sess1.createDurableSubscriber((Topic)topicTX, "sub1");
sub2 = sess1.createDurableSubscriber((Topic)topicTX, "sub2");
TextMessage rm5 = (TextMessage)sub1.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)sub1.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)sub1.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)sub1.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = sub1.receive(1000);
assertNull(m);
rm5 = (TextMessage)sub2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
rm6 = (TextMessage)sub2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
rm7 = (TextMessage)sub2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
rm8 = (TextMessage)sub2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = sub2.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* In this test, we have 4 messages in a 2 durable subs on the same topic.
*
* We ack them, then add four more messages
*
* This test tests for the recovery when the same message is in multiple channels
*
* We do restart in this test
*
*/
public void testRecoveryWithTwoDurableSubsWithRestart() throws Exception
{
Connection conn1 = null;
XAConnection conn2 = null;
XAConnection conn3 = null;
try
{
conn1 = cf.createConnection();
conn1.setClientID("wib1");
Session sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer prod1 = sess1.createProducer(topicTX);
MessageConsumer sub1 = sess1.createDurableSubscriber((Topic)topicTX, "sub1");
MessageConsumer sub2 = sess1.createDurableSubscriber((Topic)topicTX, "sub2");
//send four messages
TextMessage tm1 = sess1.createTextMessage("tm1");
TextMessage tm2 = sess1.createTextMessage("tm2");
TextMessage tm3 = sess1.createTextMessage("tm3");
TextMessage tm4 = sess1.createTextMessage("tm4");
prod1.send(tm1);
prod1.send(tm2);
prod1.send(tm3);
prod1.send(tm4);
conn1.close();
//The messages should now be in both durable subs
conn2 = cf.createXAConnection();
conn2.setClientID("wib1");
conn2.start();
XASession sess2 = conn2.createXASession();
XAResource res = sess2.getXAResource();
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
res.start(xid1, XAResource.TMNOFLAGS);
//Now send four more messages in a global tx
MessageProducer prod2 = sess2.createProducer(topicTX);
TextMessage tm5 = sess2.createTextMessage("tm5");
TextMessage tm6 = sess2.createTextMessage("tm6");
TextMessage tm7 = sess2.createTextMessage("tm7");
TextMessage tm8 = sess2.createTextMessage("tm8");
prod2.send(tm5);
prod2.send(tm6);
prod2.send(tm7);
prod2.send(tm8);
//And consume the first four from each in the tx
sub1 = sess2.createDurableSubscriber((Topic)topicTX, "sub1");
sub2 = sess2.createDurableSubscriber((Topic)topicTX, "sub2");
TextMessage rm1 = (TextMessage)sub1.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
TextMessage rm2 = (TextMessage)sub1.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
TextMessage rm3 = (TextMessage)sub1.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
TextMessage rm4 = (TextMessage)sub1.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
Message m = sub1.receive(1000);
assertNull(m);
rm1 = (TextMessage)sub2.receive(1000);
assertNotNull(rm1);
assertEquals(tm1.getText(), rm1.getText());
rm2 = (TextMessage)sub2.receive(1000);
assertNotNull(rm2);
assertEquals(tm2.getText(), rm2.getText());
rm3 = (TextMessage)sub2.receive(1000);
assertNotNull(rm3);
assertEquals(tm3.getText(), rm3.getText());
rm4 = (TextMessage)sub2.receive(1000);
assertNotNull(rm4);
assertEquals(tm4.getText(), rm4.getText());
m = sub2.receive(1000);
assertNull(m);
res.end(xid1, XAResource.TMSUCCESS);
//prepare it
res.prepare(xid1);
conn1 = null;
conn2 = null;
// Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployTopic("TXTOPIC");
conn3 = cf.createXAConnection();
XASession sess3 = conn3.createXASession();
XAResource res3 = sess3.getXAResource();
//recover
Xid[] xids = res3.recover(XAResource.TMSTARTRSCAN);
assertEquals(1, xids.length);
Xid[] xids2 = res3.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertEquals(xid1, xids[0]);
log.trace("Committing the tx");
//Commit
res3.commit(xids[0], false);
log.trace("committed the tx");
conn1 = cf.createConnection();
conn1.setClientID("wib1");
conn1.start();
sess1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);
//Should now see the last 4 messages
sub1 = sess1.createDurableSubscriber((Topic)topicTX, "sub1");
sub2 = sess1.createDurableSubscriber((Topic)topicTX, "sub2");
TextMessage rm5 = (TextMessage)sub1.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
TextMessage rm6 = (TextMessage)sub1.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
TextMessage rm7 = (TextMessage)sub1.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
TextMessage rm8 = (TextMessage)sub1.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = sub1.receive(1000);
assertNull(m);
rm5 = (TextMessage)sub2.receive(1000);
assertNotNull(rm5);
assertEquals(tm5.getText(), rm5.getText());
rm6 = (TextMessage)sub2.receive(1000);
assertNotNull(rm6);
assertEquals(tm6.getText(), rm6.getText());
rm7 = (TextMessage)sub2.receive(1000);
assertNotNull(rm7);
assertEquals(tm7.getText(), rm7.getText());
rm8 = (TextMessage)sub2.receive(1000);
assertNotNull(rm8);
assertEquals(tm8.getText(), rm8.getText());
m = sub2.receive(1000);
assertNull(m);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* Send two messages in two transactions.
* Prepare tx
* Crash the server
* Restart the server
* Make sure the messages can be received
* NOTE this test only tests transactional sends, not transactional acknowledgments
*
*/
public void testTransactionalDeliveryRecovery() throws Exception
{
log.trace("starting testTransactionalDeliveryRecovery");
XAConnection conn1 = null;
XAConnection conn2 = null;
Connection conn3 = null;
try
{
conn1 = cf.createXAConnection();
conn2 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess1.getXAResource();
XAResource res2 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "eemeli".getBytes());
Xid xid2 = new MessagingXid("bq2".getBytes(), 42, "frigtard".getBytes());
log.trace("Sending messages");
//Send two messages in transaction 1
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queueTX);
TextMessage tm1 = sess1.createTextMessage("tm1");
prod1.send(tm1);
TextMessage tm2 = sess1.createTextMessage("tm2");
prod1.send(tm2);
res1.end(xid1, XAResource.TMSUCCESS);
//Send two messages in transaction 2
res2.start(xid2, XAResource.TMNOFLAGS);
MessageProducer prod2 = sess2.createProducer(queueTX);
TextMessage tm3 = sess2.createTextMessage("tm3");
prod2.send(tm3);
TextMessage tm4 = sess2.createTextMessage("tm4");
prod2.send(tm4);
res2.end(xid2, XAResource.TMSUCCESS);
log.trace("Sent messages");
//prepare both txs
res1.prepare(xid1);
res2.prepare(xid2);
log.trace("prepared messages");
//Now "crash" the server
conn1 = null;
conn2 = null;
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("TXQ");
//Try and recover
XAResource res = cf.createXAConnection().createXASession().getXAResource();
log.trace("Recovering");
Xid[] xids = res.recover(XAResource.TMSTARTRSCAN);
assertEquals(2, xids.length);
Xid[] xids2 = res.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
//They may be in a different order
assertTrue(xids[0].equals(xid1) || xids[1].equals(xid1));
assertTrue(xids[0].equals(xid2) || xids[1].equals(xid2));
//Make sure can't receive the messages
log.trace("Creating conn");
conn3 = cf.createConnection();
Session sessRec = conn3.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons = sessRec.createConsumer(queueTX);
conn3.start();
log.trace("Created conn3");
TextMessage m1 = (TextMessage)cons.receive(1000);
assertNull(m1);
log.trace("comitting");
//Commit tx1
res.commit(xid1, false);
log.trace("comitted");
//Should now be able to receive tm1 and tm2
m1 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m1);
assertEquals(tm1.getText(), m1.getText());
TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m2);
assertEquals(tm2.getText(), m2.getText());
TextMessage m3 = (TextMessage)cons.receive(1000);
assertNull(m3);
//Now commit tx2
res.commit(xid2, false);
//Should now be able to receive tm3 and tm4
m3 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m3);
assertEquals(tm3.getText(), m3.getText());
TextMessage m4 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m4);
assertEquals(tm4.getText(), m4.getText());
TextMessage m5 = (TextMessage)cons.receive(1000);
assertNull(m5);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* This test sends some messages in a couple of txs, crashes then recovers
* NOTE it does not test transactional acknowledgements
*/
public void testMockCoordinatorRecovery() throws Exception
{
XAConnection conn1 = null;
XAConnection conn2 = null;
Connection conn3 = null;
try
{
conn1 = cf.createXAConnection();
conn2 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess1.getXAResource();
XAResource res2 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 42, "aapeli".getBytes());
Xid xid2 = new MessagingXid("bq2".getBytes(), 42, "belsebub".getBytes());
// Send a message in each tx
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queueA);
TextMessage tm1 = sess1.createTextMessage("alpha");
prod1.send(tm1);
res1.end(xid1, XAResource.TMSUCCESS);
res2.start(xid2, XAResource.TMNOFLAGS);
MessageProducer prod2 = sess2.createProducer(queueA);
TextMessage tm2 = sess2.createTextMessage("beta");
prod2.send(tm2);
res2.end(xid2, XAResource.TMSUCCESS);
//prepare both txs
res1.prepare(xid1);
res2.prepare(xid2);
//Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("QA");
XAResource res = cf.createXAConnection().createXASession().getXAResource();
Xid[] xids = res.recover(XAResource.TMSTARTRSCAN);
assertEquals(2, xids.length);
Xid[] xids2 = res.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertTrue(xids[0].equals(xid1) || xids[1].equals(xid1));
assertTrue(xids[0].equals(xid2) || xids[1].equals(xid2));
res.commit(xid1, false);
res.commit(xid2, false);
conn3 = cf.createConnection();
Session sessRec = conn3.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons = sessRec.createConsumer(queueA);
conn3.start();
Message msg = cons.receive(MAX_TIMEOUT);
TextMessage m1 = (TextMessage)msg;
assertNotNull(m1);
assertTrue("alpha".equals(m1.getText()) ||
"beta".equals(m1.getText()));
TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m2);
assertTrue("alpha".equals(m2.getText()) ||
"beta".equals(m2.getText()));
assertTrue(!tm1.getText().equals(tm2.getText()));
Message nullMessage = cons.receive(MIN_TIMEOUT);
assertTrue(nullMessage == null);
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
/*
* This test sends some messages in a couple of txs, crashes then recovers
* It uses the JBoss TS XId implementation - so we can show compatibility
* NOTE it does not test transactional acknowledgements
*/
public void testMockCoordinatorRecoveryWithJBossTSXids() throws Exception
{
XAConnection conn1 = null;
XAConnection conn2 = null;
Connection conn3 = null;
try
{
conn1 = cf.createXAConnection();
conn2 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess1.getXAResource();
XAResource res2 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new XidImple(new Uid("cadaver"), new Uid("bq1"), 666);
Xid xid2 = new XidImple(new Uid("dalidom"), new Uid("bq2"), 661); // TODO
// Send a message in each tx
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queue);
TextMessage tm1 = sess1.createTextMessage("testing1");
prod1.send(tm1);
res1.end(xid1, XAResource.TMSUCCESS);
res2.start(xid2, XAResource.TMNOFLAGS);
MessageProducer prod2 = sess2.createProducer(queue);
TextMessage tm2 = sess2.createTextMessage("testing2");
prod2.send(tm2);
res2.end(xid2, XAResource.TMSUCCESS);
//prepare both txs
res1.prepare(xid1);
res2.prepare(xid2);
//Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("Queue");
XAResource res = cf.createXAConnection().createXASession().getXAResource();
Xid[] xids = res.recover(XAResource.TMSTARTRSCAN);
assertEquals(2, xids.length);
Xid[] xids2 = res.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertTrue(xids[0].equals(xid1) || xids[1].equals(xid1));
assertTrue(xids[0].equals(xid2) || xids[1].equals(xid2));
res.commit(xid1, false);
res.commit(xid2, false);
conn3 = cf.createConnection();
Session sessRec = conn3.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons = sessRec.createConsumer(queue);
conn3.start();
TextMessage m1 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m1);
assertEquals("testing1", m1.getText());
TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m2);
assertEquals("testing2", m2.getText());
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
public void testMockCoordinatorRecovery3() throws Exception
{
XAConnection conn1 = null;
XAConnection conn2 = null;
Connection conn3 = null;
try
{
conn1 = cf.createXAConnection();
conn2 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess1.getXAResource();
XAResource res2 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 123, "gbtxid1".getBytes());
Xid xid2 = new MessagingXid("bq2".getBytes(), 124, "gbtxid2".getBytes());
// Send a message in each tx
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queue);
TextMessage tm1 = sess1.createTextMessage("testing1");
prod1.send(tm1);
res1.end(xid1, XAResource.TMSUCCESS);
res2.start(xid2, XAResource.TMNOFLAGS);
MessageProducer prod2 = sess2.createProducer(queue);
TextMessage tm2 = sess2.createTextMessage("testing2");
prod2.send(tm2);
res2.end(xid2, XAResource.TMSUCCESS);
//prepare both txs
res1.prepare(xid1);
res2.prepare(xid2);
//Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("Queue");
XAResource res = cf.createXAConnection().createXASession().getXAResource();
Xid[] xids = res.recover(XAResource.TMSTARTRSCAN);
assertEquals(2, xids.length);
Xid[] xids2 = res.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertTrue(xids[0].equals(xid1) || xids[1].equals(xid1));
assertTrue(xids[0].equals(xid2) || xids[1].equals(xid2));
res.commit(xids[0], false);
res.commit(xids[1], false);
conn3 = cf.createConnection();
Session sessRec = conn3.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons = sessRec.createConsumer(queue);
conn3.start();
TextMessage m1 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m1);
assertEquals("testing1", m1.getText());
TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT);
assertNotNull(m2);
assertEquals("testing2", m2.getText());
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
public void testMultiChannelRecovery() throws Exception
{
XAConnection conn1 = null;
XAConnection conn2 = null;
Connection conn3 = null;
try
{
conn1 = cf.createXAConnection();
conn2 = cf.createXAConnection();
XASession sess1 = conn1.createXASession();
XASession sess2 = conn2.createXASession();
XAResource res1 = sess1.getXAResource();
XAResource res2 = sess2.getXAResource();
//Pretend to be a transaction manager by interacting through the XAResources
Xid xid1 = new MessagingXid("bq1".getBytes(), 123, "gbtxid1".getBytes());
Xid xid2 = new MessagingXid("bq2".getBytes(), 124, "gbtxid2".getBytes());
// Send a message in each tx
res1.start(xid1, XAResource.TMNOFLAGS);
MessageProducer prod1 = sess1.createProducer(queueA);
MessageProducer prod2 = sess1.createProducer(queueB);
TextMessage tm1 = sess1.createTextMessage("testing1");
TextMessage tm2 = sess1.createTextMessage("testing2");
prod1.send(tm1);
prod2.send(tm2);
res1.end(xid1, XAResource.TMSUCCESS);
res2.start(xid2, XAResource.TMNOFLAGS);
MessageProducer prod3 = sess2.createProducer(queue);
TextMessage tm3 = sess2.createTextMessage("testing3");
prod3.send(tm3);
res2.end(xid2, XAResource.TMSUCCESS);
//prepare both txs
res1.prepare(xid1);
res2.prepare(xid2);
//Now "crash" the server
ServerManagement.stopServerPeer();
ServerManagement.startServerPeer();
ServerManagement.deployQueue("Queue");
ServerManagement.deployQueue("QA");
ServerManagement.deployQueue("QB");
XAResource res = cf.createXAConnection().createXASession().getXAResource();
Xid[] xids = res.recover(XAResource.TMSTARTRSCAN);
assertEquals(2, xids.length);
Xid[] xids2 = res.recover(XAResource.TMENDRSCAN);
assertEquals(0, xids2.length);
assertTrue(xids[0].equals(xid1) || xids[1].equals(xid1));
assertTrue(xids[0].equals(xid2) || xids[1].equals(xid2));
res.commit(xids[0], false);
res.commit(xids[1], false);
conn3 = cf.createConnection();
Session sessRec = conn3.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageConsumer cons1 = sessRec.createConsumer(queueA);
MessageConsumer cons2 = sessRec.createConsumer(queueB);
MessageConsumer cons3 = sessRec.createConsumer(queue);
conn3.start();
TextMessage m1 = (TextMessage)cons1.receive(MAX_TIMEOUT);
assertNotNull(m1);
assertEquals("testing1", m1.getText());
TextMessage m2 = (TextMessage)cons2.receive(MAX_TIMEOUT);
assertNotNull(m2);
assertEquals("testing2", m2.getText());
TextMessage m3 = (TextMessage)cons3.receive(MAX_TIMEOUT);
assertNotNull(m3);
assertEquals("testing3", m3.getText());
if (checkNoMessageData())
{
fail("Data remains in database");
}
}
finally
{
if (conn1 != null)
{
try
{
conn1.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn2 != null)
{
try
{
conn2.close();
}
catch (Exception e)
{
//Ignore
}
}
if (conn3 != null)
{
try
{
conn3.close();
}
catch (Exception e)
{
//Ignore
}
}
}
}
}