[jboss-svn-commits] JBL Code SVN: r35995 - in labs/jbosstm/workspace/istudens: RecoveryDemo and 12 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Nov 16 10:11:19 EST 2010


Author: istudens at redhat.com
Date: 2010-11-16 10:11:18 -0500 (Tue, 16 Nov 2010)
New Revision: 35995

Added:
   labs/jbosstm/workspace/istudens/RecoveryDemo/
   labs/jbosstm/workspace/istudens/RecoveryDemo/.classpath
   labs/jbosstm/workspace/istudens/RecoveryDemo/.project
   labs/jbosstm/workspace/istudens/RecoveryDemo/.settings/
   labs/jbosstm/workspace/istudens/RecoveryDemo/.settings/org.eclipse.jdt.core.prefs
   labs/jbosstm/workspace/istudens/RecoveryDemo/README
   labs/jbosstm/workspace/istudens/RecoveryDemo/build.xml
   labs/jbosstm/workspace/istudens/RecoveryDemo/lib/
   labs/jbosstm/workspace/istudens/RecoveryDemo/lib/antlr.jar
   labs/jbosstm/workspace/istudens/RecoveryDemo/lib/dbdriver/
   labs/jbosstm/workspace/istudens/RecoveryDemo/lib/junit-4.5.jar
   labs/jbosstm/workspace/istudens/RecoveryDemo/local.properties
   labs/jbosstm/workspace/istudens/RecoveryDemo/resources/
   labs/jbosstm/workspace/istudens/RecoveryDemo/resources/META-INF/
   labs/jbosstm/workspace/istudens/RecoveryDemo/resources/META-INF/persistence.xml
   labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-1-ds.xml
   labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-2-ds.xml
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/OrderIdGenerator.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/RecoveryDemoTest.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderEntity.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacade.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacadeRemote.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureMode.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureSpec.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureType.java
   labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASTestResource.java
