Oracle8i JDBC Developer's Guide and Reference Release 3 (8.1.7) Part Number A83724-01 |
Library | Service | Contents | Index

## XA Components

This section discusses the XA components--standard XA interfaces specified in the JDBC 2.0 Optional Package, and the Oracle classes that implement them. The following topics are covered:

- XA Data Source Interface and Oracle Implementation

- XA Connection Interface and Oracle Implementation

- XA Resource Interface and Oracle Implementation

- XA Resource Method Functionality and Input Parameters

- XA ID Interface and Oracle Implementation

### XA Data Source Interface and Oracle Implementation

The `javax.sql.XADataSource` interface outlines standard functionality of XA data sources, which are factories for XA connections. The overloaded `getXAConnection()` method returns an XA connection instance and optionally takes a user name and password as input:

    public interface XADataSource
    {
       XAConnection getXAConnection() throws SQLException;
       XAConnection getXAConnection(String user, String password)
          throws SQLException;
       ...
    }

Oracle JDBC implements the `XADataSource` interface with the `OracleXADataSource` class, located both in the `oracle.jdbc.xa.client package` and the `oracle.jdbc.xa.server` package.

The `OracleXADataSource` classes also extend the `OracleConnectionPoolDataSource` class (which extends the `OracleDataSource` class), so include all the connection properties described in "Data Source Properties".

The `OracleXADataSource` class `getXAConnection()` methods return the Oracle implementation of XA connection instances, which are `OracleXAConnection` instances (as the next section discusses).

Note: You can register XA data sources in JNDI using the same naming conventions as discussed previously for non-pooling data sources in "Register the Data Source".

### XA Connection Interface and Oracle Implementation

An XA connection instance, as with a pooled connection instance, encapsulates a physical connection to a database. This would be the database specified in the connection properties of the XA data source instance that produced the XA connection instance.

Each XA connection instance also has the facility to produce the XA resource instance that will correspond to it for use in coordinating the distributed transaction.

An XA connection instance is an instance of a class that implements the standard `javax.sql.XAConnection` interface:

    public interface XAConnection extends PooledConnection
    {
       javax.jta.xa.XAResource getXAResource() throws SQLException;
    }

As you see, the `XAConnection` interface extends the `javax.sql.PooledConnection` interface, so it also includes the `getConnection()`, `close()`, `addConnectionEventListener()`, and `removeConnectionEventListener()` methods listed in "Pooled Connection Interface and Oracle Implementation".

Oracle JDBC implements the `XAConnection` interface with the `OracleXAConnection` class, located both in the `oracle.jdbc.xa.client package` and the `oracle.jdbc.xa.server` package.

The `OracleXAConnection` classes also extend the `OraclePooledConnection` class.

The `OracleXAConnection` class `getXAResource()` method returns the Oracle implementation of an XA resource instance, which is an `OracleXAResource` instance (as the next section discusses). The `getConnection()` method returns an `OracleConnection` instance.

A JDBC connection instance returned by an XA connection instance acts as a temporary handle to the physical connection, as opposed to encapsulating the physical connection. The physical connection is encapsulated by the XA connection instance.

Each time an XA connection instance `getConnection()` method is called, it returns a new connection instance that exhibits the default behavior, and closes any previous connection instance that still exists and had been returned by the same XA connection instance. It is advisable to explicitly close any previous connection instance before opening a new one, however.

Calling the `close()` method of an XA connection instance closes the physical connection to the database. This is typically performed in the middle tier.

### XA Resource Interface and Oracle Implementation

The transaction manager uses XA resource instances to coordinate all the transaction branches that constitute a distributed transaction.

Each XA resource instance provides the following key functionality, typically invoked by the transaction manager:

- It associates and disassociates distributed transactions with the transaction branch operating in the XA connection instance that produced this XA resource instance. (Essentially, associates distributed transactions with the physical connection or session encapsulated by the XA connection instance.) This is done through use of transaction IDs.

- It performs the two-phase `COMMIT` functionality of a distributed transaction to ensure that changes are not committed in one transaction branch before there is assurance that the changes will succeed in all transaction branches.

  "XA Resource Method Functionality and Input Parameters" further discusses this.

  Notes: Because there must always be a one-to-one correlation between XA connection instances and XA resource instances, an XA resource instance is implicitly closed when the associated XA connection instance is closed.

