[jboss-cvs] JBoss Messaging SVN: r1845 - in branches/Branch_1_0: . src/etc/server/default/deploy src/main/org/jboss/jms/client/container src/main/org/jboss/jms/server/endpoint src/main/org/jboss/jms/server/plugin src/main/org/jboss/jms/server/plugin/contract src/main/org/jboss/jms/tx src/main/org/jboss/messaging/core src/main/org/jboss/messaging/core/plugin src/main/org/jboss/messaging/core/plugin/contract src/main/org/jboss/messaging/core/tx tests tests/src/org/jboss/test/messaging tests/src/org/jboss/test/messaging/core tests/src/org/jboss/test/messaging/jms

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Dec 21 19:34:26 EST 2006


Author: timfox
Date: 2006-12-21 19:34:08 -0500 (Thu, 21 Dec 2006)
New Revision: 1845

Modified:
   branches/Branch_1_0/.classpath
   branches/Branch_1_0/src/etc/server/default/deploy/mssql-persistence-service.xml
   branches/Branch_1_0/src/etc/server/default/deploy/mysql-persistence-service.xml
   branches/Branch_1_0/src/etc/server/default/deploy/oracle-persistence-service.xml
   branches/Branch_1_0/src/etc/server/default/deploy/postgresql-persistence-service.xml
   branches/Branch_1_0/src/etc/server/default/deploy/sybase-persistence-service.xml
   branches/Branch_1_0/src/main/org/jboss/jms/client/container/SessionAspect.java
   branches/Branch_1_0/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
   branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/JDBCChannelMapper.java
   branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/contract/ChannelMapper.java
   branches/Branch_1_0/src/main/org/jboss/jms/tx/ResourceManager.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/Channel.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/ChannelSupport.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/Transaction.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/TransactionRepository.java
   branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/XidImpl.java
   branches/Branch_1_0/tests/build.xml
   branches/Branch_1_0/tests/src/org/jboss/test/messaging/MessagingTestCase.java
   branches/Branch_1_0/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
   branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XARecoveryTest.java
   branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XATest.java
Log:
Backmerged xa recovery to 1_0 after changes made after merge from 1_0 to trunk



Modified: branches/Branch_1_0/.classpath
===================================================================
--- branches/Branch_1_0/.classpath	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/.classpath	2006-12-22 00:34:08 UTC (rev 1845)
@@ -21,7 +21,6 @@
 	<classpathentry kind="lib" path="lib/jboss-system.jar"/>
 	<classpathentry kind="lib" path="lib/jboss-transaction.jar"/>
 	<classpathentry kind="lib" path="lib/jnp-client.jar"/>
-	<classpathentry kind="lib" path="thirdparty/jboss/common/lib/jboss-common.jar"/>
 	<classpathentry kind="lib" path="thirdparty/oswego-concurrent/lib/concurrent.jar"/>
 	<classpathentry kind="lib" path="tests/lib/jboss-common-jdbc-wrapper.jar"/>
 	<classpathentry kind="lib" path="tests/lib/jboss-jca.jar"/>
@@ -30,15 +29,13 @@
 	<classpathentry kind="lib" path="tests/lib/jms-ra.jar"/>
 	<classpathentry kind="lib" path="tests/lib/mysql-connector-java-3.1.13-bin.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jgroups/lib/jgroups.jar"/>
-	<classpathentry kind="lib" path="perf/resources/jcommon-1.0.0-rc1.jar"/>
-	<classpathentry kind="lib" path="perf/resources/jfreechart-1.0.0-rc1.jar"/>
 	<classpathentry kind="lib" path="thirdparty/apache-log4j/lib/log4j.jar"/>
 	<classpathentry sourcepath="/home/clebert/workspaces/jboss-head/aop/src/main" kind="lib" path="thirdparty/jboss/aop/lib/jboss-aop.jar"/>
 	<classpathentry kind="lib" path="thirdparty/junit/lib/junit.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/profiler/jvmti/lib/jboss-profiler-jvmti.jar"/>
 	<classpathentry kind="lib" path="thirdparty/hsqldb/lib/hsqldb.jar"/>
 	<classpathentry kind="lib" path="thirdparty/apache-logging/lib/commons-logging.jar"/>
-	<classpathentry kind="var" path="ANT_HOME/ant-junit.jar"/>
+	<classpathentry kind="var" path="ANT_HOME/lib/ant-junit.jar"/>
 	<classpathentry sourcepath="/JBossRemoting" kind="lib" path="thirdparty/jboss/remoting/lib/jboss-remoting.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/serialization/lib/jboss-serialization.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
@@ -56,13 +53,14 @@
 	<classpathentry kind="lib" path="thirdparty/jboss/aop/lib/jdk14-pluggable-instrumentor.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/aop/lib/jrockit-pluggable-instrumentor.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/aop/lib/pluggable-instrumentor.jar"/>
-	<classpathentry kind="lib" path="thirdparty/jboss/common/lib/jboss-archive-browsing.jar"/>
-	<classpathentry kind="lib" path="thirdparty/jboss/common/lib/jboss-common-client.jar"/>
-	<classpathentry kind="lib" path="thirdparty/jboss/common/lib/namespace.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/jbossxb/lib/jboss-xml-binding.jar"/>
 	<classpathentry kind="lib" path="thirdparty/retrotranslator/lib/backport-util-concurrent.jar"/>
 	<classpathentry kind="lib" path="thirdparty/retrotranslator/lib/retrotranslator-runtime.jar"/>
 	<classpathentry kind="lib" path="thirdparty/retrotranslator/lib/retrotranslator-transformer.jar"/>
 	<classpathentry kind="lib" path="thirdparty/trove/lib/trove.jar"/>
+	<classpathentry kind="lib" path="thirdparty/jboss/jbossts/lib/jbossjta.jar"/>
+	<classpathentry kind="lib" path="thirdparty/jboss/common-logging-log4j/lib/jboss-logging-log4j.jar"/>
+	<classpathentry kind="lib" path="thirdparty/jboss/common-core/lib/jboss-common-core.jar"/>
+	<classpathentry kind="lib" path="thirdparty/jboss/common-logging-spi/lib/jboss-logging-spi.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>

Modified: branches/Branch_1_0/src/etc/server/default/deploy/mssql-persistence-service.xml
===================================================================
--- branches/Branch_1_0/src/etc/server/default/deploy/mssql-persistence-service.xml	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/etc/server/default/deploy/mssql-persistence-service.xml	2006-12-22 00:34:08 UTC (rev 1845)
@@ -32,11 +32,11 @@
 COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
 ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
 ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
-SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED='N'
-UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE <> '+'
+LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
+SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED='N'
+UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE = 'C'
 UPDATE_RELIABLE_REFS_NOT_LOADED=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='N' WHERE CHANNELID=?
-SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N'
+SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N'
 DELETE_UNRELIABLE_REFS=DELETE FROM JMS_MESSAGE_REFERENCE WHERE RELIABLE = 'N'
 UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
 CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, COREHEADERS IMAGE, PAYLOAD IMAGE, CHANNELCOUNT INTEGER, TYPE TINYINT, JMSTYPE VARCHAR(255), CORRELATIONID VARCHAR(255), CORRELATIONID_BYTES IMAGE, DESTINATION_ID BIGINT, REPLYTO_ID BIGINT, JMSPROPERTIES IMAGE, PRIMARY KEY (MESSAGEID))
@@ -58,6 +58,8 @@
 INSERT_COUNTER=INSERT INTO JMS_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
 DELETE_ALL_COUNTERS=DELETE FROM JMS_COUNTER
 SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNELID) FROM JMS_MESSAGE_REFERENCE