Log:
copying RecoveryDemo from a private svn, JBQA-3344

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/.classpath
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/.classpath	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/.classpath	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="var" path="JBOSS_HOME/common/lib/ejb3-persistence.jar"/>
+	<classpathentry kind="var" path="JBOSS_HOME/common/lib/jboss-javaee.jar"/>
+	<classpathentry kind="var" path="JBOSS_HOME"/>
+	<classpathentry kind="lib" path="lib/junit-4.5.jar"/>
+	<classpathentry kind="var" path="JBOSS_HOME/common/lib/jbossjts.jar"/>
+	<classpathentry kind="var" path="JBOSS_HOME/client/jboss-ejb3-ext-api.jar"/>
+	<classpathentry kind="output" path="classes"/>
+</classpath>

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/.project
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/.project	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/.project	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Recovery Demo</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+	</natures>
+</projectDescription>

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/.settings/org.eclipse.jdt.core.prefs	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/.settings/org.eclipse.jdt.core.prefs	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,12 @@
+#Mon May 03 10:49:43 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/README
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/README	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/README	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,89 @@
+Recovery Demo Application
+=========================
+
+In order to use this recovery demo application one has to follow the steps below.
+
+1) Prepare two Oracle databases for the demo. You will need an db account with permissions for transaction recovery.
+    1.a) Create database user account in your dbs
+    1.b) Give it the right permissions
+            GRANT SELECT ON sys.dba_pending_transactions TO username;
+            GRANT SELECT ON sys.pending_trans$ TO username;
+            GRANT SELECT ON sys.dba_2pc_pending TO username;
+            GRANT EXECUTE ON sys.dbms_xa TO username;
+         If the last command fails, execute this one:
+            GRANT EXECUTE ON sys.dbms_system TO username;
+   For more info see:
+   http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/5.0.1/html/Transactions_Administrators_Guide/ch07s04.html
+   
+2) Install JBoss EAP5 and set the JBOSS_HOME.
+
+3) Configure the demo application in the file local.properties. 
+   Especially set the URLs, usernames and user passwords for your DBs.
+   
+4) In the EAP turn on the recovery for both DBs. It is possible to run the following command to do that.
+      ant setup-crash-recovery
+
+5) Compile and deploy demo application to the EAP server.
+      ant deploy
+
+6) Start up the EAP server.
+      cd $JBOSS_HOME/bin
+      ./run.sh -c all &> log &
+
+7) Return to the demo application directory and run the test.
+      ant run-test
+
+8) During the test run, plug in/out the network cable of the second database server several times.
+   With default settings the test takes about 6 minute on typical PC.
+
+9) When the test is finished, check its result in the console and also in the TEST-org.jboss.test.recoverydemo.client.RecoveryDemoTest.xml file.
+   The databases should be in sync. The EAP server log should be full of "Cannot open connection" messages, but nothing more.
+   There should not be any messages like the one below if the recovery is properly configured.
+       Could not find new XAResource to use for recovering non-serializable XAResource
+
+
+
+It is also possible to run the test in a special mode with a fault XA resource. In order to enable
+this fault XA resource follow the steps below.
+
+1) Change the enlist.fault.xaresource property in the local.properties file of the demo application to true.
+      enlist.fault.xaresource=false
+
+2) Run the test.
+      ant run-test
+
+3) During the test run check the EAP server log and wait for signal from the fault XA resource 
+   about suspending the transaction in the commit phase.
+      tail -f $JBOSS_HOME/server/all/log/server.log
+   The signal looks like this:
+      2010-05-05 16:34:34,462 INFO  [STDOUT] (WorkerThread#1[127.0.0.1:57387]) Applying fault injection with 1 active branches
+      2010-05-05 16:34:34,462 INFO  [STDOUT] (WorkerThread#1[127.0.0.1:57387]) xa commit ... suspending for 90000
+   where 90000 means 90secs.
+
+4) Plug out the network cable of the second database server.
+
+5) Wait for signal from the fault XA resource about resuming the transaction.
+      2010-05-05 16:36:04,463 INFO  [STDOUT] (WorkerThread#1[127.0.0.1:57387]) xa commit ... resuming
+       
+6) Plug in the network cable back.
+
+7) When the test is finished, check its result in the console and also in the TEST-org.jboss.test.recoverydemo.client.RecoveryDemoTest.xml file.
+   The databases should be in sync. The EAP server log should be full of "Cannot open connection" messages, but nothing more.
+
+
+The time that the test takes depends on the client app. configuration, 
+i.e. on the properties 'max.iterations' and 'max.threads' in the local.properties file.
+The 'max.threads' property stands for the number of threads used by client application to
+invoke the test method on the EAP server.
+The 'max.iterations' property stands for number of calls that will be done by each thread.
+
+
+Note: how to manually finish a pending transaction in the Oracle db.
+1) select local_tran_id from dba_2pc_pending;
+      '8.25.224633'
+2) ALTER SYSTEM DISABLE DISTRIBUTED RECOVERY;
+3) ROLLBACK FORCE '8.25.224633';
+4) exec dbms_transaction.purge_lost_db_entry('8.25.224633');
+5) ALTER SYSTEM ENABLE DISTRIBUTED RECOVERY;
+
+ 

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/build.xml
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/build.xml	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/build.xml	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,140 @@
+<?xml version="1.0"?>
+<project name="Recovery Demo" default="compile" basedir=".">
+
+    <property environment="env"/>
+	
+	<property file="local.properties"/>
+	
+	<property name="jboss.home" value="${env.JBOSS_HOME}"/>
+	<property name="jboss.server" value="${jboss.home}/server/all"/>
+	
+    <property name="src.dir" value="${basedir}/src" />
+    <property name="res.dir" value="${basedir}/resources" />
+    <property name="classes.dir" value="${basedir}/classes" />
+    <property name="build.dir" value="${basedir}/build" />
+    <property name="lib.dir" value="${basedir}/lib" />
+    <property name="dbdriver.dir" value="${lib.dir}/dbdriver" />
+	
+    <path id="ejb-jars">
+      <fileset dir="${jboss.home}">
+            <include name="client/jbossall-client.jar"/>
+            <include name="client/log4j.jar" />
+      		<include name="client/jboss-javaee.jar"/>
+	  		<include name="client/ejb3-persistence.jar"/>
+      </fileset>
+    </path>
+	
+	<path id="classpath">
+		<pathelement location="${classes.dir}"/>
+        <fileset dir="${lib.dir}">
+            <include name="*.jar"/>
+        </fileset>
+        <path refid="ejb-jars"/>
+	</path>
+	
+    <target name="init">
+		<mkdir dir="${classes.dir}"/>
+		<mkdir dir="${build.dir}"/>
+    </target>
+	
+	<target name="compile" depends="init">
+        <javac srcdir="${src.dir}"
+                   destdir="${classes.dir}"
+                   debug="on"
+                   deprecation="on"
+                   optimize="off"
+                   includes="**">
+              <classpath refid="classpath"/>
+        </javac>
+	</target>
+
+    <target name="ejb3jar" depends="compile" >
+      <jar jarfile="${build.dir}/recovery-ejb.jar">
+        <fileset dir="${res.dir}">
+               <include name="META-INF/*.xml"/>
+        </fileset>
+        <fileset dir="${classes.dir}">
+            <include name="**/ejb3/*.class"/>
+            <include name="**/recovery/*.class"/>
+        </fileset>
+      </jar>
+    </target>
+
+    <target name="deploy" depends="ejb3jar">
+        <copy todir="${jboss.server}/lib">
+        	<fileset dir="${dbdriver.dir}">
+        		<include name="*.jar"/>
+        	</fileset>
+        </copy>
+        <copy file="${res.dir}/oracle10-xa-1-ds.xml" todir="${jboss.server}/deploy">
+            <filterset>
+                <filter token="URL" value="${db1.url}"/>
+                <filter token="USER" value="${db1.user}"/>
+                <filter token="PASS" value="${db1.pass}"/>
+            </filterset>
+        </copy>
+        <copy file="${res.dir}/oracle10-xa-2-ds.xml" todir="${jboss.server}/deploy">
+            <filterset>
+                <filter token="URL" value="${db2.url}"/>
+                <filter token="USER" value="${db2.user}"/>
+                <filter token="PASS" value="${db2.pass}"/>
+            </filterset>
+        </copy>
+        <copy file="${build.dir}/recovery-ejb.jar" todir="${jboss.server}/deploy"/>
+    </target>
+    <target name="undeploy" >
+    	<delete file="${jboss.server}/deploy/recovery-ejb.jar"/>
+        <delete file="${res.dir}/oracle10-xa-1-ds.xml"/>
+        <delete file="${res.dir}/oracle10-xa-2-ds.xml"/>
+    </target>
+
+	<target name="clean">
+		<delete dir="${classes.dir}"/>
+		<delete dir="${build.dir}"/>
+	</target>
+
+    <target name="setup-crash-recovery">
+    	<!-- enable crash recovery and point it to our datasource -->
+    	<replace file="${jboss.server}/conf/jbossts-properties.xml">
+    		<replacetoken><![CDATA[</transaction-service>]]></replacetoken>
+    		<replacevalue><![CDATA[
+     <properties depends="arjuna" name="jta">
+        <property name="com.arjuna.ats.jta.recovery.XAResourceRecovery1" value= "com.arjuna.ats.internal.jbossatx.jta.AppServerJDBCXARecovery;jndiname=CrashRecoveryDS1"/>
+        <property name="com.arjuna.ats.jta.xaRecoveryNode" value="1"/>
+     </properties>
+     <properties depends="arjuna" name="jta">
+        <property name="com.arjuna.ats.jta.recovery.XAResourceRecovery2" value= "com.arjuna.ats.internal.jbossatx.jta.AppServerJDBCXARecovery;jndiname=CrashRecoveryDS2"/>
+        <property name="com.arjuna.ats.jta.xaRecoveryNode" value="1"/>
+     </properties>
+ </transaction-service>]]></replacevalue>
+        </replace>
+        <!-- comment out for more verbose logging
+        <replace file="${jboss.server}/conf/jbossts-properties.xml">
+           <replacetoken><![CDATA[type="System" value="0x00000000"]]></replacetoken>
+           <replacevalue><![CDATA[type="System" value="0xffffffff"]]></replacevalue>
+        </replace-->
+    </target>
+	
+	<target name="run-test">
+	  <junit printsummary="yes" haltonfailure="yes" fork="true" dir="${basedir}">
+    	<classpath>
+    		<path refid="classpath"/>
+    	</classpath>
+    	
+        <formatter type="xml"/>
+
+        <test name="org.jboss.test.recoverydemo.client.RecoveryDemoTest"/>
+
+    	<sysproperty key="maxIterations" value="${max.iterations}"/>
+    	<sysproperty key="maxThreads" value="${max.threads}"/>
+    	<sysproperty key="enlistFaultXAResource" value="${enlist.fault.xaresource}"/>
+    	<sysproperty key="orderIdPrefix" value="node1"/>	<!-- FIXME put hostname here -->
+
+    	<sysproperty key="serverHostname" value="${server.hostname}"/>
+
+        <!--<jvmarg value="-Xdebug"/>-->
+        <!--<jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5006"/>-->
+      </junit>
+	</target>
+
+</project>

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/lib/antlr.jar
===================================================================
(Binary files differ)