An XA resource instance is an instance of a class that implements the standard `javax.transaction.xa.XAResource` interface:

    public interface XAResource
    {
       void commit(Xid xid, boolean onePhase) throws XAException;
       void end(Xid xid, int flags) throws XAException;
       void forget(Xid xid) throws XAException;
       int prepare(Xid xid) throws XAException;
       Xid[] recover(int flag) throws XAException;
       void rollback(Xid xid) throws XAException;
       void start(Xid xid, int flags) throws XAException;
       boolean isSameRM(XAResource xares) throws XAException;
    }

Oracle JDBC implements the `XAResource` interface with the `OracleXAResource` class, located both in the `oracle.jdbc.xa.client package` and the `oracle.jdbc.xa.server` package.

The Oracle JDBC driver creates and returns an `OracleXAResource` instance whenever the `OracleXAConnection` class `getXAResource()` method is called, and it is the Oracle JDBC driver that associates an XA resource instance with a connection instance and the transaction branch being executed through that connection.

This method is how an `OracleXAResource` instance is associated with a particular connection and with the transaction branch being executed in that connection.

### XA Resource Method Functionality and Input Parameters

The `OracleXAResource` class has several methods to coordinate a transaction branch with the distributed transaction with which it is associated. This functionality usually involves two-phase `COMMIT` operations.

A transaction manager, receiving `OracleXAResource` instances from a middle-tier component such as an application server, typically invokes this functionality.

Each of these methods takes a transaction ID as input, in the form of an `Xid` instance, which includes a transaction branch ID component and a distributed transaction ID component. Every transaction branch has a unique transaction ID, but transaction branches belonging to the same global transaction have the same global transaction component as part of their transaction IDs.

"XA ID Interface and Oracle Implementation" discusses the `OracleXid` class and the standard interface upon which it is based.

Following is a description of key XA resource functionality, the methods used, and additional input parameters. Each of these methods throws an XA exception if an error is encountered. See "XA Exception Classes and Methods".

##### Start

Start work on behalf of a transaction branch, associating the transaction branch with a distributed transaction.

    void start(Xid xid, int flags)

The `flags` parameter can have one of the following values:

- `XAResource.TMNOFLAGS` (no special flag)--This is to flag the start of a new transaction branch for subsequent operations in the session associated with this XA resource instance. This branch will have the transaction ID `xid`, which is an `OracleXid` instance created by the transaction manager. This will map the transaction branch to the appropriate distributed transaction.

- `XAResource.TMJOIN`--This is to join subsequent operations in the session associated with this XA resource instance to the existing transaction branch specified by `xid`.

- `XAResource.TMRESUME`--This is to resume the transaction branch specified by `xid`. (It must first have been suspended.)

`TMNOFLAGS`, `TMJOIN`, and `TMRESUME` are defined as static members of the `XAResource` interface and `OracleXAResource` class.

Note: Instead of using the `start()` method with `TMRESUME`, the transaction manager can cast to an `OracleXAResource` instance and use the `resume(Xid xid)` method, an Oracle extension.

Note that to create an appropriate transaction ID in starting a transaction branch, the transaction manager must know which distributed transaction the transaction branch should belong to. The mechanics of this are handled between the middle tier and transaction manager and are beyond the scope of this document. Refer to the Sun Microsystems specifications for the JDBC 2.0 Optional Package and the Java Transaction API.

##### End

End work on behalf of the transaction branch specified by `xid`, disassociating the transaction branch from its distributed transaction.

    void end(Xid xid, int flags)

The `flags` parameter can have one of the following values:

- `XAResource.TMSUCCESS`--This is to indicate that this transaction branch is known to have succeeded.

- `XAResource.TMFAIL`--This is to indicate that this transaction branch is known to have failed.

- `XAResource.TMSUSPEND`--This is to suspend the transaction branch specified by `xid`. (By suspending transaction branches, you can have multiple transaction branches in a single session. Only one can be active at any given time, however. Also, this tends to be more expensive in terms of resources than having two sessions.)

`TMSUCCESS`, `TMFAIL`, and `TMSUSPEND` are defined as static members of the `XAResource` interface and `OracleXAResource` class.

Notes: Instead of using the `end()` method with `TMSUSPEND`, the transaction manager can cast to an `OracleXAResource` instance and use the `suspend(Xid xid)` method, an Oracle extension. This XA functionality to suspend a transaction provides a way to switch between various transactions within a single JDBC connection. You can use the XA classes to accomplish this, even if you are not in a distributed transaction environment and would otherwise have no need for the XA classes.