+SELECT_MESSAGEID_FOR_REFS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '+'
+SELECT_MESSAGEID_FOR_ACKS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '-'
            ]]></attribute>
       <attribute name="MaxParams">500</attribute>
    </mbean>

Modified: branches/Branch_1_0/src/etc/server/default/deploy/mysql-persistence-service.xml
===================================================================
--- branches/Branch_1_0/src/etc/server/default/deploy/mysql-persistence-service.xml	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/etc/server/default/deploy/mysql-persistence-service.xml	2006-12-22 00:34:08 UTC (rev 1845)
@@ -32,11 +32,11 @@
 COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
 ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
 ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
-SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED='N'      
-UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE <> '+'      
+LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
+SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED='N'      
+UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE = 'C'      
 UPDATE_RELIABLE_REFS_NOT_LOADED=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='N' WHERE CHANNELID=?  
-SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N'          
+SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N'          
 DELETE_UNRELIABLE_REFS=DELETE FROM JMS_MESSAGE_REFERENCE WHERE RELIABLE = 'N'
 UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
 CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, COREHEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, CHANNELCOUNT INTEGER, TYPE TINYINT, JMSTYPE VARCHAR(255), CORRELATIONID VARCHAR(255), CORRELATIONID_BYTES VARBINARY(254), DESTINATION_ID BIGINT, REPLYTO_ID BIGINT, JMSPROPERTIES MEDIUMBLOB, PRIMARY KEY (MESSAGEID))
@@ -58,6 +58,8 @@
 INSERT_COUNTER=INSERT INTO JMS_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
 DELETE_ALL_COUNTERS=DELETE FROM JMS_COUNTER
 SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNELID) FROM JMS_MESSAGE_REFERENCE
+SELECT_MESSAGEID_FOR_REFS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '+'
+SELECT_MESSAGEID_FOR_ACKS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '-'
       ]]></attribute>
       <attribute name="MaxParams">500</attribute>
    </mbean>

Modified: branches/Branch_1_0/src/etc/server/default/deploy/oracle-persistence-service.xml
===================================================================
--- branches/Branch_1_0/src/etc/server/default/deploy/oracle-persistence-service.xml	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/etc/server/default/deploy/oracle-persistence-service.xml	2006-12-22 00:34:08 UTC (rev 1845)
@@ -32,11 +32,11 @@
 COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
 ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
 ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
-SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED='N'      
-UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE <> '+'      
+LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
+SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED='N'      
+UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE = 'C'      
 UPDATE_RELIABLE_REFS_NOT_LOADED=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='N' WHERE CHANNELID=?   
-SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N'             
+SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N'             
 DELETE_UNRELIABLE_REFS=DELETE FROM JMS_MESSAGE_REFERENCE WHERE RELIABLE = 'N'
 UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
 CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID INTEGER, RELIABLE CHAR(1), EXPIRATION INTEGER, TIMESTAMP INTEGER, PRIORITY INTEGER, COREHEADERS BLOB, PAYLOAD BLOB, CHANNELCOUNT INTEGER, TYPE INTEGER, JMSTYPE VARCHAR2(255), CORRELATIONID VARCHAR2(255), CORRELATIONID_BYTES RAW(254), DESTINATION_ID INTEGER, REPLYTO_ID INTEGER, JMSPROPERTIES BLOB, PRIMARY KEY (MESSAGEID))
@@ -58,6 +58,8 @@
 INSERT_COUNTER=INSERT INTO JMS_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
 DELETE_ALL_COUNTERS=DELETE FROM JMS_COUNTER
 SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNELID) FROM JMS_MESSAGE_REFERENCE
+SELECT_MESSAGEID_FOR_REFS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '+'
+SELECT_MESSAGEID_FOR_ACKS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '-'
       ]]></attribute>
       <attribute name="MaxParams">500</attribute>
    </mbean>      

Modified: branches/Branch_1_0/src/etc/server/default/deploy/postgresql-persistence-service.xml
===================================================================
--- branches/Branch_1_0/src/etc/server/default/deploy/postgresql-persistence-service.xml	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/etc/server/default/deploy/postgresql-persistence-service.xml	2006-12-22 00:34:08 UTC (rev 1845)
@@ -32,11 +32,11 @@
 COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
 ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
 ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
-SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED='N'
-UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE <> '+'
+LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
+SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED='N'
+UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE = 'C'
 UPDATE_RELIABLE_REFS_NOT_LOADED=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='N' WHERE CHANNELID=?
-SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N'
+SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N'
 DELETE_UNRELIABLE_REFS=DELETE FROM JMS_MESSAGE_REFERENCE WHERE RELIABLE = 'N'
 UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
 CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY int2, COREHEADERS BYTEA, PAYLOAD BYTEA, CHANNELCOUNT INTEGER, TYPE int2, JMSTYPE VARCHAR(255), CORRELATIONID VARCHAR(255), CORRELATIONID_BYTES BYTEA, DESTINATION_ID BIGINT, REPLYTO_ID BIGINT, JMSPROPERTIES BYTEA, PRIMARY KEY (MESSAGEID))
@@ -58,6 +58,8 @@
 INSERT_COUNTER=INSERT INTO JMS_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
 DELETE_ALL_COUNTERS=DELETE FROM JMS_COUNTER
 SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNELID) FROM JMS_MESSAGE_REFERENCE
+SELECT_MESSAGEID_FOR_REFS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '+'
+SELECT_MESSAGEID_FOR_ACKS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '-'
            ]]></attribute>
       <attribute name="MaxParams">500</attribute>
    </mbean>

Modified: branches/Branch_1_0/src/etc/server/default/deploy/sybase-persistence-service.xml
===================================================================
--- branches/Branch_1_0/src/etc/server/default/deploy/sybase-persistence-service.xml	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/etc/server/default/deploy/sybase-persistence-service.xml	2006-12-22 00:34:08 UTC (rev 1845)
@@ -41,11 +41,11 @@
 COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
 ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
 ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
-SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED='N'
-UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE <> '+'
+LOAD_REF_INFO=SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N' AND ORD BETWEEN ? AND ? ORDER BY ORD
+SELECT_COUNT_REFS=SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED='N'
+UPDATE_RELIABLE_REFS=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE = 'C'
 UPDATE_RELIABLE_REFS_NOT_LOADED=UPDATE JMS_MESSAGE_REFERENCE SET LOADED='N' WHERE CHANNELID=?
-SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N'
+SELECT_MIN_ORDERING=SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N'
 DELETE_UNRELIABLE_REFS=DELETE FROM JMS_MESSAGE_REFERENCE WHERE RELIABLE = 'N'
 UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
 CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID INTEGER, RELIABLE CHAR(1) NULL, EXPIRATION INTEGER NULL, TIMESTAMP NUMERIC(20,0) NULL, PRIORITY INTEGER NULL, COREHEADERS IMAGE NULL, PAYLOAD IMAGE NULL, CHANNELCOUNT INTEGER NULL, TYPE INTEGER NULL, JMSTYPE VARCHAR(255) NULL, CORRELATIONID VARCHAR(255) NULL, CORRELATIONID_BYTES VARBINARY(254) NULL, DESTINATION_ID INTEGER NULL, REPLYTO_ID INTEGER NULL, JMSPROPERTIES IMAGE NULL, PRIMARY KEY (MESSAGEID))
@@ -66,6 +66,8 @@
 INSERT_COUNTER=INSERT INTO JMS_COUNTER (NAME, NEXT_ID) VALUES (?, ?)
 DELETE_ALL_COUNTERS=DELETE FROM JMS_COUNTER
 SELECT_ALL_CHANNELS=SELECT DISTINCT(CHANNELID) FROM JMS_MESSAGE_REFERENCE