Property changes on: labs/jbosstm/workspace/istudens/RecoveryDemo/lib/antlr.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/lib/junit-4.5.jar
===================================================================
(Binary files differ)


Property changes on: labs/jbosstm/workspace/istudens/RecoveryDemo/lib/junit-4.5.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/local.properties
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/local.properties	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/local.properties	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,18 @@
+# test configuration
+max.iterations=400
+max.threads=200
+enlist.fault.xaresource=false
+
+# AS server hostname
+server.hostname=localhost
+
+# db1
+db1.url=jdbc:oracle:thin:@jawa06.englab.brq.redhat.com:1521:soaesb1
+db1.user=soaesb1
+db1.pass=soaesb1
+
+# db2
+db2.url=jdbc:oracle:thin:@jawa01.englab.brq.redhat.com:1521:soaesb1
+db2.user=soaesb1
+db2.pass=soaesb1
+

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/resources/META-INF/persistence.xml
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/resources/META-INF/persistence.xml	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/resources/META-INF/persistence.xml	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence">
+	<persistence-unit name="recoveryDemo1">
+		<jta-data-source>java:/CrashRecoveryDS1</jta-data-source>
+		<properties>
+			<property name="jboss.entity.manager.jndi.name" value="java:/CrashRecoveryManager1" />
+			<property name="jboss.entity.manager.factory.jndi.name"
+				value="java:/CrashRecoveryManagerFactory1" />
+			<property name="hibernate.hbm2ddl.auto" value="update"/>
+		</properties>
+	</persistence-unit>
+	<persistence-unit name="recoveryDemo2">
+		<jta-data-source>java:/CrashRecoveryDS2</jta-data-source>
+		<properties>
+			<property name="jboss.entity.manager.jndi.name" value="java:/CrashRecoveryManager2" />
+			<property name="jboss.entity.manager.factory.jndi.name"
+				value="java:/CrashRecoveryManagerFactory2" />
+			<property name="hibernate.hbm2ddl.auto" value="update"/>
+		</properties>
+	</persistence-unit>
+</persistence>

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-1-ds.xml
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-1-ds.xml	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-1-ds.xml	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  JBoss Server Configuration                                           -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle-xa-ds.xml 71535 2008-04-01 07:05:03Z adrian at jboss.org $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION:  DO NOT FORGET TO SET Pad=true IN transaction-service.xml  -->
+<!-- ===================================================================== -->
+
+<datasources>
+
+  <xa-datasource>
+    <jndi-name>CrashRecoveryDS1</jndi-name>
+    <track-connection-by-tx>true</track-connection-by-tx> 
+    <isSameRM-override-value>false</isSameRM-override-value>
+    <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+    <xa-datasource-property name="URL">@URL@</xa-datasource-property>
+    <xa-datasource-property name="User">@USER@</xa-datasource-property>
+    <xa-datasource-property name="Password">@PASS@</xa-datasource-property>
+    <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
+    <!-- Checks the Oracle error codes and messages for fatal errors -->
+    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+    <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
+    <no-tx-separate-pools/>
+
+      <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+      <metadata>
+         <type-mapping>Oracle9i</type-mapping>
+      </metadata>
+  </xa-datasource>
+
+</datasources>

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-2-ds.xml
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-2-ds.xml	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/resources/oracle10-xa-2-ds.xml	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ===================================================================== -->
+<!--                                                                       -->
+<!--  JBoss Server Configuration                                           -->
+<!--                                                                       -->
+<!-- ===================================================================== -->
+
+<!-- $Id: oracle-xa-ds.xml 71535 2008-04-01 07:05:03Z adrian at jboss.org $ -->
+
+<!-- ===================================================================== -->
+<!-- ATTENTION:  DO NOT FORGET TO SET Pad=true IN transaction-service.xml  -->
+<!-- ===================================================================== -->
+
+<datasources>
+
+  <xa-datasource>
+    <jndi-name>CrashRecoveryDS2</jndi-name>
+    <track-connection-by-tx>true</track-connection-by-tx> 
+    <isSameRM-override-value>false</isSameRM-override-value>
+    <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
+    <xa-datasource-property name="URL">@URL@</xa-datasource-property>
+    <xa-datasource-property name="User">@USER@</xa-datasource-property>
+    <xa-datasource-property name="Password">@PASS@</xa-datasource-property>
+    <!-- Uses the pingDatabase method to check a connection is still valid before handing it out from the pool -->
+    <valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
+    <!-- Checks the Oracle error codes and messages for fatal errors -->
+    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
+    <!-- Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa -->
+    <no-tx-separate-pools/>
+
+      <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
+      <metadata>
+         <type-mapping>Oracle9i</type-mapping>
+      </metadata>
+  </xa-datasource>
+
+</datasources>

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/OrderIdGenerator.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/OrderIdGenerator.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/OrderIdGenerator.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,31 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.client;
+
+public abstract class OrderIdGenerator {
+
+	private static long orderId = 0;
+	
+	public static synchronized long getNextOrderId()
+	{
+		return ++orderId;
+	}
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/RecoveryDemoTest.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/RecoveryDemoTest.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/client/RecoveryDemoTest.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,185 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.client;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Properties;
+
+import javax.ejb.EJBException;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.jboss.test.recoverydemo.ejb3.OrderFacade;
+import org.jboss.test.recoverydemo.ejb3.OrderFacadeRemote;
+import org.junit.Before;
+import org.junit.Test;
+
+public class RecoveryDemoTest 
+{
+	private int maxIterations;
+	private int	maxThreads;
+	private String orderIdPrefix;
+	private boolean enlistFaultXAResource;
+	
+	private String serverHostname;
+
+	private OrderFacadeRemote orderFacade = null;
+
+	
+	@Before
+	public void initialize() throws NamingException
+	{
+		maxIterations			= parseInt(System.getProperty("maxIterations"), 1000);
+		maxThreads				= parseInt(System.getProperty("maxThreads"), 5);
+		orderIdPrefix			= System.getProperty("orderIdPrefix");
+		enlistFaultXAResource	= parseBoolean(System.getProperty("enlistFaultXAResource"));
+		
+		serverHostname			= System.getProperty("serverHostname");
+		
+		if (orderFacade == null)
+			orderFacade = (OrderFacadeRemote) getNamingContext().lookup(OrderFacade.REMOTE_JNDI_NAME); 
+		
+		System.out.println("maxIterations = " + maxIterations);
+		System.out.println("maxThreads = " + maxThreads);
+		System.out.println("orderIdPrefix = " + orderIdPrefix);
+		System.out.println("enlistFaultXAResource = " + enlistFaultXAResource);
+	}
+	
+	@Test
+	public void recoveryDemo()
+	{
+		// clear the dbs before the test
+		orderFacade.initDatabases();
+		
+		// check that dbs are empty
+		int[] countsBefore = orderFacade.checkDatabaseStates();
+		assertEquals("Db1 should be empty", countsBefore[0], 0);
+		assertEquals("Db2 should be empty", countsBefore[1], 0);
+		
+		// run the test
+		ArrayList<DemoTestRunner> threads = new ArrayList<DemoTestRunner>(maxThreads);
+		for (int i=0; i < maxThreads; i++)
+		{
+			DemoTestRunner runner = new DemoTestRunner(enlistFaultXAResource && i==0);		// only the first thread potentially invokes the fault XA resource
+			threads.add(runner);
+			runner.start();
+		}
+		// wait for the threads to finish 
+		for (DemoTestRunner runner: threads)
+		{
+			try
+			{
+				runner.join();
+			}
+			catch (InterruptedException e)
+			{
+				System.err.println("Join interrupted: " + e);
+			}
+		}
+		
+		// check the dbs state after the test
+		int[] countsAfter = orderFacade.checkDatabaseStates();
+		System.out.println(countsAfter[0] + " orders in db1");
+		System.out.println(countsAfter[1] + " orders in db2");
+		assertEquals("There should be the same count of orders in both dbs after the test", countsAfter[0], countsAfter[1]);
+	}
+	
+	
+	class DemoTestRunner extends Thread
+	{
+		boolean enlistFaultXAResource;
+		
+		public DemoTestRunner(boolean enlistFaultXAResource)
+		{
+			this.enlistFaultXAResource = enlistFaultXAResource;
+		}
+		
+		public void run()
+		{
+			// the fault XA resource will be potentially invoked in the third of the cycle
+			int hitIndex = (enlistFaultXAResource) ? maxIterations/3 : -1;
+			
+			OrderFacadeRemote facade;
+			try {
+				facade = (OrderFacadeRemote) getNamingContext().lookup(OrderFacade.REMOTE_JNDI_NAME);
+			} catch (NamingException e1) {
+				throw new EJBException(e1);
+			} 
+
+			for (int k=0; k < maxIterations; k++)
+			{
+				try 
+				{
+					long orderId = OrderIdGenerator.getNextOrderId();
+					facade.storeNewOrder(orderIdPrefix + "_" + Long.toString(orderId), hitIndex == k);
+				}
+				catch (Exception e)
+				{
+					System.err.println("Error: " + e.getMessage());
+					e.printStackTrace(System.err);
+				}
+			}
+		}
+		
+	}
+
+	private Context getNamingContext() throws NamingException
+	{
+		Properties properties = new Properties();
+		properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.NamingContextFactory");
+		properties.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming.client:org.jnp.interfaces");
+		properties.setProperty(Context.PROVIDER_URL, "jnp://" + serverHostname + ":1099");
+
+		return new InitialContext(properties);
+	}
+	
+	private int parseInt(String value, int defaultValue)
+	{
+		int retVal;
+		try
+		{
+			retVal = Integer.parseInt(value);
+		}
+		catch (Exception e)
+		{
+			retVal = defaultValue;
+		}
+		return retVal;
+	}
+	
+	private boolean parseBoolean(String value)
+	{
+		boolean retVal;
+		try
+		{
+			retVal = Boolean.parseBoolean(value);
+		}
+		catch (Exception e)
+		{
+			retVal = false;
+		}
+		return retVal;
+	}
+	
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderEntity.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderEntity.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderEntity.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.ejb3;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+/**
+ * Simple OrderEntity for the Recovery Demo App.
+ * 
+ * @author <a href="istudens at redhat.com">Ivo Studensky</a>
+ * @version $Revision: 1.1 $
+ */
+ at Entity
+ at Table(name="orderentity")
+public class OrderEntity implements Serializable
+{
+	private String orderNumber;
+
+	public OrderEntity()
+	{
+		// default constructor
+	}
+
+	public OrderEntity(String orderNumber)
+	{
+		this.orderNumber = orderNumber;
+	}
+
+	@Id
+	public String getOrderNumber()
+	{
+		return orderNumber;
+	}
+	public void setOrderNumber(String orderNumber)
+	{
+		this.orderNumber = orderNumber;
+	}
+
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+		+ ((orderNumber == null) ? 0 : orderNumber.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		OrderEntity other = (OrderEntity) obj;
+		if (orderNumber == null) {
+			if (other.orderNumber != null)
+				return false;
+		} else if (!orderNumber.equals(other.orderNumber))
+			return false;
+		return true;
+	}
+
+	@Override
+	public String toString() 
+	{
+		return "OrderEntity [orderNumber=" + orderNumber + "]";
+	}
+
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacade.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacade.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacade.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,105 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.ejb3;
+
+import javax.ejb.EJBException;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.transaction.Transaction;
+
+import org.jboss.test.recoverydemo.recovery.ASFailureMode;
+import org.jboss.test.recoverydemo.recovery.ASFailureSpec;
+import org.jboss.test.recoverydemo.recovery.ASFailureType;
+import org.jboss.test.recoverydemo.recovery.ASTestResource;
+
+ at Stateless
+public class OrderFacade implements OrderFacadeRemote {
+	public static final String REMOTE_JNDI_NAME = OrderFacade.class.getSimpleName() + "/remote";
+
+
+	@PersistenceContext(unitName="recoveryDemo1")
+	EntityManager em1;
+
+	@PersistenceContext(unitName="recoveryDemo2")
+	EntityManager em2;
+
+
+	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+	public boolean storeNewOrder(String orderNumber, boolean enlistFaultXAResource)
+	{
+		OrderEntity order1 = new OrderEntity(orderNumber);
+		em1.persist(order1);
+
+		// enlist the special XA resource here
+		if (enlistFaultXAResource)
+			enlistFaultXAResource();
+
+		OrderEntity order2 = new OrderEntity(orderNumber);
+		em2.persist(order2);
+
+		return true;
+	}
+
+	private void enlistFaultXAResource()
+	{
+		try
+		{
+			Transaction tx = com.arjuna.ats.jta.TransactionManager.transactionManager().getTransaction();
+
+			int sleep = 90 * 1000;	// in msec
+			ASFailureSpec failureSpec = new ASFailureSpec("commit_suspend", ASFailureMode.SUSPEND, ASFailureType.XARES_COMMIT, Integer.toString(sleep), 0);
+
+			ASTestResource res = new ASTestResource(failureSpec);
+
+			if (res.isXAResource())
+				tx.enlistResource(res);
+			else if (res.isSynchronization())
+				tx.registerSynchronization(res);
+
+		}
+		catch (Exception e)
+		{
+			System.err.println("Error: " + e.getMessage());
+			throw new EJBException(e);
+		}
+	}
+
+
+	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+	public void initDatabases()
+	{
+		em1.createQuery("DELETE FROM OrderEntity").executeUpdate();
+		em2.createQuery("DELETE FROM OrderEntity").executeUpdate();
+	}
+
+	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+	public int[] checkDatabaseStates()
+	{
+		int db1Size = em1.createQuery("SELECT OBJECT(a) FROM OrderEntity a").getResultList().size();
+		int db2Size = em2.createQuery("SELECT OBJECT(a) FROM OrderEntity a").getResultList().size();
+
+		return new int[] {db1Size, db2Size};
+	}
+
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacadeRemote.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacadeRemote.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/ejb3/OrderFacadeRemote.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.ejb3;
+
+import javax.ejb.Remote;
+
+ at Remote
+public interface OrderFacadeRemote {
+	public boolean storeNewOrder(String orderNumber, boolean enlistFaultXAResource);
+	public void initDatabases();
+	public int[] checkDatabaseStates();
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureMode.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureMode.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureMode.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.recovery;
+
+import java.io.Serializable;
+
+/**
+ * Specification of what to do when a failure is injected.
+ * Borrowed from JBossAS Testsuite.
+ */
+public enum ASFailureMode implements Serializable
+{
+    NONE(false)
+    
+    ,HALT(true)    // halt the JVM
+    ,EXIT(true)   // exit the JVM
+    ,SUSPEND(false)  // suspend the calling thread
+    ,XAEXCEPTION(false)    // fail via one of the xa exception codes
+    ;
+
+    private boolean willTerminateVM;
+
+    ASFailureMode(boolean willTerminateVM)
+    {
+        this.willTerminateVM = willTerminateVM;
+    }
+
+    public boolean willTerminateVM()
+    {
+        return willTerminateVM;
+    }
+
+    public static ASFailureMode toEnum(String mode)
+    {
+        return ASFailureMode.valueOf(mode.toUpperCase());
+    }
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureSpec.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureSpec.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureSpec.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.recovery;
+
+import java.io.Serializable;
+
+/**
+ * An ASFailureSpec is for defining different ways of generating
+ * failures and essentially consists of a mode and type.
+ *
+ * If you need to generate new kinds of failure you should
+ * modify the ASFailureMode and ASFailureType classes. Your
+ * test will be given a reference to these specifications and is
+ * responsible for interpreting their meaning.
+ *
+ * @see org.jboss.test.crashrecovery.ASCrashRecovery01.Test03 for an example
+ * @see org.jboss.test.crashrecovery.recovery.ASFailureMode
+ * @see org.jboss.test.crashrecovery.recovery.ASFailureType
+ *
+ * A failure specification is defined in ASTestConfig
+ * @see org.jboss.test.crashrecovery.taskdefs.ASTestConfig
+ * 
+ * Borrowed from JBossAS Testsuite.
+ */
+public class ASFailureSpec implements Serializable
+{
+    String name;
+    ASFailureMode mode;
+    ASFailureType type;
+    String modeArg;
+    int recoveryArg;
+
+    public ASFailureSpec()
+    {
+        mode = ASFailureMode.NONE;
+        type = ASFailureType.NONE;
+    }
+
+    public ASFailureSpec(String name, ASFailureMode mode, ASFailureType type, String modeArg, int recoveryArg)
+    {
+        this.name = name;
+        this.mode = mode;
+        this.type = type;
+        this.modeArg = modeArg;
+        this.recoveryArg = recoveryArg;
+    }
+
+    public boolean willTerminateVM()
+    {
+        return mode.willTerminateVM();
+    }
+
+    public ASFailureMode getMode()
+    {
+        return mode;
+    }
+
+    public ASFailureType getType()
+    {
+        return type;
+    }
+
+    public String getModeArg()
+    {
+        return modeArg;
+    }
+
+    public int getRecoveryArg()
+    {
+        return recoveryArg;
+    }
+
+    public String getName()
+    {
+        return name;
+    }
+
+    public void setName(String name)
+    {
+        this.name = name;
+    }
+
+    public void setMode(String mode)
+    {
+        this.mode = ASFailureMode.valueOf(mode);
+    }
+
+    public void setType(String type)
+    {
+        this.type = ASFailureType.valueOf(type);
+    }
+
+    public void setModeArg(String modeArg)
+    {
+        this.modeArg = modeArg;
+    }
+
+    public void setRecoveryArg(int recoveryArg)
+    {
+        this.recoveryArg = recoveryArg;
+    }
+
+    public String toString()
+    {
+        return new StringBuilder().append(mode).append(',').append(type).append(',').append(modeArg).toString();
+    }
+
+    public boolean equals(Object o)
+    {
+        if (this == o) return true;
+        if (!(o instanceof ASFailureSpec)) return false;
+
+        ASFailureSpec that = (ASFailureSpec) o;
+
+        if (name != null ? !name.equals(that.name) : that.name != null) return false;
+
+        return true;
+    }
+
+    public int hashCode()
+    {
+        return (name != null ? name.hashCode() : 0);
+    }
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureType.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureType.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASFailureType.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.recovery;
+
+import java.io.Serializable;
+
+/**
+ * Specification of when to inject a failure.
+ * Borrowed from JBossAS Testsuite.
+ */
+public enum ASFailureType implements Serializable
+{
+    NONE
+
+    ,PRE_PREPARE // do something before prepare is called
+
+    ,XARES_START    // failures specific to the XA protocol
+    ,XARES_END
+    ,XARES_PREPARE
+    ,XARES_ROLLBACK
+    ,XARES_COMMIT
+    ,XARES_RECOVER
+    ,XARES_FORGET
+
+    ,SYNCH_BEFORE   // do something before completion
+    ,SYNCH_AFTER
+    ;
+    
+    public static ASFailureType toEnum(String type)
+    {
+        return ASFailureType.valueOf(type.toUpperCase());
+    }
+
+    public boolean isXA()
+    {
+        return name().startsWith("XARES");
+    }
+
+    public boolean isSynchronization()
+    {
+        return name().startsWith("SYNCH");
+    }
+
+    public boolean isPreCommit()
+    {
+        return equals(PRE_PREPARE);
+    }
+}

Added: labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASTestResource.java
===================================================================
--- labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASTestResource.java	                        (rev 0)
+++ labs/jbosstm/workspace/istudens/RecoveryDemo/src/org/jboss/test/recoverydemo/recovery/ASTestResource.java	2010-11-16 15:11:18 UTC (rev 35995)
@@ -0,0 +1,328 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package org.jboss.test.recoverydemo.recovery;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.Synchronization;
+import java.io.Serializable;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * Simulate a variety of faults during the various phases of the XA protocol.
+ * Borrowed from JBossAS Testsuite.
+ */
+public class ASTestResource implements Synchronization, XAResource, Serializable
+{
+    private static final Map<String, XAException> xaCodeMap = new HashMap<String, XAException>();
+
+    private ASFailureType _xaFailureType = ASFailureType.NONE;
+    private ASFailureMode _xaFailureMode = ASFailureMode.NONE;
+    private String[] _args;
+    private int _suspend;
+    private int _recoveryAttempts = 1;
+    private XAException _xaException;
+    private int txTimeout = 10;
+    private Set<Xid> _xids = new HashSet<Xid>();
+    private transient boolean _isPrepared = false; // transient so it doesn't get persisted in the tx store
+
+    static
+    {
+        init();
+    }
+    
+    public ASTestResource()
+    {
+    }
+
+    public ASTestResource(ASFailureSpec spec)
+    {
+        this();
+
+        if (spec == null)
+            throw new IllegalArgumentException("Invalid XA resource failure injection specification");
+        
+        setFailureMode(spec.getMode(), spec.getModeArg());
+        setFailureType(spec.getType());
+        setRecoveryAttempts(spec.getRecoveryArg());
+    }
+
+    public void applySpec(String message) throws XAException
+    {
+        applySpec(message, _isPrepared);
+    }
+
+    public void applySpec(String message, boolean prepared) throws XAException
+    {
+        if (_xaFailureType.equals(ASFailureType.NONE) || _xaFailureMode.equals(ASFailureMode.NONE) || !prepared)
+        {
+            System.out.println(message + (_isPrepared ? " ... " : " recovery"));
+            return; // NB if !_isPrepared then we must have been called from the recovery subsystem
+        }
+
+        System.out.println("Applying fault injection with " + _xids.size() + " active branches");
+        if (_xaException != null)
+        {
+            System.out.println(message + " ... xa error: " + _xaException.getMessage());
+            throw _xaException;
+        }
+        else if (_xaFailureMode.equals(ASFailureMode.HALT))
+        {
+            System.out.println(message + " ... halting");
+            Runtime.getRuntime().halt(1);
+        }
+        else if (_xaFailureMode.equals(ASFailureMode.EXIT))
+        {
+            System.out.println(message + " ... exiting");
+            System.exit(1);
+        }
+        else if (_xaFailureMode.equals(ASFailureMode.SUSPEND))
+        {
+            System.out.println(message + " ... suspending for " + _suspend);
+            suspend(_suspend);
+            System.out.println(message + " ... resuming");
+        }
+    }
+
+    public String toString()
+    {
+        return _xaFailureType + ", " + _xaFailureMode + ", " + (_args != null && _args.length != 0 ? _args[0] : "");
+    }
+
+    private void suspend(int msecs)
+    {
+        try
+        {
+            Thread.sleep(msecs);
+        }
+        catch (InterruptedException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public void setFailureMode(ASFailureMode mode, String ... args) throws IllegalArgumentException
+    {
+        _xaFailureMode = mode;
+        _args = args;
+
+        if (args != null && args.length != 0)
+        {
+            if (_xaFailureMode.equals(ASFailureMode.SUSPEND))
+            {
+                _suspend = Integer.parseInt(args[0]);
+            }
+            else if (_xaFailureMode.equals(ASFailureMode.XAEXCEPTION))
+            {
+                _xaException = xaCodeMap.get(args[0]);
+
+                if (_xaException == null)
+                    _xaException = new XAException(XAException.XAER_RMFAIL);
+            }
+        }
+    }
+
+    public void setFailureType(ASFailureType type)
+    {
+        _xaFailureType = type;
+    }
+
+    public ASFailureType getFailureType()
+    {
+        return _xaFailureType;
+    }
+
+    public void setRecoveryAttempts(int _recoveryAttempts)
+    {
+        this._recoveryAttempts = _recoveryAttempts;
+    }
+
+    // Synchronizatons
+
+    public void beforeCompletion()
+    {
+        if (_xaFailureType.equals(ASFailureType.SYNCH_BEFORE))
+            try
+            {
+                applySpec("Before completion");
+            }
+            catch (XAException e)
+            {
+                throw new RuntimeException(e);
+            }
+    }
+
+    public void afterCompletion(int i)
+    {
+        if (_xaFailureType.equals(ASFailureType.SYNCH_AFTER))
+            try
+            {
+                applySpec("After completion");
+            }
+            catch (XAException e)
+            {
+                throw new RuntimeException(e);
+            }
+    }
+
+    // XA Interface implementation
+
+    public void commit(Xid xid, boolean b) throws XAException
+    {
+        if (_xaFailureType.equals(ASFailureType.XARES_COMMIT))
+            applySpec("xa commit");
+
+        _isPrepared = false;
+        _xids.remove(xid);
+    }
+
+    public void rollback(Xid xid) throws XAException
+    {
+       if (_xaFailureType.equals(ASFailureType.XARES_ROLLBACK))
+            applySpec("xa rollback");
+
+        _isPrepared = false;
+        _xids.remove(xid);
+    }
+    
+    public void end(Xid xid, int i) throws XAException
+    {
+        if (_xaFailureType.equals(ASFailureType.XARES_END))
+            applySpec("xa end");
+    }
+
+    public void forget(Xid xid) throws XAException
+    {
+        if (_xaFailureType.equals(ASFailureType.XARES_FORGET))
+            applySpec("xa forget");
+
+        _isPrepared = false;
+        _xids.remove(xid);
+    }
+
+    public int getTransactionTimeout() throws XAException
+    {
+        return txTimeout;
+    }
+
+    public boolean isSameRM(XAResource xaResource) throws XAException
+    {
+        return false;
+    }
+
+    public int prepare(Xid xid) throws XAException
+    {
+        _isPrepared = true;
+        
+        if (_xaFailureType.equals(ASFailureType.XARES_PREPARE))
+            applySpec("xa prepare");
+
+        _xids.add(xid);
+
+        return XA_OK;
+    }
+
+    public Xid[] recover(int i) throws XAException
+    {
+        if (_recoveryAttempts <= 0)
+            return _xids.toArray(new Xid[_xids.size()]);
+
+        _recoveryAttempts -= 1;
+
+        if (_xaFailureType.equals(ASFailureType.XARES_RECOVER))
+            applySpec("xa recover");
+
+        return new Xid[0];
+    }
+
+    public boolean setTransactionTimeout(int txTimeout) throws XAException
+    {
+        this.txTimeout = txTimeout;
+        
+        return true;    // set was successfull
+    }
+
+    public void start(Xid xid, int i) throws XAException
+    {
+        _xids.add(xid);
+
+       if (_xaFailureType.equals(ASFailureType.XARES_START))
+            applySpec("xa start");
+    }
+
+    public String getEISProductName() { return "Test XAResouce";}
+    
+    public String getEISProductVersion() { return "v666.0";}
+
+    @SuppressWarnings({"ThrowableInstanceNeverThrown"})
+    private static void init()
+    {
+        xaCodeMap.put("XA_HEURCOM", new XAException(XAException.XA_HEURCOM));
+        xaCodeMap.put("XA_HEURHAZ", new XAException(XAException.XA_HEURHAZ));
+        xaCodeMap.put("XA_HEURMIX", new XAException(XAException.XA_HEURMIX));
+        xaCodeMap.put("XA_HEURRB", new XAException(XAException.XA_HEURRB));
+        xaCodeMap.put("XA_NOMIGRATE", new XAException(XAException.XA_NOMIGRATE));
+        xaCodeMap.put("XA_RBBASE", new XAException(XAException.XA_RBBASE));
+        xaCodeMap.put("XA_RBCOMMFAIL", new XAException(XAException.XA_RBCOMMFAIL));
+        xaCodeMap.put("XA_RBDEADLOCK", new XAException(XAException.XA_RBDEADLOCK));
+        xaCodeMap.put("XA_RBEND", new XAException(XAException.XA_RBEND));
+        xaCodeMap.put("XA_RBINTEGRITY", new XAException(XAException.XA_RBINTEGRITY));
+        xaCodeMap.put("XA_RBOTHER", new XAException(XAException.XA_RBOTHER));
+        xaCodeMap.put("XA_RBPROTO", new XAException(XAException.XA_RBPROTO));
+        xaCodeMap.put("XA_RBROLLBACK", new XAException(XAException.XA_RBROLLBACK));
+        xaCodeMap.put("XA_RBTIMEOUT", new XAException(XAException.XA_RBTIMEOUT));
+        xaCodeMap.put("XA_RBTRANSIENT", new XAException(XAException.XA_RBTRANSIENT));
+        xaCodeMap.put("XA_RDONLY", new XAException(XAException.XA_RDONLY));
+        xaCodeMap.put("XA_RETRY", new XAException(XAException.XA_RETRY));
+        xaCodeMap.put("XAER_ASYNC", new XAException(XAException.XAER_ASYNC));
+        xaCodeMap.put("XAER_DUPID", new XAException(XAException.XAER_DUPID));
+        xaCodeMap.put("XAER_INVAL", new XAException(XAException.XAER_INVAL));
+        xaCodeMap.put("XAER_NOTA", new XAException(XAException.XAER_NOTA));
+        xaCodeMap.put("XAER_OUTSIDE", new XAException(XAException.XAER_OUTSIDE));
+        xaCodeMap.put("XAER_PROTO", new XAException(XAException.XAER_PROTO));
+        xaCodeMap.put("XAER_RMERR", new XAException(XAException.XAER_RMERR));
+        xaCodeMap.put("XAER_RMFAIL ", new XAException(XAException.XAER_RMFAIL));
+    }
+
+    public boolean isXAResource()
+    {
+        return _xaFailureType.isXA() || _xaFailureType.equals(ASFailureType.NONE);
+    }
+
+    public boolean isSynchronization()
+    {
+        return _xaFailureType.isSynchronization();
+    }
+
+    public boolean isPreCommit()
+    {
+        return _xaFailureType.isPreCommit();
+    }
+
+    public boolean expectException()
+    {
+        return _xaFailureMode.equals(ASFailureMode.XAEXCEPTION);
+    }
+}



More information about the jboss-svn-commits mailing list