JBoss.orgCommunity Documentation
Some transaction specifications and systems define a generic resource which can be used to register arbitrary
resources with a transaction, the JTA is much more XA-specific. Interface
javax.transaction.xa.XAResource
is a Java mapping of the XA interface. The
XAResource
interface defines the contract between a
ResourceManager
and a TransactionManager
in a
distributed transaction processing environment. A resource adapter for a
ResourceManager
implements the XAResource
interface
to support association of a top-level transaction to a resource such as a relational database.
The XAResource
interface can be supported by any transactional resource adapter
designed to be used in an environment where transactions are controlled by an external transaction manager, such a
database management system. An application may access data through multiple database connections. Each database
connection is associated with an XAResource
object that serves as a proxy object to
the underlying ResourceManager
instance. The transaction manager obtains an
XAResource
for each ResourceManager
participating in
a top-level transaction. The start
method associates the transaction with the resource,
and the end
method disassociates the transaction from the resource.
The ResourceManager
associates the transaction with all work performed on its data
between invocation of start
and end
methods. At transaction
commit time, these transactional ResourceManager
s are informed by the transaction
manager to prepare, commit, or roll back the transaction according to the two-phase commit protocol.
For better Java integration, the XAResource
differs from the standard
XA
interface in the following ways:
The resource adapter implicitly initializes the ResourceManager
when the
resource (the connection) is acquired. There is no equivalent to the xa_open
method
of the interface XA
.
Rmid
is not passed as an argument. Each Rmid
is represented by a
separate XAResource
object.
Asynchronous operations are not supported, because Java supports multi-threaded processing and most databases do not support asynchronous operations.
Error return values caused by the transaction manager’s improper handling of the
XAResource
object are mapped to Java exceptions via the
XAException
class.
The DTP concept of Thread of Control maps to all Java threads that are given access to the
XAResource
and Connection
objects. For example,
it is legal for two different threads to perform the start
and
end
operations on the same XAResource
object.
By default, whenever an XAResource
object is registered with a JTA-compliant
transaction service, there is no way to manipulate the order in which it is invoked during the two-phase commit
protocol, with respect to other XAResource
objects. JBoss Transactions, however, provides
support for controlling the order via the two interfaces
com.arjuna.ats.jta.resources.StartXAResource
and
com.arjuna.ats.jta.resources.EndXAResource
. By inheriting your
XAResource
instance from either of these interfaces, you control whether an
instance of your class is invoked first or last, respectively.
Only one instance of each interface type may be registered with a specific transaction.
The ArjunaCore Development Guide discusses the Last Resource Commit
optimization (LRCO), whereby a single resource that is only one-phase aware, and does not support
the prepare
phase, can be enlisted with a transaction that is manipulating two-phase
aware participants. This optimization is also supported within the JBoss Transactions.
In order to use the LRCO, your XAResource
implementation must extend the
com.arjuna.ats.jta.resources.LastResourceCommitOptimisation
marker interface. A
marker interface is an interface which provides no methods. When
enlisting the resource via method Transaction.enlistResource
, JBoss Transactions ensures that only a single instance of this
type of participant is used within each transaction. Your resource is driven last in the commit protocol,
and no invocation of method prepare
occurs.
By default an attempt to enlist more than one instance of a LastResourceCommitOptimisation class will fail and false will be returned from Transaction.enlistResource. This behavior can be overridden by setting the com.arjuna.ats.jta.allowMultipleLastResources to true. However, before doing so you should read the section on enlisting multiple one-phase aware resources.
You need to disable interposition support to use the LCRO in a distributed environment. You can still use implicit context propagation.
One-phase commit is used to process a single one-phase aware resource, which does not conform to the two-phase commit protocol. You can still achieve an atomic outcome across resources, by using the LRCO, as explained earlier.
Multiple one-phase-aware resources may be enlisted in the same transaction. One example is when a legacy
database runs within the same transaction as a legacy JMS implementation. In such a situation, you cannot
achieve atomicity of transaction outcome across multiple resources, because none of them enter the
prepare
state. They commit or roll back immediately when instructed by the
transaction coordinator, without knowledge of other resource states and without a way to undo if subsequent
resources make a different choice. This can result in data corruption or heuristic outcomes.
You can approach these situations in two different ways:
Wrap the resources in compensating transactions. See the XTS Transactions Development Guide for details.
Migrate the legacy implementations to two-phase aware equivalents.
If neither of these options is viable, JBoss Transactions support enlisting multiple one-phase aware resources within the same transaction, using LRCO, which is discussed in the ArjunaCore Development Guide in detail.
Even when this support is enabled, JBoss Transactions issues a warning when it detects that the option has been
enabled: You have chosen to enable multiple last resources in the transaction manager. This is
transactionally unsafe and should not be relied upon.
Another warning is issued when multiple
one-phase aware resources are enlisted within a transaction: This is transactionally unsafe and
should not be relied on.
To override the above-mentioned warning at runtime, set the
CoreEnvironmentBean.disableMultipleLastResourcesWarning
property to
true
. You will see a warning that you have done this when JBoss Transactions starts up and see the
warning about enlisting multiple one-phase resources only the first time it happens, but after that no
further warnings will be output. You should obviously only consider changing the default value of this
property (false) with caution.
The X/Open XA
interface requires the transaction manager to initialize a resource
manager, using method xa_open
, before invoking any other of the interface's methods. JTA
requires initialization of a resource manager to be embedded within the resource adapter that represents the
resource manager. The transaction manager does not need to know how to initialize a resource manager. It only
informs the resource manager about when to start and end work associated with a transaction and when to complete
the transaction. The resource adapter opens the resource manager when the connection to the resource manager is
established.
The resource adapter closes a resource manager as a result of destroying the transactional resource. A transaction resource at the resource adapter level is comprised of two separate objects:
An XAResource
object that allows the transaction manager to start and end the
transaction association with the resource in use and to coordinate transaction completion process.
A connection object that allows the application to perform operations on the underlying resource, such as JDBC operations on an RDBMS.
Once opened, the resource manager is kept open until the resource is released explicitly. When the application
invokes the connection’s close
method, the resource adapter invalidates the connection
object reference that was held by the application and notifies the application server about the close. The
transaction manager invokes the XAResource.end
method to disassociate the transaction
from that connection.
The close notification triggers the application server to perform any necessary cleanup work and to mark the physical XA connection as free for reuse, if connection pooling is in place.
The X/Open XA
interface specifies that the transaction-association-related
xa
calls must be invoked from the same thread context. This
thread-of-control requirement does not apply to the object-oriented component-based
application run-time environment, in which application threads are dispatched dynamically as methods are
invoked.. Different threads may use the same connection resource to access the resource manager if the connection
spans multiple method invocation. Depending on the implementation of the application server, different threads may
be involved with the same XAResource
object. The resource context and the
transaction context operate independent of thread context. This creates the possibility of different threads
invoking the start
and end
methods.
If the application server allows multiple threads to use a single XAResource
object
and the associated connection to the resource manager, the application server must ensure that only one
transaction context is associated with the resource at any point of time. Thus the
XAResource
interface requires the resource managers to support the two-phase commit
protocol from any thread context.
A transaction is associated with a transactional resource via the start
method and disassociated from the
resource via the end
method. The resource adapter internally maintains an association between
the resource connection object and the XAResource
object. At any given time, a
connection is associated with zero or one transaction. JTA does not support nestedtransactions, so attempting to
invoke the start
method on a thread that is already associated with a transaction is an error.
The transaction manager can Interleave multiple transaction contexts using the same resource, as long as methods
start
and end
are invoked properly for each transaction context
switch. Each time the resource is used with a different transaction, the method end
must
be invoked for the previous transaction that was associated with the resource, and method
start
must be invoked for the current transaction context.
For a transactional application whose transaction states are managed by an application server, its resources must
also be managed by the application server so that transaction association is performed properly. If an application
is associated with a transaction, the application must not perform transactional work through the
connection without having the connection’s resource object already associated with the global transaction. The
application server must ensure that the XAResource
object in use is associated with
the transaction, by invoking the Transaction.enlistResource
method.
If a server-side transactional application retains its database connection across multiple client requests, the application server must ensure that before dispatching a client request to the application thread, the resource is enlisted with the application’s current transaction context. This implies that the application server manages the connection resource usage status across multiple method invocations.
When the same transactional resource is used to interleave multiple transactions, the application server must ensure that only one transaction is enlisted with the resource at any given time. To initiate the transaction commit process, the transaction manager is allowed to use any of the resource objects connected to the same resource manager instance. The resource object used for the two-phase commit protocol does not need to have been involved with the transaction being completed.
The resource adapter must be able to handle multiple threads invoking the
XAResource
methods concurrently for transaction commit processing. This is
illustrated in Example 3.1, “Resource sharing example”.
Example 3.1. Resource sharing example
XAResource xares = r1.getXAResource();
xares.start(xid1); // associate xid1 to the connection
..
xares.end(xid1); // disassociate xid1 to the connection
..
xares.start(xid2); // associate xid2 to the connection
..
// While the connection is associated with xid2,
// the TM starts the commit process for xid1
status = xares.prepare(xid1);
..
xares.commit(xid1, false);
A transactional resource r1
. Global transaction xid1
is
started and ended with r1. Then a different global transaction xid2
is associated with
r1
. Meanwhile, the transaction manager may start the two phase commit process for
xid1
using r1
or any other transactional resource connected to
the same resource manager. The resource adapter needs to allow the commit process to be executed while the
resource is currently associated with a different global transaction.
The resource adapter must support the usage of both local and global transactions within the same transactional
connection. Local transactions are started and coordinated by the resource manager internally. The
XAResource
interface is not used for local transactions. When using the same
connection to perform both local and global transactions, the following rules apply:
The local transaction must be committed or rolled back before a global transaction is started in the connection.
The global transaction must be disassociated from the connection before any local transaction is started.
You can associate timeout values with transactions in order to control their lifetimes. If the timeout value
elapses before a transaction terminates, by committing or rolling back, the transaction system rolls it back. The
XAResource
interface supports a setTransactionTimeout
operation, which allows the timeout associated with the current transaction to be propagated to the resource
manager and if supported, overrides any default timeout associated with the resource manager. Overriding the
timeout can be useful when long-running transactions may have lifetimes that would exceed the default, and using
the default timeout would cause the resource manager to roll back before the transaction terminates, and cause the
transaction to roll back as well.
If You do not explicitly set a timeout value for a transaction, or you use a value of 0
, an
implementation-specific default value may be used. In JBoss Transactions, property value
CoordinatorEnvironmentBean.defaultTimeout
represents this implementation-specific default, in
seconds. The default value is 60 seconds. A value of 0
disables default transaction timeouts.
Unfortunately, imposing the same timeout as the transaction on a resource manager is not always appropriate. One
example is that your business rules may require you to have control over the lifetimes on resource managers
without allowing that control to be passed to some external entity. JBoss Transactions supports an all-or-nothing approach to
whether or not method setTransactionTimeout
is called on
XAResource
instances.
If the JTAEnvironmentBean.xaTransactionTimeoutEnabled
property is set to
true
, which is the default, it is called on all instances. Otherwise, use the
setXATransactionTimeoutEnabled
method of
com.arjuna.ats.jta.common.Configuration
.
Dynamic registration is not supported in XAResource
. There are two reasons this
makes sense.
In the Java component-based application server environment, connections to the resource manager are acquired dynamically when the application explicitly requests a connection. These resources are enlisted with the transaction manager on an as-needed basis.
If a resource manager needs to dynamically register its work to the global transaction, you can implement this at the resource adapter level via a private interface between the resource adapter and the underlying resource manager.