This chapter describes the TimesTen implementation of the Java Transaction API (JTA).
The TimesTen implementation of the Java JTA interfaces is intended to enable Java applications, application servers, and transaction managers to use TimesTen resource managers in distributed transaction processing (DTP) environments. The TimesTen implementation is supported for use by the Oracle WebLogic Server.
The purpose of this chapter is to provide information specific to the TimesTen implementation of JTA and is intended to be used with the following documents:
The JTA and JDBC documentation available from the following locations:
WebLogic documentation, available through the following location:
http://www.oracle.com/technetwork/middleware/weblogic/documentation
As TimesTen JTA is built on top of the TimesTen implementation of the X/Open XA standard, much of the discussion here is in terms of underlying XA features. You can also refer to "Distributed Transaction Processing: XA" in Oracle TimesTen In-Memory Database C Developer's Guide.
This chapter includes the following topics:
Important:
The TimesTen XA implementation does not work with the Oracle In-Memory Database Cache (IMDB Cache). The start of any XA transaction will fail if the cache agent is running.
You cannot execute an XA transaction if replication is enabled.
Do not execute DDL statements within an XA transaction.
This section provides a brief overview of the following XA concepts.
Figure 4-1 illustrates the interfaces defined by the X/Open DTP model.
Figure 4-1 Distributed transaction processing model
The TX interface is what applications use to communicate with a transaction manager. The figure shows an application communicating global transactions to the transaction manager. In the DTP model, the transaction manager breaks each global transaction down into multiple branches and distributes them to separate resource managers for service. It uses the JTA interface to coordinate each transaction branch with the appropriate resource manager.
In the context of TimesTen JTA, the resource managers can be a collection of TimesTen databases, or databases in combination with other commercial databases that support JTA.
Global transaction control provided by the TX and JTA interfaces is distinct from local transaction control provided by the native JDBC interface. It is generally best to maintain separate connections for local and global transactions. Applications can obtain a connection handle to a TimesTen resource manager to initiate both local and global transactions over the same connection.
In a JTA implementation, the transaction manager commits the distributed branches of a global transaction by using a two-phase commit protocol.
In phase 1, the transaction manager directs each resource manager to prepare to commit, which is to verify and guarantee it can commit its respective branch of the global transaction. If a resource manager cannot commit its branch, the transaction manager rolls back the entire transaction in phase 2.
In phase 2, the transaction manager either directs each resource manager to commit its branch or, if a resource manager reported it was unable to commit in phase 1, rolls back the global transaction.
Note the following optimizations.
If a global transaction is determined by the transaction manager to have involved only one branch, it skips phase 1 and commits the transaction in phase 2.
If a global transaction branch is read-only, where it does not generate any transaction log records, the transaction manager commits the branch in phase 1 and skips phase 2 for that branch.
Note:
The transaction manager considers the global transaction committed if and only if all branches successfully commit.This section discusses the following considerations for using JTA in TimesTen:
To guarantee global transaction consistency, TimesTen XA transaction branches must be durable. The TimesTen implementation of the xa_prepare()
, xa_rollback()
, and xa_commit()
functions log their actions to disk, regardless of the value set in the DurableCommits
general connection attribute or by the ttDurableCommit
built-in procedure. If you must recover from a failure, both the resource manager and the TimesTen transaction manager have a consistent view of which transaction branches were active in a prepared state at the time of failure.
Rollback of transactions requires transaction logging, which is always enabled with XA.
When a database is loaded from disk to recover after a failure or unexpected termination, any global transactions that were prepared but not committed are left pending, or in doubt. Normal processing is not enabled until the disposition of all in-doubt transactions has been resolved.
After connection and recovery are complete, TimesTen checks for in-doubt transactions. If there are no in-doubt transactions, operation proceeds as normal. If there are in-doubt transactions, other connections may be created, but virtually all operations are prohibited on those connections until the in-doubt transactions are resolved. Any other JDBC calls result in the following error:
Error 11035 - "In-doubt transactions awaiting resolution in recovery must be resolved first"
The list of in-doubt transactions can be retrieved through the XA implementation of xa_recover()
, then dealt with through the XA call xa_commit()
, xa_rollback()
, or xa_forget()
, as appropriate. After all the in-doubt transactions are cleared, operations proceed normally.
This scheme should be adequate for systems that operate strictly under control of the transaction manager, since the first thing the transaction manager should do after connect is to call xa_recover()
.
If the transaction manager is unavailable or cannot resolve an in-doubt transaction, you can use the ttXactAdmin
utility to independently commit or abort the individual transaction branches. Be aware, however, that these ttXactAdmin
options require ADMIN
privilege. See "ttXactAdmin" in Oracle TimesTen In-Memory Database Reference.
The XA specification has a limited, strictly defined set of errors that can be returned from XA interface calls. The ODBC SQLError
mechanism returns XA defined errors, along with any additional information.
The TimesTen XA related errors begin at number 11000. Errors 11002 through 11020 correspond to the errors defined by the XA standard.
See "Warnings and Errors" in Oracle TimesTen In-Memory Database Error Messages and SNMP Traps for the complete list of errors.
The TimesTen implementation of JTA provides an API consistent with that specified in the JTA specification. TimesTen JTA operates on JDK 1.4 and above.
This section covers the following topics for using the JTA API:
Regarding how to register a TimesTen DSN with WebLogic, information on configuring TimesTen for application servers and object-relational mapping frameworks is available in the TimesTen Quick Start. Click J2EE and OR Mapping under Configuration and Setup.
The TimesTen JDBC and XA implementations are available in the following packages:
com.timesten.jdbc.*; com.timesten.jdbc.xa.*;
Your application should also import these standard packages:
import java.sql.*; import javax.sql.*; import javax.transaction.xa.*;
Connections to XA data sources are established through XADataSource
objects. You can create an XAConnection
object for your database by using the TimesTenXADataSource
instance as a connection factory. TimesTenXADataSource
implements the javax.sql.XADataSource
interface.
After creating a new TimesTenXADataSource
instance, use the setUrl()
method to specify a database. The URL should look similar to the following.
For a direct connection:
jdbc:timesten:direct:DSNname
For a client connection:
jdbc:timesten:client:DSNname
You can also optionally use the setUser()
and setPassword()
methods to set the ID and password for a specific user.
Note:
Privilege must be granted to connect to a database. Refer to "Access control for connections".Example 4-1 Creating a TimesTen XA data source object
In this example, the TimesTenXADataSource
object is used as a factory to create a new TimesTen XA data source object. Then the URL that identifies the TimesTen DSN (dsn1
), the user name (myName
), and the password (myPasswd
) are set for this TimesTenXADataSource
instance. Then the getXAConnection()
method is used to return a connection to the object, xaConn
.
TimesTenXADataSource xads = new TimesTenXADataSource(); xads.setUrl("jdbc:timesten:direct:dsn1"); xads.setUser("myName"); xads.setPassword("myPassword"); XAConnection xaConn = null; try { xaConn = xads.getXAConnection(); } catch (SQLException e){ e.printStackTrace(); return; }
You can create multiple connections to an XA data source object. This example creates a second connection, xaConn2
:
XAConnection xaConn = null; XAConnection xaConn2 = null; try { xaConn = xads.getXAConnection(); xaConn2 = xads.getXAConnection(); }
Example 4-2 Creating multiple TimesTen XA data source objects
This example creates two instances of TimesTenXADataSource
for the databases named dsn1
and dsn2
. It then creates a connection for dsn1
and two connections for dsn2
.
TimesTenXADataSource xads = new TimesTenXADataSource(); xads.setUrl("jdbc:timesten:direct:dsn1"); xads.setUser("myName"); xads.setPassword("myPassword"); XAConnection xaConn1 = null; XAConnection xaConn2 = null; XAConnection xaConn3 = null; try { xaConn1 = xads.getXAConnection(); // connect to dsn1 } catch (SQLException e){ e.printStackTrace(); return; } xads.setUrl("jdbc:timesten:direct:dsn2"); xads.setUser("myName"); xads.setPassword("myPassword"); try { xaConn2 = xads.getXAConnection(); // connect to dsn2 xaConn3 = xads.getXAConnection(); // connect to dsn2 } catch (SQLException e){ e.printStackTrace(); return; }
Note:
Once anXAConnection
is established, autocommit is off.After using getXAConnection()
to obtain an XAConnection
object, you can use the XAConnection
method getXAResource()
to obtain an XAResource
object, then the XAConnection
method getConnection()
to obtain a Connection
object for the underlying connection.
Example 4-3 Getting an XA resource object and a connection
//get an XAResource XAResource xaRes = null; try { xaRes = xaConn.getXAResource(); }catch (SQLException e){ e.printStackTrace(); return; } //get an underlying physical Connection Connection conn = null; try { conn = xaConn.getConnection(); }catch (SQLException e){ e.printStackTrace(); return; }
From this point, you can use the same connection, conn
, for both local and global transactions. Be aware of the following, however.
You must commit or roll back an active local transaction before starting a global transaction. Otherwise you will get the XAException
exception XAER_OUTSIDE
.
You must end an active global transaction before initiating a local transaction, otherwise you will get a SQLException
, "Illegal combination of local transaction and global (XA) transaction."