+SELECT_MESSAGEID_FOR_REFS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '+'
+SELECT_MESSAGEID_FOR_ACKS=SELECT MESSAGEID, CHANNELID FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID = ? AND STATE = '-'
       ]]>
 		</attribute>
 	</mbean>

Modified: branches/Branch_1_0/src/main/org/jboss/jms/client/container/SessionAspect.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/jms/client/container/SessionAspect.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/jms/client/container/SessionAspect.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -295,7 +295,7 @@
     */
    public Object handleRedeliver(Invocation invocation) throws Throwable
    {
-      if (trace) { log.trace("redeliver called"); }
+      if (trace) { log.trace(this + " redeliver called"); }
       
       MethodInvocation mi = (MethodInvocation)invocation;
       SessionState state = getState(invocation);
@@ -318,10 +318,15 @@
          {
             // This is ok. The original consumer has closed, this message wil get cancelled back
             // to the channel.
+            
+            if (trace) { log.trace("Original consumer has closed, ddding message " + proxy + " to list of messages to cancel"); }
+            
             toCancel.addFirst(info);
          }
          else
          {
+            if (trace) { log.trace("Adding message " + proxy + " back to front of buffer"); }
+            
             handler.addToFrontOfBuffer(proxy);
          }                                    
       }

Modified: branches/Branch_1_0/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -481,6 +481,8 @@
         
    public synchronized void cancelDeliveries(List ackInfos) throws JMSException
    {
+      if (trace) { log.trace(this + " cancelDeliveries " + ackInfos); }
+      
       try
       {
          if (closed)
@@ -522,6 +524,8 @@
             }
             else
             {            
+               if (trace) { log.trace("Cancelling delivery " + ack.getMessageID()); }
+               
                consumer.cancelDelivery(new Long(ack.getMessageID()), ack.getDeliveryCount());
             }
             

Modified: branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/JDBCChannelMapper.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/JDBCChannelMapper.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/JDBCChannelMapper.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -23,6 +23,7 @@
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 import javax.jms.JMSException;
 import javax.management.MBeanServerInvocationHandler;
@@ -126,6 +127,8 @@
    // Map<clientID - Map<subscriptionName - CoreDurableSubscription>>
    protected Map subscriptions;
    
+   protected Map channelIdSubMap;
+   
    // Map<name - Queue>
    protected Map queues;
    
@@ -159,6 +162,8 @@
       
       idMap = new ConcurrentReaderHashMap();
       
+      channelIdSubMap = new ConcurrentHashMap();
+      
       sqlProperties = new Properties();
       
       populateTables = new ArrayList();
@@ -247,6 +252,12 @@
    {
       return (JBossDestination)idMap.get(new Long(coreDestinationId));
    }      
+   
+   public CoreSubscription getDurableSubscription(long channelID)
+   {
+      return (CoreSubscription)channelIdSubMap.get(new Long(channelID));
+      
+   }
     
    public void deployCoreDestination(boolean isQueue, 
                                      String destName,
@@ -835,6 +846,8 @@
       {
          return null;
       }
+      
+      this.channelIdSubMap.remove(new Long(removed.getChannelID()));
    
       if (subs.size() == 0)
       {
@@ -1167,6 +1180,8 @@
       
       subs.put(subscriptionName, subscription);
       
+      channelIdSubMap.put(new Long(id), subscription);
+      
       return subscription;
    }   
    

Modified: branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/contract/ChannelMapper.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/contract/ChannelMapper.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/jms/server/plugin/contract/ChannelMapper.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -15,6 +15,7 @@
 import org.jboss.jms.server.subscription.DurableSubscription;
 import org.jboss.jms.server.subscription.Subscription;
 import org.jboss.messaging.core.local.CoreDestination;
+import org.jboss.messaging.core.local.CoreSubscription;
 import org.jboss.messaging.core.memory.MemoryManager;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
@@ -99,5 +100,7 @@
    void setPersistenceManager(PersistenceManager pm) throws Exception;
    
    void setQueuedExecutorPool(QueuedExecutorPool pool) throws Exception;
+   
+   CoreSubscription getDurableSubscription(long channelID);
 
 }

Modified: branches/Branch_1_0/src/main/org/jboss/jms/tx/ResourceManager.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/jms/tx/ResourceManager.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/jms/tx/ResourceManager.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -246,6 +246,8 @@
          tx.clearMessages();
       }
       
+      //it's possible the tx may not be here since the transaction manager is calling commit
+      //as part of the recovery process before recover is called
       if ((tx == null) || tx.getState() == TxState.TX_PREPARED)
       {
          request = new TransactionRequest(TransactionRequest.TWO_PHASE_ROLLBACK_REQUEST, xid, tx);
@@ -264,7 +266,12 @@
       
       try
       {
-         redeliverMessages(tx);
+         if (tx != null)
+         {
+            redeliverMessages(tx);
+            
+            tx.setState(TxState.TX_ROLLEDBACK);
+         }
       }
       catch (JMSException e)
       {
@@ -282,6 +289,8 @@
       // Sort messages into lists, one for each session. We use a LinkedHashMap since we need to
       // preserve the order of the sessions.
 
+      if (trace) { log.trace("Redelivering messages locally: " + ts.getAcks()); }
+      
       Map toAck = new LinkedHashMap();
 
       for(Iterator i = ts.getAcks().iterator(); i.hasNext(); )
@@ -296,7 +305,7 @@
             toAck.put(del, acks);
          }
          acks.add(ack);
-      }
+      }            
       
       // Now tell each session to redeliver.
       
@@ -309,11 +318,15 @@
          l.addFirst(entry);
       }
       
+      if (trace) { log.trace("There are " + l.size() + " sessions to redeliver locally"); }
+      
       for(Iterator i = l.iterator(); i.hasNext();)
       {
          Map.Entry entry = (Map.Entry)i.next();
          SessionDelegate sess = (SessionDelegate)entry.getKey();
          List acks = (List)entry.getValue();
+         
+         if (trace) { log.trace("Redelivering to sess " + sess); }
          sess.redeliver(acks);
       }  
    }
@@ -452,15 +465,23 @@
          try
          {
             Xid[] txs = conn.getPreparedTransactions();
+            
+            //Note- we only want to do replace the tx, if it doesn't already exist -
+            //remember recover can be called when the connection is still alive -
+            //we do not want to lose the client side transactional state!
 
             //populate with TxState --MK
-            for(int i = 0; i < txs.length;i++)
+            for( int i = 0; i < txs.length;i++)
             {
-               TxState tx = new TxState();
-
-               tx.setState(TxState.TX_PREPARED);
-
-               transactions.put(txs[i], tx);
+               // Don't overwrite if it is already there
+               if (!transactions.containsKey(txs[i]))
+               {
+                  TxState tx = new TxState();
+   
+                  tx.setState(TxState.TX_PREPARED);
+      
+                  transactions.put(txs[i], tx);            
+               }
             }
 
             return txs;

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/Channel.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/Channel.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/Channel.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -141,6 +141,8 @@
     * @throws Throwable
     */
    void removeAllReferences() throws Throwable;
+   
+   void addDelivery(Delivery del);
 
 }
 

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/ChannelSupport.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/ChannelSupport.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/ChannelSupport.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -413,9 +413,18 @@
          router.clear();
          router = null;
       }
+   }
 
+   
+   public void addDelivery(Delivery del)
+   {
+      synchronized (deliveryLock)
+      {
+         deliveries.add(del);
+      }
    }
 