##### Prepare

Prepare the changes performed in the transaction branch specified by `xid`. This is the first phase of a two-phase `COMMIT` operation, to ensure that the database is accessible and that the changes can be committed successfully.

    int prepare(Xid xid)

This method returns an integer value as follows:

- `XAResource.XA_RDONLY`--This is returned if the transaction branch executes only read-only operations such as `SELECT` statements.

- `XAResource.XA_OK`--This is returned if the transaction branch executes updates that are all prepared without error.

- n/a (no value returned)--No value is returned if the transaction branch executes updates and any of them encounter errors during preparation. In this case, an XA exception is thrown.

`XA_RDONLY` and `XA_OK` are defined as static members of the `XAResource` interface and `OracleXAResource` class.

Notes: Always call the `end()` method on a branch before calling the `prepare()` method. If there is only one transaction branch in a distributed transaction, then there is no need to call the `prepare()` method. You can call the XA resource `commit()` method without preparing first.

##### Commit

Commit prepared changes in the transaction branch specified by `xid`. This is the second phase of a two-phase `COMMIT` and is performed only after all transaction branches have been successfully prepared.

    void commit(Xid xid, boolean onePhase)

Set the `onePhase` parameter as follows:

- `true`--This is to use one-phase instead of two-phase protocol in committing the transaction branch. This is appropriate if there is only one transaction branch in the distributed transaction; the `prepare` step would be skipped.

- `false`--This is to use two-phase protocol in committing the transaction branch (typical).

##### Roll back

Rolls back prepared changes in the transaction branch specified by `xid`.

    void rollback(Xid xid)

##### Forget

Tells the resource manager to forget about a heuristically completed transaction branch.

    public void forget(Xid xid)

##### Recover

The transaction manager calls this method during recovery to obtain the list of transaction branches that are currently in prepared or heuristically completed states.

    public Xid[] recover(int flag)

Note: The `flag` parameter is ignored and therefore not implemented for Oracle8i 8.1.7 since the `scan` option (flag parameter) is not meaningful without a `count` parameter. See the Sun Microsystems Java Transaction API (JTA) Specification for more detail.

The resource manager returns zero or more `Xid`s for the transaction branches that are currently in a prepared or heuristically completed state. If an error occurs during the operation, the resource manager throws the appropriate `XAException`.

##### Check for same RM

To determine if two XA resource instances correspond to the same resource manager (database), call the `isSameRM()` method from one XA resource instance, specifying the other XA resource instance as input. In the following example, presume `xares1` and `xares2` are `OracleXAResource` instances:

    boolean sameRM = xares1.isSameRM(xares2);

A transaction manager can use this method regarding certain Oracle optimizations, as "Oracle XA Optimizations" explains.

### XA ID Interface and Oracle Implementation

The transaction manager creates transaction ID instances and uses them in coordinating the branches of a distributed transaction. Each transaction branch is assigned a unique transaction ID, which includes the following information:

- format identifier (4 bytes)

  A format identifier specifies a Java transaction manager--for example, there could be a format identifier `ORCL`. This field cannot be null.

- global transaction identifier (64 bytes) (or "distributed transaction ID component", as discussed earlier)

- branch qualifier (64 bytes) (or "transaction branch ID component", as discussed earlier)

The 64-byte global transaction identifier value will be identical in the transaction IDs of all transaction branches belonging to the same distributed transaction. The overall transaction ID, however, is unique for every transaction branch.

An XA transaction ID instance is an instance of a class that implements the standard `javax.transaction.xa.Xid` interface, which is a Java mapping of the X/Open transaction identifier XID structure.

Oracle implements this interface with the `OracleXid` class in the `oracle.jdbc.xa` package. `OracleXid` instances are employed only in a transaction manager, transparent to application programs or an application server.

Note: Oracle8i 8.1.7 does not require the use of `OracleXid` for Oracle XA resource calls. Instead, use any class that implements `javax.transaction.xa.Xid` interface.

A transaction manager may use the following in creating an `OracleXid` instance:

    public OracleXid(int fId, byte gId[], byte bId[]) throws XAException

Where `fId` is an integer value for the format identifier, `gId[]` is a byte array for the global transaction identifier, and `bId[]` is a byte array for the branch qualifier.

The `Xid` interface specifies the following getter methods:

- `public int getFormatId()`

- `public byte[] getGlobalTransactionId()`

- `public type[] getBranchQualifier()`

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index