The preferred solution for this problem is to configure
the data source for session bean 1 with an XA-capable driver.
If it is not possible to use XA, the first session bean must have the
following code technique used to get the first transaction properly
suspended when the second session bean is called.
The idea behind the mechanism is to suspend the global transaction before
issuing the remote call, then to resume the transaction after the remote
call ends. The preInvoke method is called just before the remote method
(session bean method) is called, and then the postInvoke() method is
called after the remote method returns. This sequence of calls can be made
any number of times before the UserTransaction.commit() call is made.
Note: The example refers to a remote method. It does not
actually have to be remote; this mechanism works for both local and remote
calls.
There is a mechanism to suspend a global transaction using a supported
SPI.
In the program calling the remote EJB, do this once:
com.ibm.ws.extensionhelper.ExtensionHelper extHelper =
(com.ibm.ws.extensionhelper.ExtensionHelper)InitialContext.lookup
("services:websphere/ExtensionHelper");
com.ibm.ws.extensionhelper.extHelper.TransactionControl tranControl =
extHelper.getTransactionControl();
// Wrap work with TransactionControl preInvoke/postInvoke to execute
// outside current UOW.
try
{
// Suspends current global or local UOW. See below for flag settings
com.ibm.ws.extensionhelper.extHelper.TxHandle txHandle =
tranControl.preInvoke(false, true) ;
/**************************************************************************************
Parameters for the preInvoke are as follows:
* Start a transaction, behavior will be decided by depending on
the input
* false, false, participate in a global transaction if one active
or start a new global transaction
* false, true, start a new global transaction, suspend any
existing global transaction
* true, false, start a new local transaction, suspend any other
transaction
* true, true, Error
****************************************************************************************/
// any work performed here is now in a new local UOW (i.e., outside a
transaction) that will // be ended by postInvoke
}
finally
{
tranControl.postInvoke(txHandle) ; // resumes previous global or local
UOW
}
Important: This mechanism gives you the outcome desired because
the invoked session bean has a transaction attribute of requiresNew
on the remote request. If Session Bean 2 is using Required for the
transaction attribute, using this technique causes the JDBC and EJB
operations to not roll back together if a failure occurs in the new
transaction. This is because these are now separate transactions.
This means that the application programmer has to write the application to
explicitly rollback any operations in the initial transaction that are
dependent on the new transaction.
|