+
    /*
     * This method clears the channel.
     * Basically it acknowledges any outstanding deliveries and consumes the rest of the messages in the channel.

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -36,10 +36,12 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 
 import javax.management.MBeanServer;
 import javax.management.MBeanServerInvocationHandler;
@@ -54,6 +56,7 @@
 import org.jboss.jms.message.JBossMessage;
 import org.jboss.jms.server.plugin.contract.ChannelMapper;
 import org.jboss.logging.Logger;
+import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.local.CoreDestination;
@@ -63,10 +66,10 @@
 import org.jboss.messaging.core.message.RoutableSupport;
 import org.jboss.messaging.core.persistence.JDBCUtil;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.tx.PreparedTxInfo;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.messaging.core.tx.TxCallback;
 import org.jboss.messaging.core.tx.XidImpl;
-import org.jboss.messaging.core.tx.PreparedTxInfo;
 import org.jboss.messaging.util.Util;
 import org.jboss.serial.io.JBossObjectInputStream;
 import org.jboss.serial.io.JBossObjectOutputStream;
@@ -135,17 +138,17 @@
    
    protected String loadReferenceInfo = 
       "SELECT MESSAGEID, ORD, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE "
-      + "WHERE CHANNELID=? AND STATE <> '+' AND LOADED = 'N' AND "
+      + "WHERE CHANNELID=? AND STATE = 'C' AND LOADED = 'N' AND "
       + "ORD BETWEEN ? AND ? ORDER BY ORD";
    
    protected String selectMinOrdering = 
       "SELECT MIN(ORD) FROM JMS_MESSAGE_REFERENCE WHERE "
-      + "CHANNELID=? AND STATE <> '+' AND LOADED = 'N'";
+      + "CHANNELID=? AND STATE = 'C' AND LOADED = 'N'";
    
-   protected String selectCountReferences = "SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE <> '+' AND LOADED='N'";
+   protected String selectCountReferences = "SELECT COUNT(MESSAGEID) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID=? AND STATE = 'C' AND LOADED='N'";
    
    protected String updateReliableRefs = 
-      "UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE <> '+'";
+      "UPDATE JMS_MESSAGE_REFERENCE SET LOADED='Y' WHERE ORD BETWEEN ? AND ? AND CHANNELID=? AND RELIABLE='Y' AND STATE = 'C'";
     
    protected String updateReliableRefsNotLoaded = "UPDATE JMS_MESSAGE_REFERENCE SET LOADED='N' WHERE CHANNELID=?";
    
@@ -609,21 +612,23 @@
       }
    }
    
-   public ChannelMapper getChannels()
+   public List getMessageChannelPairRefsForTx(long transactionId) throws Exception
    {
-	   return cm;
+      return getMessageChannelPair(selectMessageIdForRef, transactionId);
    }
-
-   public Map getMessageChannelPairForTx(long transactionId) throws Exception
+   
+   public List getMessageChannelPairAcksForTx(long transactionId) throws Exception
    {
-	   return getMessageChannelPair(selectMessageIdForRef, transactionId);
+      return getMessageChannelPair(selectMessageIdForAck, transactionId);
    }
-   public List getAcksForTx(long transactionId) throws Exception
+   
+   public ChannelMapper getChannels()
    {
-	   return new ArrayList(getMessageChannelPair(selectMessageIdForAck, transactionId).keySet());
+      return cm;
    }
 
-
+   
+   
    /*
     * Retrieve a List of messages corresponding to the specified List of message ids.
     * The implementation here for HSQLDB does this by using a PreparedStatment with an IN clause
@@ -4483,49 +4488,91 @@
    }
 
 
-   private Map getMessageChannelPair(String sqlQuery, long transactionId) throws Exception
+   private List getMessageChannelPair(String sqlQuery, long transactionId) throws Exception
    {
       if (trace) log.trace("loading message and channel ids for tx [" + transactionId + "]");
-
+      
       Connection conn = null;
       PreparedStatement ps = null;
       ResultSet rs = null;
       TransactionWrapper wrap = new TransactionWrapper();
-
+      
       try
       {
          conn = ds.getConnection();
-
+         
          ps = conn.prepareStatement(sqlQuery);
-
+         
          ps.setLong(1, transactionId);
-
+         
          rs = ps.executeQuery();
-
-         Map messageChannelPair = new HashMap();
-
-
+         
+         //Don't use a Map. A message could be in multiple channels in a tx, so if you use a map
+         //when you put the same message again it's going to overwrite the previous put!!
+         
+         List holders = new ArrayList();
+         
+         //Unique set of messages
+         Set msgIds = new HashSet();
+         
+         //TODO it would probably have been simpler just to have done all this in a SQL JOIN rather
+         //than do the join in memory.....
+         
+         class Holder
+         {
+            long messageId;
+            long channelId;
+            Holder(long messageId, long channelId)
+            {
+               this.messageId = messageId;
+               this.channelId = channelId;
+            }
+         }
+                  
          while(rs.next())
-         {
-        	   long messageId = rs.getLong(1);
+         {            
+            long messageId = rs.getLong(1);
             long channelId = rs.getLong(2);
-
-            messageChannelPair.put(new Long(messageId), new Long(channelId));
-
+            
+            Holder holder = new Holder(messageId, channelId);
+            
+            holders.add(holder);
+                        
+            msgIds.add(new Long(messageId));
+            
             if (trace) log.trace("Loaded MsgID: " + messageId + " and ChannelID: " + channelId);
          }
-
-         List messages = getMessages(new ArrayList(messageChannelPair.keySet()));
-
-         Map returnSet = new HashMap();
-
+         
+         Map messageMap = new HashMap();
+         
+         List messages = getMessages(new ArrayList(msgIds));
+         
          for (Iterator iter = messages.iterator(); iter.hasNext(); )
          {
             Message msg = (Message)iter.next();
-            returnSet.put(msg, messageChannelPair.get(new Long(msg.getMessageID())));
+            
+            messageMap.put(new Long(msg.getMessageID()), msg);            
          }
-
-         return returnSet;
+         
+         List returnList = new ArrayList();
+         
+         for (Iterator iter = holders.iterator(); iter.hasNext(); )
+         {
+            Holder holder = (Holder)iter.next();
+            
+            Message msg = (Message)messageMap.get(new Long(holder.messageId));
+            
+            if (msg == null)
+            {
+               throw new IllegalStateException("Cannot find message " + holder.messageId);
+            }
+            
+            MessageChannelPair pair = new MessageChannelPair(msg, holder.channelId);
+            
+            returnList.add(pair);
+         }
+         
+         return returnList;
       }
       catch (Exception e)
       {

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -22,11 +22,11 @@
 package org.jboss.messaging.core.plugin.contract;
 
 import java.util.List;
-import java.util.Map;
 
+import org.jboss.jms.server.plugin.contract.ChannelMapper;
+import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.jms.server.plugin.contract.ChannelMapper;
 
 /**
  * The interface to the persistence manager
@@ -44,12 +44,13 @@
 {
    List retrievePreparedTransactions() throws Exception;
 
+   List getMessageChannelPairRefsForTx(long transactionId) throws Exception;
+
+   List getMessageChannelPairAcksForTx(long transactionId) throws Exception;
+   
    ChannelMapper getChannels();
+   
 
-   Map getMessageChannelPairForTx(long transactionId) throws Exception;
-
-   List getAcksForTx(long transactionId) throws Exception;
-
    void resetLoadedStatus(long channelID) throws Exception;
       
    void addReference(long channelID, MessageReference ref, Transaction tx) throws Exception;
@@ -82,6 +83,30 @@
    // Interface value classes
    //---------------------------------------------------------------
    
+   class MessageChannelPair
+   {
+      private Message message;
+      
+      private long channelId;
+      
+      public MessageChannelPair(Message message, long channelId)
+      {
+         this.message = message;
+         
+         this.channelId = channelId;
+      }
+      
+      public Message getMessage()
+      {
+         return message;
+      }
+      
+      public long getChannelId()
+      {
+         return channelId;
+      }
+   }
+   
    class ReferenceInfo
    {
       private long messageId;

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/Transaction.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/Transaction.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/Transaction.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -70,6 +70,10 @@
    
    protected Map keyedCallbackMap;
    
+   private boolean loadedAtStartup;
+   
+   
+   
    // Static --------------------------------------------------------
    
    public static final int STATE_ACTIVE = 0;
@@ -324,6 +328,16 @@
       sb.append(stateToString(state));
       return sb.toString();
    }
+   
+   public boolean isLoadedAtStartup()
+   {
+      return this.loadedAtStartup;
+   }
+   
+   public void setLoadedAtStartup(boolean loadedAtStartup)
+   {
+      this.loadedAtStartup = loadedAtStartup;
+   }
 
    // Package protected ---------------------------------------------
    

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/TransactionRepository.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/TransactionRepository.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/TransactionRepository.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -25,17 +25,21 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+
 import javax.transaction.xa.Xid;
 
 import org.jboss.jms.destination.JBossDestination;
 import org.jboss.jms.server.plugin.contract.ChannelMapper;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.Delivery;
+import org.jboss.messaging.core.Channel;
 import org.jboss.messaging.core.DeliveryObserver;
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.Receiver;
 import org.jboss.messaging.core.SimpleDelivery;
+import org.jboss.messaging.core.SingleReceiverDelivery;
 import org.jboss.messaging.core.local.CoreDestination;
+import org.jboss.messaging.core.local.CoreSubscription;
 import org.jboss.messaging.core.plugin.IdManager;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
@@ -71,7 +75,9 @@
    protected MessageStore messageStore;
 
    protected IdManager idManager;
-
+   
+   protected ChannelMapper channelMapper;
+   
    // Static --------------------------------------------------------
    
    // Constructors --------------------------------------------------
@@ -87,6 +93,8 @@
    {
       this.persistenceManager = persistenceManager;
       this.messageStore = store;
+      
+      this.channelMapper = persistenceManager.getChannels();
 
       //TODO make this configurable
       idManager = new IdManager("TRANSACTION_ID", 4096, persistenceManager);
@@ -102,64 +110,82 @@
     *
     * @return  List of Xid instances
     */
-	public List recoverPreparedTransactions()
+   public synchronized List recoverPreparedTransactions()
    {
-		ArrayList prepared = new ArrayList();
+      if (trace) { log.trace(this + " recoverPreparedTransactions()"); }
+      
+      ArrayList prepared = new ArrayList();
 
-		Iterator iter = globalToLocalMap.values().iterator();
+      Iterator iter = globalToLocalMap.values().iterator();
 
-		while (iter.hasNext())
+      while (iter.hasNext())
       {
-			Transaction tx = (Transaction) iter.next();
+         Transaction tx = (Transaction) iter.next();
 
-			if (tx.xid != null && tx.getState() == Transaction.STATE_PREPARED)
+         if (tx.getXid() != null && tx.getState() == Transaction.STATE_PREPARED)
          {
             try
             {
-               if(trace) log.trace("Loading and handling refs and acks to the Tx "+tx);
+               if (trace) log.trace("Loading and handling refs and acks to the Tx "+tx);
 
-               handleReferences(tx);
-               handleAcks(tx);
+               //The transaction might have been created, prepared, without the server crashing
+               //in which case the tx will already have the references and acks in them
+               //in this case we DO NOT want to replay them again, since they will end up in the transaction state
+               //twice
+               //In other words we only want to replay acks and sends if this tx was loaded at startup
+               if (tx.isLoadedAtStartup())
+               {
+                  handleReferences(tx);
+                  handleAcks(tx);
+                  
+                  tx.setLoadedAtStartup(false);
+               }
             }
             catch (Exception e)
             {
                log.warn("Failed to replay transaction (XID: " + tx.getXid() + ", LocalID: " + tx.getId() + ") during recovery.", e);
             }
 
-				prepared.add(tx.getXid());
-			}
-		}
+            prepared.add(tx.getXid());
+         }
+      }
 
-		return prepared;
-	}
+      return prepared;
+   }
 
 	/*
 	 * Load any prepared transactions into the repository so they can be
 	 * recovered
 	 */
-	public void loadPreparedTransactions() throws Exception
+   public void loadPreparedTransactions() throws Exception
    {
       if (trace) log.trace("load prepared transactions...");
 
-		List prepared = null;
+      List prepared = null;
 
-		prepared = persistenceManager.retrievePreparedTransactions();
+      prepared = persistenceManager.retrievePreparedTransactions();
 
       if (trace) log.trace ("Found " + prepared.size() + " transactions in prepared state:");
 
-		if (prepared != null) {
-			Iterator iter = prepared.iterator();
+      if (prepared != null)
+      {
+         Iterator iter = prepared.iterator();
 
-			while (iter.hasNext()) {
-				PreparedTxInfo txInfo = (PreparedTxInfo) iter.next();
+         while (iter.hasNext())
+         {
+            PreparedTxInfo txInfo = (PreparedTxInfo) iter.next();
 
             if (trace) log.trace("Reinstating TX(XID: " + txInfo.getXid() + ", LocalId " + txInfo.getTxId() +")");
             
-				Transaction tx = createTransaction(txInfo);
-				tx.state = Transaction.STATE_PREPARED;
-			}
-		}
-	}
+            Transaction tx = createTransaction(txInfo);
+            
+            tx.state = Transaction.STATE_PREPARED;
+            
+            tx.setLoadedAtStartup(true);
+            
+         }
+      }
+   }
 
 
    public Transaction getPreparedTx(Xid xid) throws Exception
@@ -231,67 +257,152 @@
    
    // Private -------------------------------------------------------
 
