Introduction
In this wiki page we'll look at how JBossTS recovery works within JBossAS. We'll spend a bit of time looking at the example code too, though as usual the manuals are the best source of material on the what's and why's of recovery. This article applies to JBossAS 4.2 and EAP versions based on is (EAP 4.2, 4.3)
JBoss Messaging recovery
JBM provides its own XAResources and instructions on how to recover them. See http://www.jboss.org/file-access/default/members/jbossmessaging/freezone/docs/userguide-1.4.0.SP3/html_single/index.html#recovery
JBossJCA <xa-datasource> recovery
XA transaction aware database connection pools configured via -ds.xml files rely upon the JBossJCA XAResources. Approaches to recovery for these include using either bypassing the JCA and recovering using the standard JDBC recovery modules from JBossTS standalone, or using the AppServerJDBCXARecovery module. For the former see the JBossTS documentation and the JDBC section of the JBossTSRecovery wiki page . For the latter see JBTM-319 and the javadoc for AppServerJDBCXARecovery Note that AppServerJDBCXARecovery is not present in JBossAS (you need to download and build it from source) or early EAP releases. It is in EAP 4.2.CP03, EAP 4.3.CP01 and later EAP releases. AppServerJDBCXARecovery does not currently support invoker security, see JBTM-432
For recovery of custom XAResource types not covered in the sections above, keep reading.
JTA recovery
Assuming you have deployed JBossTS as per the JTA
or JTS notes, you need only change your jbossjts-properties.xml to enable:
<property name="com.arjuna.ats.arjuna.recovery.recoveryExtension5" value="com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule"/>
You can remove the other entry as we do not need it for this example.
Clean your ObjectStore prior to running the example.
Then download and build the example. You should deploy this into the default configuration for JBossAS and run the application server instance. Once it is ready, run the example client java org.jboss.ejb.TestClient. Within the JBossAS log output, you will eventually see:
10:43:27,392 INFO STDOUT enlisting resources 10:43:27,399 INFO STDOUT ExampleResource: ExampleXAResource (Constructor) 10:43:27,401 INFO STDOUT ExampleResource: start 10:43:27,408 INFO STDOUT ExampleResource: ExampleXAResource (Constructor) 10:43:27,409 INFO STDOUT ExampleResource: isSameRM 10:43:27,411 INFO STDOUT ExampleResource: start 10:43:27,416 INFO STDOUT committing 10:43:27,419 INFO STDOUT ExampleResource: end 10:43:27,431 INFO STDOUT ExampleResource: prepare 10:43:27,433 INFO STDOUT ExampleResource: end 10:43:27,435 INFO STDOUT ExampleResource: prepare 10:43:27,444 INFO STDOUT ExampleResource: writeObject (Serialized) 10:43:27,448 INFO STDOUT ExampleResource: writeObject (Serialized) 10:43:27,458 INFO STDOUT ExampleResource: commit,xid=< 131075, 28, 26, 1--3f57fe99:ead3:44757bdb:65-3f57fe99:ead3:44757bdb:66 >,onePhase=false 10:43:27,470 INFO STDOUT ExampleResource: Sleeping 20000 milliseconds
At this stage, we have enlisted two XAResource instances with the transaction and told both to prepare. Because both implementations are serializable, their states have been written into the transaction log for recovery purposes and the transaction has entered the second (commit) phase. At this point it blocks and you should kill your JBossAS instance.
If you then look in the ObjectStore, you should see the transaction log entry:
PutObjectStoreDirHere//HashedActionStore/defaultStore/StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction/4: total 8 -rw-rr 1 marklitt marklitt 752 May 25 10:43 -3f57fe99_ead3_44757bdb_65
Now restart your JBossAS instance and wait. Eventually you will see the recovery system start to work and recognise that there is an inflight transaction. It will then re-activate that transaction and start to recover any participants (XAResources in this case) that were registered with it. The log output will look similar to:
If you look within the ObjectStore, the transaction log has been removed because both participants successfully recovered.
JTS recovery
First ensure that your JBossTS installation is configured to use the
JTS implementation of the JTA. Make sure that your jbossjts-properties.xml file is correctly configured. You need:
<property name="com.arjuna.ats.jta.jtaTMImplementation" value="com.arjuna.ats.internal.jta.transaction.jts.TransactionManagerImple"/> <property name="com.arjuna.ats.jta.jtaUTImplementation" value="com.arjuna.ats.internal.jta.transaction.jts.UserTransactionImple"/>
and
<property name="com.arjuna.ats.arjuna.recovery.recoveryExtension5" value="com.arjuna.ats.internal.jta.recovery.jts.XARecoveryModule"/>
Clean your ObjectStore prior to running the example.
Next download and build the example using the build-ejb.sh script. You may have to modify this for your operating system of choice. The setup.sh is provided for additional convenience where necessary. When the build is complete, you will have a recovery-test.jar which should should deploy into your JBossAS installation (using the all configuration).
Now start your JBossAS instance. Once that is ready, we need to run the example and cause a crash. To do this, execute java org.jboss.ejb.TestClient and you will eventually see a stack trace, part of which is shown below:
Exception in thread "main" java.rmi.UnmarshalException: Error unmarshaling return header; nested exception is: java.io.EOFException at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:203) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126) at org.jboss.invocation.jrmp.server.JRMPInvoker_Stub.invoke(Unknown Source) at org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxy.invoke(JRMPInvokerProxy.java:119) at org.jboss.invocation.InvokerInterceptor.invokeInvoker(InvokerInterceptor.java:227) at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:167) at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46) at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:55)
Plus your JBossAS instance will have exited. This is correct behaviour: out test has just crashed the server.
If you look in the ObjectStore, you will see two state entries:
PutObjectStoreDirHere//ShadowNoFileLockStore/defaultStore/CosTransactions/XAResourceRecord: total 16 -rw-rr 1 marklitt marklitt 1008 May 24 14:14 -3f57fe99_e758_44745bf8_85 -rw-rr 1 marklitt marklitt 1008 May 24 14:14 -3f57fe99_e758_44745bf8_89
and if you check the server log, you'll see something like the following:
11:14:04,195 INFO STDOUT work 11:14:04,213 INFO STDOUT enlisting resources 11:14:04,222 INFO STDOUT ExampleXAResource: ExampleXAResource (1, true) 11:14:04,230 INFO STDOUT ExampleXAResource: start 11:14:04,241 INFO STDOUT ExampleXAResource: ExampleXAResource (2, true) 11:14:04,243 INFO STDOUT ExampleXAResource: isSameRM 11:14:04,258 INFO STDOUT ExampleXAResource: start 11:14:04,338 INFO STDOUT committing 11:14:04,343 INFO STDOUT ExampleXAResource: end 11:14:04,344 INFO STDOUT ExampleXAResource: prepare < 131072, 28, 26, 1--3f57fe99:eb33:4475834c:79-3f57fe99:eb33:4475834c:7b > 11:14:04,346 INFO STDOUT writing XID < 131072, 28, 26, 1--3f57fe99:eb33:4475834c:79-3f57fe99:eb33:4475834c:7b > 11:14:04,405 INFO STDOUT ExampleXAResource: end 11:14:04,406 INFO STDOUT ExampleXAResource: prepare < 131072, 28, 26, 1--3f57fe99:eb33:4475834c:79-3f57fe99:eb33:4475834c:7f > 11:14:04,407 INFO STDOUT writing XID < 131072, 28, 26, 1--3f57fe99:eb33:4475834c:79-3f57fe99:eb33:4475834c:7f > 11:14:04,535 INFO STDOUT ExampleXAResource: commit,xid=< 131072, 28, 26, 1--3f57fe99:eb33:4475834c:79-3f57fe99:eb33:4475834c:7b >,onePhase=false
At this stage, we have enlisted two XAResource instances with the transaction and told both to prepare. JBossTS writes recovery information on behalf of each
instance within the ObjectStore: each instance is actually a CosTransactions::Resource implementation, which wraps the registered XAResources. At this point it blocks and you should kill your JBossAS instance.
If you look in the ObjectStore, you will see the two state entries mentioned above:
PutObjectStoreDirHere//ShadowNoFileLockStore/defaultStore/CosTransactions/XAResourceRecord: total 16 -rw-rr 1 marklitt marklitt 1032 May 25 11:14 -3f57fe99_eb33_4475834c_7c -rw-rr 1 marklitt marklitt 1032 May 25 11:14 -3f57fe99_eb33_4475834c_80
as well as the transaction log entry. Each CosTransactions::Resource entry contains information on the XAResource, the transaction within which the XAResource was registered and a remote reference to an OTS::RecoveryCoordinator instance, which will be used to drive recovery.
Now restart your JBossAS instance and wait. When recovery occurs, you will see:
15:05:48,683 INFO STDOUT ExampleXAResource: readObject (Deserialized 15:05:48,708 INFO LoggerI18N Com.arjuna.ats.internal.jta.recovery.jts.orbspecific.commit XA recovery committing < 131072, 27, 25, 1-7f000001:ec40:4475b888:797f000001:ec40:4475b888:7b > 15:05:48,710 INFO STDOUT ExampleXAResource: commit,xid=< 131072, 27, 25, 1-7f000001:ec40:4475b888:797f000001:ec40:4475b888:7b >,onePhase=false 15:05:48,717 INFO STDOUT ExampleXAResource: readObject (Deserialized 15:05:48,781 INFO STDOUT ExampleXAResource: commit,xid=< 131072, 27, 25, 1-7f000001:ec40:4475b888:797f000001:ec40:4475b888:7f >,onePhase=false 15:05:48,789 INFO LoggerI18N Com.arjuna.ats.internal.jta.recovery.jts.orbspecific.commit XA recovery committing < 131072, 27, 25, 1-7f000001:ec40:4475b888:797f000001:ec40:4475b888:7f >
If you check the ObjectStore, you will see that both CosTransactions::Resource entries have gone, along with the transaction log. Recovery has completed.
Comments