bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

WebLogic Tuxedo Connector Programmer's Guide

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

- 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

Note: For more detailed information, see the JTA API.

The 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 Tuxedo transaction primitives to equivalent JTA transaction primitives.

Table 5-1 Mapping Tuxedo Transaction Primitives to JTA Equivalents

Tuxedo | Tuxedo Functionality | JTA Equivalent
--- | --- | ---
tpabort | Use to end a transaction. | setRollbackOnly
tpcommit | Use to complete a transaction. | commit
tpgetlev | Use to determine if a service routine is in transaction mode. | getStatus
tpbegin | Use to begin a transaction. | setTransactionTimeout begin

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() or a setRollbackOnly(). Any service subroutines that are called between the transaction delimiter become part of the current transaction.

Starting a Transaction

Note: 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 Tuxedo, you must 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 either commit() or a setRollbackOnly(). When commit() returns successfully, all changes to the resource as a result of the current transaction become permanent. setRollbackOnly() is used to indicate an abnormal condition and rolls back any call descriptors to their original state.

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.

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 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.

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;
>     }