-	/**
-	 * Load the references and invoke the channel to handle those refs
-	 */
-	private void handleReferences(Transaction tx) throws Exception {
-
+   private Receiver getQueue(long channelID) throws Exception
+   {
+      JBossDestination dest = channelMapper.getJBossDestination(channelID);
+      
+      Receiver ch = null;
+      
+      if (dest == null)
+      {
+         CoreSubscription sub = channelMapper.getDurableSubscription(channelID);
+         
+         if (sub == null)
+         {
+            throw new IllegalStateException("Cannot find queue for channel id: " + channelID);
+         }               
+         
+         ch = sub;
+      }
+      else
+      {
+         CoreDestination cd = channelMapper.getCoreDestination(dest);
+         
+         if (cd == null)
+         {
+            throw new IllegalStateException("Cannot find core destination for dest: " + dest);
+         }
+         
+         ch = cd;
+      }     
+      
+      return ch;
+   }
+   
+   /**
+    * Load the references and invoke the channel to handle those refs
+    */
+   private void handleReferences(Transaction tx) throws Exception
+   {
       if (trace) log.trace("Handle references for TX(XID: " + tx.getXid() + ", LocalID: " + tx.getId()+ "):");
 
       long txId = tx.getId();
 
-		Map messageChannelPair = persistenceManager.getMessageChannelPairForTx(txId);
+      List pairs = persistenceManager.getMessageChannelPairRefsForTx(txId);
 
-      if (trace) log.trace("Found " + messageChannelPair.size() + " unhandled messages.");
+      if (trace) log.trace("Found " + pairs.size() + " unhandled references.");
 
-      for (Iterator iter = messageChannelPair.keySet().iterator(); iter.hasNext();)
+      for (Iterator iter = pairs.iterator(); iter.hasNext();)
       {
-         Message msg = (Message)iter.next();
-         MessageReference ref = messageStore.reference(msg);
+         PersistenceManager.MessageChannelPair pair = (PersistenceManager.MessageChannelPair)iter.next();
+         
+         Message msg = pair.getMessage();
+         
+         long channelID = pair.getChannelId();
+         
+         MessageReference ref = null;
+         
+         try
+         {
+            ref = messageStore.reference(msg);    
+            
+            Receiver ch = getQueue(channelID);
+       
+            if (trace) log.trace("Destination for message[ID=" + ref.getMessageID() + "] is: " + ch);
+   
+            ch.handle(null, ref, tx);
+         }
+         finally
+         {
+            if (ref != null)
+            {
+               //Need to release reference
+               ref.releaseMemoryReference();
+            }
+         }
+      }
+   }
 
-         long channelID = ((Long)messageChannelPair.get(msg)).longValue();
-
-         ChannelMapper mapper = persistenceManager.getChannels();
-         JBossDestination destn = mapper.getJBossDestination(channelID);
-
-         CoreDestination d = mapper.getCoreDestination(destn);
-
-         if (trace) log.trace("Destination for message[ID=" + ref.getMessageID() + "] is: " + d);
-
-         d.handle(null, ref, tx);
-		}
-	}
-
-	/**
-	 * Load the acks and acknowledge them
-	 */
-	private void handleAcks(Transaction tx) throws Exception {
-
+   /**
+    * Load the acks and acknowledge them
+    */
+   private void handleAcks(Transaction tx) throws Exception
+   {
       long txId = tx.getId();
+      
+      List pairs = persistenceManager.getMessageChannelPairAcksForTx(txId);
 
-		List messages = persistenceManager.getAcksForTx(txId);
+      if (trace) log.trace("Found " + pairs.size() + " unhandled acks.");
+      
+      List dels = new ArrayList();
 
-      if (trace) log.trace("Found " + messages.size() + " unhandled acks.");
-
-      for (Iterator iter = messages.iterator(); iter.hasNext();)
+      for (Iterator iter = pairs.iterator(); iter.hasNext();)
       {
-         Message msg = (Message)iter.next();
-         MessageReference ref = messageStore.reference(msg);
+         PersistenceManager.MessageChannelPair pair = (PersistenceManager.MessageChannelPair)iter.next();
+         
+         Message msg = pair.getMessage();
+         
+         long channelID = pair.getChannelId();
+         
+         MessageReference ref = null;
+         
+         try
+         {
+            ref = messageStore.reference(msg);         
 
-			Delivery del = new SimpleDelivery(null, ref);
+            Receiver ch = getQueue(channelID);
+               
+            if (trace) log.trace("Destination for message[ID=" + ref.getMessageID() + "] is: " + ch);
+   
+            //Create a new delivery - note that it must have a delivery observer otherwise acknowledge will fail
+            SingleReceiverDelivery del = new SimpleDelivery((DeliveryObserver)ch, ref);
 
-			try
-         {
-				if(trace) log.trace("Acknowledging..");
+            if (trace) log.trace("Acknowledging..");
 
-				((DeliveryObserver)del).acknowledge(del, tx);
-			}
-         catch (Throwable e)
+            try
+            {
+               //At this point there won't be a delivery in the channel for this ref - since
+               //we won't have loaded it when the queue was loaded (since the stat column would have been '-')
+               //so we add it
+               
+               ((Channel)ch).addDelivery(del);
+               
+               del.acknowledge(tx);
+            }
+            catch (Throwable t)
+            {
+               log.error("Failed to acknowledge " + del + " during recovery", t);
+            }
+            
+            dels.add(del);            
+         }
+         finally
          {
-				log.debug("Acknowledgement failed.", e);
-			}
-		}
-	}
+            if (ref != null)
+            {
+               //Need to release reference
+               ref.releaseMemoryReference();
+            }
+         }
+      }
+      
+      if (!dels.isEmpty())
+      {
+         //Add a callback so these dels get cancelled on rollback
+         tx.addCallback(new CancelCallback(dels));
+      }
+      
+   }
 
 
 	/**
@@ -323,4 +434,58 @@
 
    // Inner classes -------------------------------------------------
    
+   private class CancelCallback implements TxCallback
+   {
+      private List toCancel;
+      
+      private CancelCallback(List toCancel)
+      {
+         this.toCancel = toCancel;
+      }
+
+      public void afterCommit(boolean onePhase) throws Exception
+      {
+      }
+
+      public void afterPrepare() throws Exception
+      {
+      }
+
+      public void afterRollback(boolean onePhase) throws Exception
+      {
+         //On rollback we need to cancel the ref back into the channel
+         //We only need to do this if the tx was reloaded 
+         
+         //Need to cancel in reverse
+         
+         for (int i = toCancel.size() - 1; i >= 0; i--)
+         {                     
+            SingleReceiverDelivery del = (SingleReceiverDelivery)toCancel.get(i);
+            
+            try
+            {
+               del.cancel();
+            }
+            catch (Throwable t)
+            {
+               log.error("Failed to cancel delivery", t);
+               throw new TransactionException(t.getMessage(), t);
+            }
+         }
+      }
+
+      public void beforeCommit(boolean onePhase) throws Exception
+      {
+      }
+
+      public void beforePrepare() throws Exception
+      {
+      }
+
+      public void beforeRollback(boolean onePhase) throws Exception
+      {
+      }
+      
+   }
+   
 }
\ No newline at end of file

Modified: branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/XidImpl.java
===================================================================
--- branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/XidImpl.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/src/main/org/jboss/messaging/core/tx/XidImpl.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -61,6 +61,11 @@
       return globalTransactionId;
    }
    
+   //For serialization
+   public XidImpl()
+   {      
+   }
+   
    public XidImpl(byte[] branchQualifier, int formatId, byte[] globalTransactionId)
    {
       this.branchQualifier = branchQualifier;

Modified: branches/Branch_1_0/tests/build.xml
===================================================================
--- branches/Branch_1_0/tests/build.xml	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/tests/build.xml	2006-12-22 00:34:08 UTC (rev 1845)
@@ -134,7 +134,7 @@
        JDBC Drivers.
    -->
    <path id="any.jdbc.driver.classpath">
-	       <fileset dir="${tests.root}/lib/jdbc-drivers" includes="*.jar"/>
+          <fileset dir="${tests.root}/lib/jdbc-drivers" includes="*.jar"/>
    </path>
 
 
@@ -357,6 +357,7 @@
       </junit>
    </target>
 
+
    <target name="memory-leak-tests" depends="tests-jar, prepare-testdirs, clear-test-logs"
            description="Runs memory-leak tests using JBossProfiler in-VM configuration">
 
@@ -623,7 +624,7 @@
       <antcall target="crash-test">
          <param name="crash.test.name" value="org.jboss.test.messaging.jms.crash.ClientCrashTwoConnectionsTest"/>
       </antcall>
-   	
+
       <antcall target="start-rmi-server"/>
 
       <antcall target="crash-test">

Modified: branches/Branch_1_0/tests/src/org/jboss/test/messaging/MessagingTestCase.java
===================================================================
--- branches/Branch_1_0/tests/src/org/jboss/test/messaging/MessagingTestCase.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/tests/src/org/jboss/test/messaging/MessagingTestCase.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -21,6 +21,9 @@
 */
 package org.jboss.test.messaging;
 
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
 import javax.jms.Destination;
@@ -28,9 +31,13 @@
 import javax.jms.MessageConsumer;
 import javax.jms.Session;
 import javax.jms.Topic;
