Monday, November 12, 2007

Distributed Transactions::JAVA-JDBC2

XADataSource and XAConnection

The XADataSource and XAConnection interfaces, which are defined in the package javax.sql, are implemented by JDBC drivers that support distributed transactions. An XAConnection object is a pooled connection that can participate in a distributed transaction. More precisely, XAConnection extends the PooledConnection interface by adding the method getXAResource. This method produces an XAResource object that can be used by a transaction manager to coordinate the work done on this connection with the other participants in the distributed transaction.

CODE EXAMPLE gives the definition of the XAConnection interface.

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

CODE EXAMPLE The XAConnection interface Because they extend the PooledConnection interface, XAConnection objects support all the methods of PooledConnection objects. They are reusable physical connections to an underlying data source and produce logical connection handles that can be passed back to a JDBC application. XAConnection objects are produced by an XADataSource object. There is some similarity between ConnectionPoolDataSource objects and XADataSource objects in that they are both implemented below a DataSource layer that is visible to the JDBC application. This architecture allows JDBC drivers to support distributed transactions in a way that is transparent to the application.

CODE EXAMPLE shows the signatures for the two getXAConnection methods

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

...
}

CODE EXAMPLE The XADataSource interface Typically, DataSource implementations built on top of an XADataSource implementation will also include a connection pooling module.
12.2.1 Deploying an XADataSource Object Deploying an XADataSource object is done in exactly the same manner as previously described for ConnectionPoolDataSource objects. The two-step
process includes deploying the XADataSource object and the application-visible DataSource object, as is done in

CODE EXAMPLE

// com.acme.jdbc.XADataSource implements the
// XADataSource interface.
// Create an instance and set properties.
com.acme.jdbc.XADataSource xads = new com.acme.jdbc.XADataSource();
xads.setServerName(“bookstore”);
xads.setDatabaseName(“bookinventory”);
xads.setPortNumber(9040);
xads.setDescription(“XADataSource for inventory”);
// First register xads with a JNDI naming service, using the
// logical name “jdbc/xa/inventory_xa”
Context ctx = new InitialContext();
ctx.bind(“jdbc/xa/inventory_xa”, xads);
// Next register the overlying DataSource object for application
// access. com.acme.appserver.DataSource is an implementation of
// the DataSource interface.
// Create an instance and set properties.
com.acme.appserver.DataSource ds =
new com.acme.appserver.DataSource();
ds.setDescription(“Datasource supporting distributed transactions”);
// Reference the previously registered XADataSource
ds.setDataSourceName(“jdbc/xa/inventory_xa”);
// Register the DataSource implementation with a JNDI naming service,
// using the logical name “jdbc/inventory”.
ctx.bind(“jdbc/inventory”, ds);

CODE EXAMPLE Deploying a DataSource object backed by an XADataSource object

Getting a Connection

As in the connection pooling case, the application call to the method DataSource.getConnection returns a logical handle produced by the physical XAConnection object. The application code to get a logical connection is shown in

CODE EXAMPLE

Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(“jdbc/inventory”);
Connection con = ds.getConnection(“myID”,“mypasswd”);

CODE EXAMPLE Application code to get a logical connection
CODE EXAMPLE is an example of code from the middle-tier server’s implementation of the method DataSource.getConnection.

// Assume xads is a driver’s implementation of XADataSource
XADataSource xads = (XADataSource)ctx.lookup(“jdbc/xa/" +
"inventory_xa”);
// xacon implements XAConnection
XAConnection xacon = xads.getXAConnection(“myID”, “mypasswd”);
// Get a logical connection to pass back up to the application
Connection con = xacon.getConnection();

CODE EXAMPLE Getting a logical connection from an XAConnection object

XAResource

The XAResource interface is defined in the JTA specification and is the mapping in the Java programming language of the X/Open Group XA interface. An XAResource object is produced by calling the XAConnection.getXAResource method and is used to associate an XAConnection object with a distributed transaction. A given XAConnection object may be associated with at most one transaction at a time. The JDBC driver maintains a one-to-one correspondence
between an XAResource object and its associated XAConnection object; that is, multiple calls to the getXAResource method must all return the same object. In a typical scenario, the middle-tier application server calls the method XAConnection.getXAResource and passes the returned object to an external transaction manager. The transaction manager uses the XAResource object exclusively—it does not access an XAConnection object directly. The transaction manager coordinates the work of multiple XAResource objects, each of which represents a resource manager participating in the distributed transaction. Note that two XAResource objects may “point” to the same resource manager, that is, they may be associated with XAConnection objects that were produced by the same XADataSource. The following XAResource methods are used by the transaction manager to implement a two-phase commit protocol.

Each method takes an xid parameter that identifies the distributed transaction:

  • start — tells the resource manager that the subsequent operations are part of the distributed transaction.
  • end — marks the end of this resource manager’s part of the distributed transaction.
  • prepare — gets the resource manager’s vote on whether to commit or roll back the distributed transaction.
  • commit — tells the resource manager to commit its part of the distributed transaction. This method is invoked only if all the participating resource managers voted to commit the transaction.
  • rollback — tells the resource manager to roll back its part of the distributed transaction. This method is invoked if one or more of the participating resource managers voted to roll back the transaction.
See the JTA specification for a complete description of the XAResouce interface.

Transaction Management

Participation in a distributed transaction is defined as the work done between invocations of the methods XAResource.start and XAResource.end. Outside these boundaries, the transaction mode is local, and a connection behaves exactly like a local connection. With one exception, there is no difference in how an application participating in a distributed transaction is coded. In contrast to the local case, the boundaries of a distributed transaction must be controlled by an external transaction manager that is coordinating the work of multiple connections. For this reason, it is an error for applications to call any of the following Connection methods while they are participating in a distributed transaction:

  • setAutoCommit(true)
  • commit
  • rollback
  • setSavepoint
The JDBC driver throws an SQLException if one of these operations is attempted on a connection that is participating in a distributed transaction. If the connection is later used for a local transaction, these operations are legal at that point. Applications should also refrain from calling Connection.setTransactionIsolation within the bounds of a distributed transaction. The resulting behavior is implementation-defined. If a connection has auto-commit mode already enabled at the time it joins a global transaction, the attribute will be ignored. The auto-commit behavior will resume when the connection returns to local transaction mode.

No comments: