Oracle WebLogic Tuxedo Connector Programmer's Guide
Oracle WebLogic Tuxedo Connector JATMI Transactions
The following sections provide information on global transactions and how to define and manage them in your applications:
- Global Transactions
- JTA Transaction API
- Defining a Transaction
- Oracle WebLogic Tuxedo Connector Transaction Rules
- Example Transaction Code
Global Transactions
A global transaction is a transaction that allows work involving more than one resource manager and spanning more than one physical site to be treated as one logical unit. A global transaction is always treated as a specific sequence of operations that is characterized by the following four properties:
- Atomicity: All portions either succeed or have no effect.
- Consistency: Operations are performed that correctly transform the resources from one consistent state to another.
- Isolation: Intermediate results are not accessible to other transactions, although other processes in the same transaction may access the data.
- Durability: All effects of a completed sequence cannot be altered by any kind of failure.
JTA Transaction API
For more detailed information, see the JTA API.
The Oracle WebLogic Tuxedo Connector uses the Java Transaction API (JTA) to manage transactions.
Types of JTA Interfaces
JTA offers three types of transaction interfaces:
- Transaction
- TransactionManager
- UserTransaction
Transaction
The Transaction interface allows operations to be performed against a transaction in the target Transaction object. A transaction object is created to correspond to each global transaction created. Use the Transaction interface to enlist resources, synchronize registration, and perform transaction completion and status query operations.
TransactionManager
The TransactionManager interface allows the application server to communicate to the Transaction Manager for transaction boundaries demarcation on behalf of the application. Use the TransactionManager interface to communicate to the transaction manager on behalf of container-managed EJB components.
UserTransaction
The UserTransaction interface is a subset of the TransactionManager interface. Use the UserTransaction interface when it is necessary to restrict access to Transaction object.
JTA Transaction Primitives
The following table maps the functionality of Oracle Tuxedo transaction primitives to equivalent JTA transaction primitives.
Defining a Transaction
Transactions can be defined in either client or server processes. A transaction has three parts: a starting point, the program statements that are in transaction mode, and a termination point.
To explicitly define a transaction, call the begin() method. The same process that makes the call, the initiator, must also be the one that terminates it by invoking a commit(), setRollbackOnly(), or rollback(). Any service subroutines that are called between the transaction delimiter become part of the current transaction.
Starting a Transaction
Setting setTransactionTimeout() to unrealistically large values delays system detection and reporting of errors. Use time-out values to ensure response to service requests occur within a reasonable time and to terminate transactions that have encountered problem, such as a network failure. For productions environments, adjust the time-out value to accommodate expected delays due to system load and database contention.
A transaction is started by a call to begin(). To specify a time-out value, precede the begin() statement with a setTransactionTimeout(int seconds) statement.
To propagate the transaction to Oracle Tuxedo, do the following:
- Look up a TuxedoConnectionFactory object in the JNDI.
- Get a TuxedoConnection object using getTuxedoConnection().
Using TPNOTRAN
Service routines that are called within the transaction delimiter are part of the current transaction. However, if tpcall() or tpacall() have the flags parameter set to TPNOTRAN, the operations performed by the called service do not become part of that transaction. As a result, services performed by the called process are not affected by the outcome of the current transaction.
Terminating a Transaction
A transaction is terminated by a call to commit(), rollback(), or setRollbackOnly(). When commit() returns successfully, all changes to the resource as a result of the current transaction become permanent. In order for a commit() to succeed, the following two conditions must be met:
- The calling process must be the same one that initiated the transaction with a begin()
- The calling process must have no transaction replies outstanding
If either condition is not true, the call fails and an exception is thrown.
setRollbackOnly() and rollback() are used to indicate an abnormal condition and to roll back any call descriptors to their original state.
- Use setRollbackOnly() if further processing or cleanup is needed before rolling back the transaction.
- Use rollback() if no further processing or cleanup is required before rolling back the transaction.
Oracle WebLogic Tuxedo Connector Transaction Rules
You must follow certain rules while in transaction mode to insure successful completion of a transaction. The basic rules of etiquette that must be observed while in a transaction mode follow:
- You must propagate the transaction to Oracle Tuxedo using a TuxedoConnection object after you initiate a transaction with a begin().
- tpterm() closes a connection to an object and prevents future operations on this object.
- Processes that are participants in the same transaction must require replies for their requests.
- Requests requiring no reply can be made only if the flags parameter of tpacall() is set to TPNOREPLY.
- A service must retrieve all asynchronous transaction replies before calling commit().
- The initiator must retrieve all asynchronous transaction replies before calling begin().
- The asynchronous replies that must be retrieved include those that are expected from non-participants of the transaction, that is, replies expected for requests made with a tpacall() suppressing the transaction but not the reply.
- If a transaction has not timed out but is marked abort-only, further communication should be performed with the TPNOTRAN flag set so that the work done as a result of the communication has lasting effect after the transaction is rolled back.
- If a transaction has timed out:
- the descriptor for the timed out call becomes stale and any further reference to it will return TPEBADDESC.
- further calls to tpgetrply() or tprecv() for any outstanding descriptors will return the global state of transaction time-out by setting tperrono to TPETIME.
- asynchronous calls can be make with the flags parameter of tpacall() set to TPNOREPLY | TPNOBLOCK | TPNOTRAN.
- Once a transaction has been marked abort-only for reasons other than time-out, a call to tpgetrply() will return whatever represents the local state of the call, that is, it can either return success or an error code that represents the local condition.
- Once a descriptor is used with tpgetrply() to retrieve a reply, it becomes invalid and any further reference to it will return TPEBADDESC.
- Once a descriptor is used with tpsend() or tprecv()to report an error condition, it becomes invalid and any further reference to it will return TPEV_DISCONIMM.
- Once a transaction is aborted, all outstanding transaction call descriptions (made without the TPNOTRAN flag) become stale, and any further reference to them will return TPEBADDESC.
- Oracle WebLogic Tuxedo Connector does not guarantee that all calls for a particular transaction Id are routed to a particular server instance when load balancing. Load balancing is performed on a per call basis.
Example Transaction Code
The following provides a code example for a transaction: Listing 5-1 Example Transaction Code
public class TransactionSampleBean implements SessionBean {
.....
public int transaction_sample () {
int ret = 0;
try {
javax.naming.Context myContext = new InitialContext();
TransactionManager tm = (javax.transaction.TransactionManager)
myContext.lookup("javax.transaction.TransactionManager");
// Begin Transaction
tm.begin ();
TuxedoConnectionFactory tuxConFactory = (TuxedoConnectionFactory)
ctxt.lookup("tuxedo.services.TuxedoConnection");
// You could do a local JDBC/XA-database operation here
// which will be part of this transaction.
.....
// NOTE 1: Get the Tuxedo Connection only after
// you begin the transaction if you want the
// Tuxedo call to be part of the transaction!
// NOTE 2: If you get the Tuxedo Connection before
// the transaction was started, all calls made from
// that Tuxedo Connection are out of scope of the
// transaction.
TuxedoConnection myTux = tuxConFactory.getTuxedoConnection();
// Do a tpcall. This tpcall is part of the transaction.
TypedString depositData = new TypedString("somecharacters,5000.00");
Reply depositReply = myTux.tpcall("DEPOSIT", depositData, 0);
// You could also do tpcalls which are not part of
// transaction (For example, Logging all attempted
// operations etc.) by setting the TPNOTRAN Flag!
TypedString logData =
new TypedString("DEPOSIT:somecharacters,5000.00");
Reply logReply = myTux.tpcall("LOGTRAN", logData,
ApplicationToMonitorInterface.TPNOTRAN);
// Done with the Tuxedo Connection. Do tpterm.
myTux.tpterm ();
// Commit Transaction...
tm.commit ();
// NOTE: The TuxedoConnection object which has been
// used in this transaction, can be used after the
// transaction only if TPNOTRAN flag is set.
}
catch (NamingException ne) {
System.out.println ("ERROR: Naming Exception looking up JNDI: " + ne);
ret = -1;
}
catch (RollbackException re) {
System.out.println("ERROR: TRANSACTION ROLLED BACK: " + re);
ret = 0;
}
catch (TPException te) {
System.out.println("ERROR: tpcall failed: TpException: " + te);
ret = -1;
}
catch (Exception e) {
log ("ERROR: Exception: " + e);
ret = -1;
}
return ret;
}