+import javax.naming.InitialContext;
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
 
 import org.jboss.logging.Logger;
 import org.jboss.test.messaging.tools.ServerManagement;
+import org.jboss.tm.TransactionManagerService;
 
 import junit.framework.TestCase;
 
@@ -160,7 +167,73 @@
    {
       return ServerManagement.isRemote();
    }
+   
+   protected boolean checkNoMessageData() throws Exception
+   {
+      //Can't do this remotely
+      
+      if (ServerManagement.isRemote())
+      {
+         return false;
+      }
+      
+      InitialContext ctx = new InitialContext();
 
+      TransactionManager mgr = (TransactionManager)ctx.lookup(TransactionManagerService.JNDI_NAME);
+      DataSource ds = (DataSource)ctx.lookup("java:/DefaultDS");
+      
+      javax.transaction.Transaction txOld = mgr.suspend();
+      mgr.begin();
+      
+      java.sql.Connection conn = null;
+      
+      PreparedStatement ps = null;
+      
+      ResultSet rs = null;
+
+      try
+      {
+         conn = ds.getConnection();
+         String sql = "SELECT * FROM JMS_MESSAGE_REFERENCE";
+         ps = conn.prepareStatement(sql);
+         
+         rs = ps.executeQuery();
+         
+         boolean exists = rs.next();
+         
+         if (!exists)
+         {
+            rs.close();
+            
+            ps.close();
+            
+            ps = conn.prepareStatement("SELECT * FROM JMS_MESSAGE");
+            
+            rs = ps.executeQuery();
+           
+            exists = rs.next();
+         }
+         
+         return exists;
+      }
+      finally
+      {
+         if (rs != null) rs.close();
+         
+         if (ps != null) ps.close();
+         
+         if (conn != null) conn.close();
+         
+         mgr.commit();
+
+         if (txOld != null)
+         {
+            mgr.resume(txOld);
+         }
+                  
+      } 
+   }
+
    // Private -------------------------------------------------------
    
    // Inner classes -------------------------------------------------   

Modified: branches/Branch_1_0/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
===================================================================
--- branches/Branch_1_0/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -191,6 +191,11 @@
       throw new NotYetImplementedException();
    }
 
+   public void addDelivery(Delivery del)
+   {
+      throw new NotYetImplementedException();
+   }
+
    // Package protected ---------------------------------------------
    
    // Protected -----------------------------------------------------

Modified: branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XARecoveryTest.java
===================================================================
--- branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XARecoveryTest.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XARecoveryTest.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -23,13 +23,14 @@
 
 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.jms.Message;
 import javax.naming.InitialContext;
 import javax.transaction.TransactionManager;
 import javax.transaction.xa.XAResource;
@@ -41,12 +42,19 @@
 import org.jboss.test.messaging.tools.ServerManagement;
 import org.jboss.tm.TransactionManagerLocator;
 
+import com.arjuna.ats.arjuna.common.Uid;
 import com.arjuna.ats.jta.xa.XidImple;
-import com.arjuna.ats.arjuna.common.Uid;
 
 /**
+ * 
+ * A XARecoveryTest
+ *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @author <a href="mailto:juha at jboss.org">Juha Lindfors</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
  */
 public class XARecoveryTest extends MessagingTestCase
 {
@@ -59,7 +67,7 @@
    protected InitialContext initialContext;
    
    protected JBossConnectionFactory cf;
-   protected Destination queue, queueA, queueB, queueTX;
+   protected Destination queue, queueA, queueB, queueTX, topicTX;
 
    TransactionManager tm;
 
@@ -75,9 +83,8 @@
    public void setUp() throws Exception
    {
       super.setUp();
-      ServerManagement.start("all");
+      ServerManagement.start("all");      
       
-      
       initialContext = new InitialContext(ServerManagement.getJNDIEnvironment());
       cf = (JBossConnectionFactory)initialContext.lookup("/ConnectionFactory");
       
@@ -95,11 +102,16 @@
 
       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);
@@ -113,561 +125,3209 @@
       ServerManagement.undeployQueue("QA");
       ServerManagement.undeployQueue("QB");
       ServerManagement.undeployQueue("TXQ");
+      
+      ServerManagement.undeployTopic("TXTOPIC");
 
-
       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 XidImpl("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);
 
-/*
-   public void testJBossTSCoordinator() throws Exception
+         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
    {
-      UserTransaction ut = com.arjuna.ats.jta.UserTransaction.userTransaction();
+      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 XidImpl("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);
 
-      ut.begin();
-
-
-      ut.commit();
+         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
+            }
+         }               
+      }
    }
-*/
-
-
-   public void testTransactionalDeliveryRecovery() throws Exception
+   
+   /*
+    * 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 XidImpl("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
 
-      XAConnection conn1 = cf.createXAConnection();
+         ServerManagement.stopServerPeer();
 
-      XAConnection conn2 = cf.createXAConnection();
+         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);
 
-      XASession sess1 = conn1.createXASession();
+         assertEquals(xid1, xids[0]);
+         
+         log.trace("Committing the tx");
+         
+         //Commit
+         res3.commit(xids[0], false);
+         
+         log.trace("committed the tx");
 
-      XASession sess2 = conn2.createXASession();
+         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 XidImpl("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
 
-      XAResource res1 = sess1.getXAResource();
+         ServerManagement.stopServerPeer();
 
-      XAResource res2 = sess2.getXAResource();
+         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);
 
-      //Pretend to be a transaction manager by interacting through the XAResources
-      Xid xid1 = new XidImpl("bq1".getBytes(), 42, "eemeli".getBytes());
-      Xid xid2 = new XidImpl("bq2".getBytes(), 42, "frigtard".getBytes());
+         assertEquals(xid1, xids[0]);
+         
+         log.trace("rolling back the tx");
+         
+         //rollback
+         res3.rollback(xids[0]);
+         
+         log.trace("rolled back the tx");
+         
+         Thread.sleep(1000);
 
-      //    Send a message in each 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(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 XidImpl("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 XidImpl("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);
 
-      res1.start(xid1, XAResource.TMNOFLAGS);
+         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 XidImpl("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
 
-      MessageProducer prod1 = sess1.createProducer(queueTX);
+         ServerManagement.stopServerPeer();
 
-      TextMessage tm1 = sess1.createTextMessage("tm1");
+         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);
 
-      prod1.send(tm1);
+         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 XidImpl("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);
 
-      TextMessage tm2 = sess1.createTextMessage("tm2");
+         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 XidImpl("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
 
-      prod1.send(tm2);
+         ServerManagement.stopServerPeer();
 
-      res1.end(xid1, XAResource.TMSUCCESS);
+         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 XidImpl("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);
 
-      res2.start(xid2, XAResource.TMNOFLAGS);
+         //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);
 
-      MessageProducer prod2 = sess2.createProducer(queueTX);
+         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 XidImpl("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);
 
-      TextMessage tm3 = sess2.createTextMessage("tm3");
+         //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
 
-      prod2.send(tm3);
+         ServerManagement.stopServerPeer();
 
-      TextMessage tm4 = sess2.createTextMessage("tm4");
+         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);
 
-      prod2.send(tm4);
+         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
+            }
+         }               
+      }
+   }
+         
+   
 
-      res2.end(xid2, XAResource.TMSUCCESS);
+   /*
+    * 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;
 
-      //prepare both txs
-
-
-      res1.prepare(xid1);
-      res2.prepare(xid2);
-
-      //Now "crash" the server
-
-      ServerManagement.stopServerPeer();
-
-      ServerManagement.startServerPeer();
-
-      ServerManagement.deployQueue("TXQ");
-
-
-
-      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);
-
-
-      Connection conn3 = cf.createConnection();
-
-      Session sessRec = conn3.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageConsumer cons = sessRec.createConsumer(queueTX);
-      conn3.start();
-
-      TextMessage m1 = (TextMessage)cons.receive(MAX_TIMEOUT);
-      assertNotNull(m1);
-
-      assertTrue(tm1.getText().equals("tm1") ||
-                 tm1.getText().equals("tm2") ||
-                 tm1.getText().equals("tm3") ||
-                 tm1.getText().equals("tm4"));
-
-
-      TextMessage m2 = (TextMessage)cons.receive(MAX_TIMEOUT);
-      assertNotNull(m2);
-
-      assertTrue(tm2.getText().equals("tm1") ||
-                 tm2.getText().equals("tm2") ||
-                 tm2.getText().equals("tm3") ||
-                 tm2.getText().equals("tm4"));
-      assertTrue(!tm1.getText().equals(tm2.getText()));
-
-
-      TextMessage m3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-      assertNotNull(m3);
-
-      assertTrue(tm3.getText().equals("tm1") ||
-                 tm3.getText().equals("tm2") ||
-                 tm3.getText().equals("tm3") ||
-                 tm3.getText().equals("tm4"));
-
-      assertTrue(!tm3.getText().equals(tm2.getText()));
-      assertTrue(!tm3.getText().equals(tm1.getText()));
-
-
-      TextMessage m4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-      assertNotNull(m4);
-
-      assertTrue(tm4.getText().equals("tm1") ||
-                 tm4.getText().equals("tm2") ||
-                 tm4.getText().equals("tm3") ||
-                 tm4.getText().equals("tm4"));
-
-      assertTrue(!tm4.getText().equals(tm3.getText()));
-      assertTrue(!tm4.getText().equals(tm2.getText()));
-      assertTrue(!tm4.getText().equals(tm1.getText()));
-
-
-      TextMessage nullMessage = (TextMessage)cons.receive(MIN_TIMEOUT);
-
-      assertTrue(nullMessage == null);
-
-      conn3.close();
+      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 XidImpl("bq1".getBytes(), 42, "eemeli".getBytes());
+         Xid xid2 = new XidImpl("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 XidImpl("bq1".getBytes(), 42, "aapeli".getBytes());
+         Xid xid2 = new XidImpl("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
+            }
+         }    
+      }
 
-      XAConnection conn1 = cf.createXAConnection();
-
-      XAConnection 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 XidImpl("bq1".getBytes(), 42, "aapeli".getBytes());
-      Xid xid2 = new XidImpl("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);
-
-
-      Connection 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);
-
-      conn3.close();
    }
 
+   
+   /*
+    * 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();
 
-      XAConnection conn1 = cf.createXAConnection();
-
-      XAConnection 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);
-
-
-      Connection 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());
-
-      conn3.close();
-
+         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();
 
-      XAConnection conn1 = cf.createXAConnection();
-
-      XAConnection 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 XidImpl("bq1".getBytes(), 123, "gbtxid1".getBytes());
-      Xid xid2 = new XidImpl("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);
-
-
-      Connection 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());
-
-      conn3.close();
-
+         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 XidImpl("bq1".getBytes(), 123, "gbtxid1".getBytes());
+         Xid xid2 = new XidImpl("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();
 
-      XAConnection conn1 = 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 XidImpl("bq1".getBytes(), 123, "gbtxid1".getBytes());
+         Xid xid2 = new XidImpl("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
+            }
+         }    
+      }
 
-      XAConnection 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 XidImpl("bq1".getBytes(), 123, "gbtxid1".getBytes());
-      Xid xid2 = new XidImpl("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);
-
-
-      Connection 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());
-
-      conn3.close();
-
    }
 
 }

Modified: branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XATest.java
===================================================================
--- branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XATest.java	2006-12-21 23:43:16 UTC (rev 1844)
+++ branches/Branch_1_0/tests/src/org/jboss/test/messaging/jms/XATest.java	2006-12-22 00:34:08 UTC (rev 1845)
@@ -46,10 +46,15 @@
 import org.jboss.tm.TxUtils;
 
 /**
+ * 
+ * A XATest
+ *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
  * @author <a href="mailto:juha at jboss.org">Juha Lindfors</a>
  *
  * $Id$
+ *
  */
 public class XATest extends MessagingTestCase
 {
@@ -132,7 +137,6 @@
 
 
    // Public --------------------------------------------------------
-
    
    public void test2PCSendCommit1PCOptimization() throws Exception
    {
@@ -144,8 +148,7 @@
       Connection conn2 = null;
       
       try
-      {
-      
+      {      
          conn = cf.createXAConnection();
          
          tm.begin();
@@ -1062,8 +1065,6 @@
          TextMessage r3 = (TextMessage)cons.receive(MIN_TIMEOUT);
          assertNull(r3);
 
-
-
       }
       finally
       {
@@ -1226,28 +1227,82 @@
          //rollback
 
          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(queue);
-         conn2.start();
+         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);
 
-         TextMessage r3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r3);
-         assertEquals("jellyfish1", r3.getText());
-
-         r3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r3);
-         assertEquals("jellyfish2", r3.getText());
-
-         TextMessage r4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r4);
-         assertEquals("jellyfish3", r4.getText());
-
-         r4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r4);
-         assertEquals("jellyfish4", r4.getText());
-
-
       }
       finally
       {
@@ -1333,34 +1388,84 @@
          cons2.close();
 
          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(queue);
          conn2.start();
 
-         //NOTE
-         //The order here is actually probably dependent on the transaction manager implementation
-         //In this case, rollback will be called on each session, but whether it is called first on res1
-         //or res2 determines the order the messages are put back in the queue
-         //This test assumes it is called in order res1, res2
+         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);
 
-         TextMessage r3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r3);
-         assertEquals("jellyfish3", r3.getText());
 
-         r3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r3);
-         assertEquals("jellyfish4", r3.getText());
-
-         TextMessage r4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r4);
-         assertEquals("jellyfish1", r4.getText());
-
-         r4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r4);
-         assertEquals("jellyfish2", r4.getText());
-
-
       }
       finally
       {
@@ -1389,6 +1494,7 @@
          conn2 = cf.createConnection();
          Session sessProducer = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
          MessageProducer prod  = sessProducer.createProducer(queue);
+         
          Message m = sessProducer.createTextMessage("jellyfish1");
          prod.send(m);
          m = sessProducer.createTextMessage("jellyfish2");
@@ -1398,10 +1504,9 @@
          m = sessProducer.createTextMessage("jellyfish4");
          prod.send(m);
 
-
          conn = cf.createXAConnection();
          conn.start();
-
+         
          tm.begin();
 
          XASession sess1 = conn.createXASession();
@@ -1433,13 +1538,22 @@
 
          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
+         
+         
+         //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();
@@ -1449,28 +1563,41 @@
          {
             //We should expect this
          }
-
+         
+         Thread.sleep(1000);
+         
+         
          Session sess = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);
          MessageConsumer cons = sess.createConsumer(queue);
          conn2.start();
 
-         TextMessage r3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r3);
-         assertEquals("jellyfish1", r3.getText());
-
-         r3 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r3);
-         assertEquals("jellyfish2", r3.getText());
-
-         TextMessage r4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r4);
-         assertEquals("jellyfish3", r4.getText());
-
-         r4 = (TextMessage)cons.receive(MAX_TIMEOUT);
-         assertNotNull(r4);
-         assertEquals("jellyfish4", r4.getText());
-
-
+         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
       {
@@ -1498,7 +1625,6 @@
 
       try
       {
-
          conn = cf.createXAConnection();
          conn.start();
 




More information about the jboss-cvs-commits mailing list