Transactions Development Guide
Developing Applications Using JTA, JTS, and XTS APIs
Edition 5.1.0
Abstract
Part I. JTA Development
Chapter 1. An Introduction to the Java Transaction API (JTA)
- Application Server
- Provides the infrastructure required to support an application run-time environment which includes transaction state management, such as an EJB server.
- Transaction Manager
- Provides the services and management functions required to support transaction demarcation, transactional resource management, synchronization, and transaction context propagation.
- Resource Manager
- (through a resource adapter[1]) Provides the application with access to resources. The resource manager participates in distributed transactions by implementing a transaction resource interface. The transaction manager uses this interface to communicate transaction association, transaction completion, and recovery.
- Communication Resource Manager (CRM)
- Supports transaction context propagation and access to the transaction service for incoming and outgoing requests.
Note
Chapter 2. The JBoss JTA Implementation
- A high-level application transaction demarcation interface
- A high-level transaction manager interface intended for application server
- A standard Java mapping of the X/Open XA protocol intended for transactional resource manager
Important
2.1. UserTransaction
UserTransaction
interface allows applications to control transaction boundaries. It provides methods for beginning, committing, and rolling back top-level transactions. Nested transactions are not supported, and the begin
method throws the NotSupportedException
when the calling thread is already associated with a transaction. UserTransaction
automatically associates newly created transactions with the invoking thread.
Note
UserTransaction
from JNDI.
InitialContext ic = new InitialContext(); UserTransaction utx = ic.lookup("java:comp/UserTransaction")
- Set the com.arjuna.ats.jta.jtaTMImplementation property to
com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple
. - Set the com.arjuna.ats.jta.jtaUTImplementation property to
com.arjuna.ats.internal.jta.transaction.arjunacore.UserTransactionImple
.
2.2. TransactionManager
TransactionManager
interface allows the application server to control transaction boundaries on behalf of the application being managed.
Note
TransactionManager
from JNDI.
InitialContext ic = new InitialContext(); TransactionManager utm = ic.lookup("java:/TransactionManager")
null
or it refers to a specific global transaction. Multiple threads can be associated with the same global transaction. Nested transactions are not supported.
begin
method of TransactionManager
begins a new top-level transaction, and associates the transaction context with the calling thread. If the calling thread is already associated with a transaction then the begin
method throws the NotSupportedException
.
getTransaction
method returns the Transaction object that represents the transaction context currently associated with the calling thread. This object can be used to perform various operations on the target transaction. These operations are described elsewhere.
commit
method completes the transaction currently associated with the calling thread. After it returns, the calling thread is not associated with any transaction. If commit
is called when the thread is not associated with any transaction context, an exception is thrown. In some implementations, only the transaction originator can use the commit
operation. If the calling thread is not permitted to commit the transaction, an exception is thrown. JBossJTA does not impose any restrictions on the ability of threads to terminate transactions.
rollback
method is used to roll back the transaction associated with the current thread. After the rollback
method completes, the thread is not associated with any transaction.
Note
IllegalStateException
exception.
2.3. Suspending and Resuming a Transaction
suspend
method is called to temporarily suspend the current transaction associated with the calling thread. If the thread is not associated with any transaction, a null
object reference is returned; otherwise, a valid Transaction
object is returned. The Transaction
object can later be passed to the resume
method to reinstate the transaction context.
resume
method associates the specified transaction context with the calling thread. If the transaction specified is valid, the transaction context is associated with the calling thread. Otherwise, the thread is not associated with any transaction.
Note
resume
method is invoked when the calling thread is already associated with another transaction, the Transaction Manager throws the IllegalStateException
exception.
Transaction tobj = TransactionManager.suspend(); .. TransactionManager.resume(tobj);
Note
2.4. The Transaction Interface
Transaction
interface allows operations to be performed on the transaction associated with the target object. Every top-level transaction is associated with one Transaction
object when the transaction is created. The Transaction
object can be used to:
- Enlist the transactional resources in use by the application.
- Register for transaction synchronization call backs.
- Commit or rollback the transaction.
- Obtain the status of the transaction.
commit
and rollback
methods allow the target object to be committed or rolled back. The calling thread is not required to have the same transaction associated with the thread. If the calling thread is not allowed to commit the transaction, the transaction manager throws an exception. JBossJTA does not impose restrictions on threads terminating transactions.
2.5. Resource Enlistment
enlistResource
method with an XAResource
object which identifies the resource in use. See
for details on how the implementation of the XAResource
can affect recovery in the event of a failure.
XAResource.start
method call to the resource manager.
delistResource
method is used to dissociate the specified resource from the transaction context in the target object. The application server invokes the method with two parameters:
- An
XAResources
object, which represents the resource. - A flag to indicate whether the operation is due to the transaction being suspended (
TMSUSPEND
), a portion of the work has failed (TMFAIL
), or a normal resource release by the application (TMSUCCESS
).
XAResource
. The flag value allows the application server to indicate whether it intends to come back to the same resource, in which case the resource states must be kept intact. The transaction manager passes the appropriate flag value in its XAResource.end
method call to the underlying resource manager.
2.6. Transaction Synchronization
Synchronization
callback object to be invoked by the transaction manager either before or after completion:
- The
beforeCompletion
method is called prior to the start of the two-phase transaction complete process. This call is executed in the same transaction context of the caller who initiates theTransactionManager.commit
, or with no transaction context ifTransaction.commit
is used. - The
afterCompletion
method is called after the transaction has completed. The status of the transaction is supplied in the parameter. This method is executed without a transaction context.
2.7. Transaction Equality
Transaction
object’s equals
method to allow comparison between the target object and another Transaction object. The equals
method returns true
if the target object and the parameter object both refer to the same global transaction.
Transaction txObj = TransactionManager.getTransaction(); Transaction someOtherTxObj = .. .. boolean isSame = txObj.equals(someOtherTxObj);
Chapter 3. The Resource Manager
3.1. The XAResource Interface
javax.transaction.xa.XAResource
interface is a Java mapping of the XA
interface, and defines the contract between a Resource Manager and a Transaction Manager in a distributed transaction processing environment. A resource adapter implements the XAResource
interface to support association of a top-level transaction to a resource. A relational database is an example of such a resource.
XAResource
interface can be supported by any transactional resource adapter that is intended to be used in an environment where transactions are controlled by an external transaction manager. An application can access data through multiple database connections. Each database connection is associated with an XAResource
object that serves as a proxy object to the underlying resource manager instance. The transaction manager obtains an XAResource
for each resource manager participating in a top-level transaction. The start
and end
methods associates and dissociate the transaction from the resource.
start
and end
invocations. At transaction commit time, these transactional resource managers are instructed by the transaction manager to prepare, commit, or rollback the transaction according to the two-phase commit protocol.
XAResource
differs from the standard XA
interface in the following ways:
- The resource manager initialization is done implicitly by the resource adapter when the connection is acquired. There is no
xa_open
equivalent. Rmid
is not passed as an argument. EachRmid
is represented by a separateXAResource
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 improper handling of the
XAResource
object by the transaction manager are mapped to Java exceptions by theXAException
class. - The DTP concept of Thread of Control maps to all Java threads with access to the
XAResource
andConnection
objects. For example, two different threads are able to perform thestart
andend
operations on the sameXAResource
object.
3.1.1. Extended XAResource Control
XAResource
object is registered with a JTA-compliant transaction service, you have no control over the order in which it will be invoked during the two-phase commit protocol, with respect to other XAResource
objects. However, JBoss Transaction Service supports controlling the order with 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 will be invoked at the beginning or end of the commit protocol.
Note
prepare
) to be enlisted with a transaction which manipulates two-phase aware participants. JBossJTA provides LRCO support.
XAResource
implementation must extend the com.arjuna.ats.jta.resources.LastResourceCommitOptimisation
marker interface. When enlisting the resource via Transaction.enlistResource
, JBoss Transaction Service allows only a single LastResourceCommitOptimisation
participant to be used within each transaction. Your resource is driven last in the commit protocol, and the prepare
method is not invoked.
Note
LastResourceCommitOptimisation
class will fail and false
is returned from Transaction.enlistResource
. You can override this behavior by setting the com.arjuna.ats.jta.allowMultipleLastResources property to true
. Be sure to read the section on enlisting multiple one-phase aware resources fore more information.
3.1.2. Enlisting Multiple One-Phase Aware Resources
prepare
state. They commit or rollback immediately when instructed by the transaction coordinator, without knowledge of other resource states and without any way of undoing their actions if subsequent resources make a different choice. This can cause data corruption or heuristic outcomes.
- Wrap the resources in compensating transactions.
- Migrate the legacy implementations to two-phase aware equivalents.
Important
"You have chosen to enable multiple last resources in the transaction manager. This is transactionally unsafe and should not be relied upon.”
or, when multiple one-phase resources are enlisted within the transaction, “This is transactionally unsafe and should not be relied on.”
.
3.2. Opening a Resource Manager
XA
interface requires the transaction manager to initialize a resource manager using the xa_open
prior to issuing any other xa_
calls. JTA requires initialization of a resource manager to be embedded within the resource adapter representing the resource manager. The transaction manager does not need to know how to initialize a resource manager. It must only tell the resource manager when to start and end work associated with a transaction and when to complete the transaction. The resource adapter is responsible for opening (initializing) the resource manager when the connection to the resource manager is established.
3.3. Closing a Resource Manager
- An
XAResource
object that allows the transaction manager tostart
andend
the transaction association with the resource in use, and to coordinate the transaction completion process. - A connection object that allows the application to perform operations on the underlying resource (for example, JDBC operations on an RDBMS).
close
method, the resource adapter invalidates the connection object reference that was held by the application, notifying the application server about the close
. The transaction manager needs to invoke the XAResource.end
method to dissociate the transaction from that connection.
close
notification allows the application server to perform any necessary garbage collection and mark the physical XA connection as free for reuse, in the case of connection pooling.
3.4. Threads of Control
XA
interface specifies that the XA calls related to transaction associations must be invoked from the same thread context. This thread-of-control requirement is not applicable to the object-oriented component-based application run-time environment, in which application threads are dispatched dynamically at method invocation time. Different threads may use the same connection resource to access the resource manager if the connection spans multiple method invocations. 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 may operate independent of thread context. Therefore, different threads may invoke the start
and end
methods.
XAResource
object and its associated connection to the resource manager, the application server must ensure that only one transaction context is associated with the resource at any point in time. Therefore, the XAResource
interface requires the resource managers to be able to support the two-phase commit protocol from any thread context.
3.5. Transaction Association
start
method, and dissociated 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 transactions. Because JTA does not support nested transactions, the start
method cannot be invoked on a connection that is currently associated with a different transaction.
start
and end
are invoked properly for each transaction context switch. Each time the resource is used with a different transaction, the end
method must be invoked for the previous transaction that was associated with the resource, and the start
method must be invoked for the current transaction context.
3.6. Externally-Controlled Connections
XAResource
object in use with the transaction by invoking the Transaction.enlistResource
method.
3.7. Resource Sharing
commit
process, the transaction manager can 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 be associated with the transaction being completed.
XAResource
methods concurrently for transaction commit
processing. The code below declares a transactional resource r1
. Global transaction xid1
is started and ended with r1
. Then a different global transaction xid2
is associated with r1
. In the meantime, 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.
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);
3.8. Local and Global Transactions
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 starting a global transaction in the connection.
- The global transaction must be dissociated from the connection before any local transaction is started.
3.9. Transaction Timeouts
XAResource
interface supports a operation allowing 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. This is useful when long-running transactions have lifetimes that exceed the default. If the timeout is not altered, the resource manager will rollback before the transaction terminates and subsequently cause the transaction to roll back as well.
- Local JTA
- Set the com.arjuna.ats.arjuna.coordinator.defaultTimeout property to a value expressed in seconds. The default value is 60 seconds.
- JTS
- Set the com.arjuna.ats.jts.defaultTimeout property to a value expressed in seconds. The default value is 0, meaning that transactions do not time out.
setTransactionTimeout
is called on XAResource
instances.
true
(the default), it is called on all instances. Alternatively, the setXATransactionTimeoutEnabled
method of com.arjuna.ats.jta.common.Configuration
can be used.
3.10. Dynamic Registration
XAResource
for the following reasons:
- 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, it can be done at the resource adapter level via a private interface between the resource adapter and the underlying resource manager.
Chapter 4. Transaction Recovery
4.1. Failure recovery
XAResource.recover
method to retrieve the list of transactions currently in a prepared
or heuristically completed
state. Typically, the system administrator configures all transactional resource factories that are used by the applications deployed on the system. The JDBC XADataSource
object, for example, is a factory for the JDBC XAConnection
objects.
XAResource
objects are not persistent across system failures, the Transaction Manager needs the ability to acquire the XAResource
objects that represent the resource managers which might have participated in the transactions prior to a system failure. For example, a Transaction Manager might use the JNDI look-up mechanism to acquire a connection from each of the transactional resource factories, and then obtain the corresponding XAResource
object for each connection. The Transaction Manager then invokes the XAResource.recover
method to ask each resource manager to return the transactions that are currently in a prepared
or heuristically completed
state.
Note
*
forces recovery, and possibly rollback, of all transactions, regardless of their node identifier. Use it with caution.
XAResource
crash recovery automatically. Otherwise one, of the following recovery mechanisms is used:
- If the
XAResource
is able to be serialized, then the serialized form will be saved during transaction commitment, and used during recovery. The recreatedXAResource
is assumed to be valid and able to drive recovery on the associated database. - The
com.arjuna.ats.jta.recovery.XAResourceRecovery
,com.arjuna.ats.jta.recovery.XARecoveryResourceManager
andcom.arjuna.ats.jta.recovery.XARecoveryResource
interfaces are used. Refer to the JDBC chapters on failure recovery for more information.
4.2. Recovering XAConnections
com.arjuna.ats.jta.recovery.XAResourceRecovery
for each database that may be used by an application.
Note
XAResourceRecovery
instances, specify their class names through properties. Any property found in the properties
file, or registered at run-time, starting with the name com.arjuna.ats.jta.recovery.XAResourceRecovery is recognized as representing one of these instances. Its value is the class name, such as: com.arjuna.ats.jta.recovery.XAResourceRecoveryOracle=com.foo.barRecovery
com.arjuna.ats.jta.recovery.XAResourceRecoveryOracle=com.foo.barRecovery;myData=hello
Note
property
file.
public interface XAResourceRecovery { public XAResource getXAResource () throws SQLException; public boolean initialise (String p); public boolean hasMoreResources (); };
initialize
- After the instance is created, any additional information found after the first semicolon in the property value definition is passed to the object. The object can use this information in an implementation-specific manner.
hasMoreResources
- Each
XAResourceRecovery
implementation can provide multipleXAResource
instances. Before calling togetXAResource
,hasMoreResources
is called to determine whether any further connections need to be obtained. If the return value isfalse
,getXAResource
is not called called again during this recovery sweep and the instance is ignored until the next recovery scan. getXAResource
- Returns an instance of the
XAResource
object. How this is created (and how the parameters to its constructors are obtained) is up to theXAResourceRecovery
implementation. The parameters to the constructors of this class should be similar to those used when creating the initial driver or data source, and should be sufficient to create newXAResources
instances that can be used to drive recovery.
Note
XAResourceRecovery
instance to be called during each sweep of the recovery manager, ensure that once hasMoreResources
returns false
to indicate the end of work for the current scan, it then returns true
for the next recovery scan.
4.3. Alternative to XAResourceRecovery
XAResourceRecovery
uses needs to be implemented with the ability to manage states. This leads to unnecessary complexity. In JBoss Transaction Service, you can provide an implementation of the public interface, as below:
com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper { public boolean initialise(String p) throws Exception; public XAResource[] getXAResources() throws Exception; }
getXAResources
method is called, and attempts recovery on each element of the array. For the majority of resource managers, you only need one XAResource
in the array, since the recover
method can return multiple Xids.
XAResourceRecovery
instances, which are configured via the XML properties file and instantiated by JBoss Transaction Service, instances of XAResourceRecoveryHelper
are constructed by the application code and registered with JBoss Transaction Service by calling XARecoveryModule.addXAResourceRecoveryHelper
.
initialize
method is not currently called by JBoss Transaction Service, but is provided to allow for the addition of further configuration options in later releases.
XAResourceRecoveryHelper
instances, after which they will no longer be called by the recovery manager. Deregistration may block for a while, if a recovery scan is in progress.
XAResourceRecoveryHelper
while the system is running is beneficial for environments where datasources may be deployed or undeployed, such as application servers. Be careful when classloading behavior in these cases.
Chapter 5. JDBC and Transactions
5.1. Using the transactional JDBC driver
5.1.1. Managing Transactions
5.1.2. Restrictions
5.2. Transactional drivers
com.arjuna.ats.jdbc.TransactionalDriver
interface, which implements the java.sql.Driver
interface.
5.2.1. Loading drivers
TransactionalDriver arjunaJDBC2Driver = new TransactionalDriver();
java.sql.DriverManager
) to manage driver instances by adding them to the Java system properties. The jdbc.drivers property contains a list of driver class names, separated by colons, which the JDBC driver manager loads when it is initialized.
Class.forName()
method to load the driver or drivers.
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Class.forName()
method automatically registers the driver with the JDBC driver manager. You can also explicitly create an instance of the JDBC driver.
sun.jdbc.odbc.JdbcOdbcDriver drv = new sun.jdbc.odbc.JdbcOdbcDriver(); DriverManager.registerDriver(drv);
5.3. Connections
5.3.1. Making the connection
5.3.2. JBossJTA JDBC Driver Properties
com.arjuna.ats.jdbc.TransactionalDriver
class.
- userName
- the user name to use when attempting to connect to the database.
- password
- the password to use when attempting to connect to the database.
- createDb
- set this to
true
to cause the driver to try to create the database when it connects. This may not be supported by all JDBC 2.0 implementations. - dynamicClass
- dynamicClass: this specifies a class to instantiate to connect to the database, rather than using JNDI.
5.3.3. XADataSources
XADataSources
. JBossJTA uses the appropriate DataSource when a connection to the database is made. It then obtains XAResources
and registers them with the transaction using the JTA interfaces. The transaction service uses these XAResources
when the transaction terminates, triggering the database to either commit or rollback the changes made via the JDBC connection.
XADataSources
in one of two ways. For simplicity, it is assumed that the JDBC 2.0 driver is instantiated directly by the application.
5.3.3.1. Java Naming and Directory Interface (JNDI)
TransactionalDriver
class use a JNDI registered XADataSource
you need to create the XADataSource
instance and store it in an appropriate JNDI implementation.
XADataSource ds = MyXADataSource(); Hashtable env = new Hashtable(); String initialCtx = PropertyManager.getProperty("Context.INITIAL_CONTEXT_FACTORY"); env.put(Context.INITIAL_CONTEXT_FACTORY, initialCtx); initialContext ctx = new InitialContext(env); ctx.bind("jdbc/foo", ds);
Properties dbProps = new Properties(); dbProps.setProperty(TransactionalDriver.userName, "user"); dbProps.setProperty(TransactionalDriver.password, "password"); TransactionalDriver arjunaJDBC2Driver = new TransactionalDriver(); Connection connection = arjunaJDBC2Driver.connect("jdbc:arjuna:jdbc/foo", dbProps);
jdbc:arjuna:
in order for the ArjunaJDBC2Driver
interface to recognize that the DataSource needs to participate within transactions and be driven accordingly.
5.3.3.2. Dynamic class instantiation
5.3.3.3. Using the connection
close
method, all operations performed on the connection at the application level use this transaction-specific connection exclusively.
Statement stmt = conn.createStatement(); try { stmt.executeUpdate("CREATE TABLE test_table (a INTEGER,b INTEGER)"); } catch (SQLException e) { // table already exists } stmt.executeUpdate("INSERT INTO test_table (a, b) VALUES (1,2)"); ResultSet res1 = stmt.executeQuery("SELECT * FROM test_table");
5.3.3.4. Connection Pooling
close
method requests.
5.3.3.5. Reusing Connections
true
on the JDBC URL.
jdbc:arjuna:sequelink://host:port;databaseName=foo;reuseconnection=true
5.3.3.6. Terminating the Transaction
5.3.3.7. AutoCommit
true
for JDBC 1.0, the execution of every SQL statement is a separate top-level transaction, and it is not possible to group multiple statements to be managed within a single OTS transaction. Therefore, JBossJTA disables AutoCommit on JDBC 1.0 connections before using them. If AutoCommit is subsequently set to true
by the application, JBossJTA raises the java.sql.SQLException
exception.
5.3.3.8. Setting Isolation Levels
Note
Chapter 6. Examples
6.1. JDBC example
Example 6.1. JDBCTest Example
public class JDBCTest { public static void main (String[] args) { /* */ Connection conn = null; Connection conn2 = null; Statement stmt = null; // non-tx statement Statement stmtx = null; // will be a tx-statement Properties dbProperties = new Properties(); try { System.out.println("\nCreating connection to database: "+url); /* * Create conn and conn2 so that they are bound to the JBossTS * transactional JDBC driver. The details of how to do this will * depend on your environment, the database you wish to use and * whether or not you want to use the Direct or JNDI approach. See * the appropriate chapter in the JTA Programmers Guide. */ stmt = conn.createStatement(); // non-tx statement try { stmt.executeUpdate("DROP TABLE test_table"); stmt.executeUpdate("DROP TABLE test_table2"); } catch (Exception e) { // assume not in database. } try { stmt.executeUpdate("CREATE TABLE test_table (a INTEGER,b INTEGER)"); stmt.executeUpdate("CREATE TABLE test_table2 (a INTEGER,b INTEGER)"); } catch (Exception e) { } try { System.out.println("Starting top-level transaction."); com.arjuna.ats.jta.UserTransaction.userTransaction().begin(); stmtx = conn.createStatement(); // will be a tx-statement System.out.println("\nAdding entries to table 1."); stmtx.executeUpdate("INSERT INTO test_table (a, b) VALUES (1,2)"); ResultSet res1 = null; System.out.println("\nInspecting table 1."); res1 = stmtx.executeQuery("SELECT * FROM test_table"); while (res1.next()) { System.out.println("Column 1: "+res1.getInt(1)); System.out.println("Column 2: "+res1.getInt(2)); } System.out.println("\nAdding entries to table 2."); stmtx.executeUpdate("INSERT INTO test_table2 (a, b) VALUES (3,4)"); res1 = stmtx.executeQuery("SELECT * FROM test_table2"); System.out.println("\nInspecting table 2."); while (res1.next()) { System.out.println("Column 1: "+res1.getInt(1)); System.out.println("Column 2: "+res1.getInt(2)); } System.out.print("\nNow attempting to rollback changes."); com.arjuna.ats.jta.UserTransaction.userTransaction().rollback(); com.arjuna.ats.jta.UserTransaction.userTransaction().begin(); stmtx = conn.createStatement(); ResultSet res2 = null; System.out.println("\nNow checking state of table 1."); res2 = stmtx.executeQuery("SELECT * FROM test_table"); while (res2.next()) { System.out.println("Column 1: "+res2.getInt(1)); System.out.println("Column 2: "+res2.getInt(2)); } System.out.println("\nNow checking state of table 2."); stmtx = conn.createStatement(); res2 = stmtx.executeQuery("SELECT * FROM test_table2"); while (res2.next()) { System.out.println("Column 1: "+res2.getInt(1)); System.out.println("Column 2: "+res2.getInt(2)); } com.arjuna.ats.jta.UserTransaction.userTransaction().commit(true); } catch (Exception ex) { ex.printStackTrace(); System.exit(0); } } catch (Exception sysEx) { sysEx.printStackTrace(); System.exit(0); } }
6.2. BasicXARecovery Example for Failure Recovery
XAResourceRecovery
interface for XAResources
. The parameter supplied in setParameters can contain arbitrary information necessary to initialize the class once created. Here, it contains the name of the property file containing database connection information, as well as the number of connections that this file knows about. Values are separated by semi-colons.
XAResourceRecovery
is capable of. In real life, it is not recommended to store database connection information such as user names and passwords in a raw text file, as this example does.
- DB_x_DatabaseURL=
- DB_x_DatabaseUser=
- DB_x_DatabasePassword=
- DB_x_DatabaseDynamicClass=
Note
Example 6.2. XAResourceRecovery Example
/* * Some XAResourceRecovery implementations will do their startup work here, * and then do little or nothing in setDetails. Since this one needs to know * dynamic class name, the constructor does nothing. */ public BasicXARecovery () throws SQLException { numberOfConnections = 1; connectionIndex = 0; props = null; } /* * The recovery module will have chopped off this class name already. The * parameter should specify a property file from which the url, user name, * password, etc. can be read. * * @message com.arjuna.ats.internal.jdbc.recovery.initexp An exception * occurred during initialisation. */ public boolean initialise (String parameter) throws SQLException { if (parameter == null) return true; int breakPosition = parameter.indexOf(BREAKCHARACTER); String fileName = parameter; if (breakPosition != -1) { fileName = parameter.substring(0, breakPosition - 1); try { numberOfConnections = Integer.parseInt(parameter.substring(breakPosition + 1)); } catch (NumberFormatException e) { return false; } } try { String uri = com.arjuna.common.util.FileLocator.locateFile(fileName); jdbcPropertyManager.propertyManager.load(XMLFilePlugin.class.getName(), uri); props = jdbcPropertyManager.propertyManager.getProperties(); } catch (Exception e) { return false; } return true; } /* * @message com.arjuna.ats.internal.jdbc.recovery.xarec {0} could not find * information for connection! */ public synchronized XAResource getXAResource () throws SQLException { JDBC2RecoveryConnection conn = null; if (hasMoreResources()) { connectionIndex++; conn = getStandardConnection(); if (conn == null) conn = getJNDIConnection(); } return conn.recoveryConnection().getConnection().getXAResource(); } public synchronized boolean hasMoreResources () { if (connectionIndex == numberOfConnections) return false; else return true; } private final JDBC2RecoveryConnection getStandardConnection () throws SQLException { String number = new String("" + connectionIndex); String url = new String(dbTag + number + urlTag); String password = new String(dbTag + number + passwordTag); String user = new String(dbTag + number + userTag); String dynamicClass = new String(dbTag + number + dynamicClassTag); Properties dbProperties = new Properties(); String theUser = props.getProperty(user); String thePassword = props.getProperty(password); if (theUser != null) { dbProperties.put(TransactionalDriver.userName, theUser); dbProperties.put(TransactionalDriver.password, thePassword); String dc = props.getProperty(dynamicClass); if (dc != null) dbProperties.put(TransactionalDriver.dynamicClass, dc); return new JDBC2RecoveryConnection(url, dbProperties); } else return null; } private final JDBC2RecoveryConnection getJNDIConnection () throws SQLException { String number = new String("" + connectionIndex); String url = new String(dbTag + jndiTag + number + urlTag); String password = new String(dbTag + jndiTag + number + passwordTag); String user = new String(dbTag + jndiTag + number + userTag); Properties dbProperties = new Properties(); String theUser = props.getProperty(user); String thePassword = props.getProperty(password); if (theUser != null) { dbProperties.put(TransactionalDriver.userName, theUser); dbProperties.put(TransactionalDriver.password, thePassword); return new JDBC2RecoveryConnection(url, dbProperties); } else return null; } private int numberOfConnections; private int connectionIndex; private Properties props; private static final String dbTag = "DB_"; private static final String urlTag = "_DatabaseURL"; private static final String passwordTag = "_DatabasePassword"; private static final String userTag = "_DatabaseUser"; private static final String dynamicClassTag = "_DatabaseDynamicClass"; private static final String jndiTag = "JNDI_"; /* * Example: * * DB2_DatabaseURL=jdbc\:arjuna\:sequelink\://qa02\:20001 * DB2_DatabaseUser=tester2 DB2_DatabasePassword=tester * DB2_DatabaseDynamicClass=com.arjuna.ats.internal.jdbc.drivers.sequelink_5_1 * * DB_JNDI_DatabaseURL=jdbc\:arjuna\:jndi DB_JNDI_DatabaseUser=tester1 * DB_JNDI_DatabasePassword=tester DB_JNDI_DatabaseName=empay * DB_JNDI_Host=qa02 DB_JNDI_Port=20000 */ private static final char BREAKCHARACTER = ';'; // delimiter for parameters
com.arjuna.ats.internal.jdbc.recovery.JDBC2RecoveryConnection
class can create a new connection to the database using the same parameters used to create the initial connection.
Chapter 7. Configuring JBossJTA
7.1. Configuring options
JTA Configuration Options and Default Values
- com.arjuna.ats.jta.supportSubtransactions
- Default Values: Yes/No
- com.arjuna.ats.jta.jtaTMImplementation
- com.arjuna.ats.jta.jtaUTImplementation
- Default Values: com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple/com.arjuna.ats.internal.jta.transaction.jts.TransactionManagerImple
- com.arjuna.ats.jta.xaBackoffPeriod
- com.arjuna.ats.jdbc.isolationLevel
- Default Values: Any supported JDBC isolation level.
- com.arjuna.ats.jta.xaTransactionTimetouEnabled
- Default Values: true / false
Chapter 8. Using JBossJTA with JBoss Enterprise Application Platform
8.1. Service Configuration
etc
directory. Several extra attributes can be configured when it is run as a JBOSS service, however.
- TransactionTimeout
- The default transaction timeout to be used for new transactions. An integer value, expressed in seconds.
- StatisticsEnabled
- Determines whether or not the transaction service should gather statistical information. Viable using the
PerformanceStatistics
MBean. A Boolean value, whose default isNO
. - PropagateFullContext
- Determines whether a full transactional context is propagated by context importer/exporter. If set to
false
, only the current transaction context is propagated. If set totrue
, the full transaction context is propagated, including any parent transactions.
jboss-service.xml
file located in the server/all/conf
directory, See Example 8.1, “Example jboss-services.xml
” for an example.
Example 8.1. Example jboss-services.xml
<mbean code="com.arjuna.ats.jbossatx.jts.TransactionManagerService" name="jboss:service=TransactionManager"> <attribute name="TransactionTimeout">300</attribute> <attribute name="StatisticsEnabled>true</attribute>> </mbean>
etc
directory. You can edit these files manually or through JMX. Each property file is exposed using an object whose name is derived from a combination of com.arjuna.ts.properties
and the name of the module containing the attribute to be configured An example example is com.arjuna.ts.properties:module=arjuna
.
8.2. Logging
TransactionManagerService
service modifies the level of some log messages by overriding the value of the com.arjuna.common.util.logger property given in the jbossjta-properties.xml
file. Therefore, the value of this property has no effect on the logging behavior when the transaction service is embedded in JBoss Enterprise Application Platform. By forcing use of the log4j_releveler
logger, the TransactionManagerService
service causes all INFO
level messages in the transaction code to be modified to be shown as DEBUG
messages. As a side effect, these messages do not appear in log files if the filter level is INFO
. All other log messages behave as normal.
8.3. The Services
TransactionManagerService
. This service ensures the recovery manager is started, and binds the JBoss Transaction Service JTA transaction manager to the JNDI provider using the name java:/TransactionManager
. This service depends upon the existence of the CORBA ORB
Service and it must be using JacORB
as the underlying ORB
implementation.
- Distributed
- Uses the JBoss Transaction Service-enabled transaction manager implementation and supports distributed transactions and recovery. Configured with the
com.arjuna.ats.jbossatx.jts.TransactionManagerService
class. This is the default configuration. - Local
- Uses the purely local JTA implementation. Configured using the
com.arjuna.ats.jbossatx.jta.TransactionManagerService
class.
8.4. Ensuring Transactional Context is Propagated to the Server
JRMPInvokerProxy.setTPCFactory( new com.arjuna.ats.internal.jbossatx.jts.PropagationContextManager() );
Part II. JTS Development
Chapter 9. Overview
9.1. Introduction
com.arjuna.ats.txoj
and com.arjuna.ats.arjuna
packages.
9.2. JBoss Transaction Service
Note
Figure 9.1. JBoss Transaction Service Class Hierarchy
9.2.1. Saving Object States
InputObjectState
class and the OutputObjectState
class. The classes maintain an internal array into which instances of the standard types can be contiguously packed and unpacked using pack
and unpack
operations. This buffer is automatically resized as required. The instances are all stored in the buffer in a standard machine-independent form called network byte order. Any other architecture-independent format, such as XDR or ASN.1), can be implemented by replacing the classes with the ones corresponding to the pack and unpack function in the required format.
9.2.2. The Object Store
read_committed
operation and written by the write_committed
and write_uncommitted
operations.
9.2.3. Recovery and persistence
StateManager
class is at the root of the class hierarchy, and is responsible for object activation and deactivation and object recovery. See Example 9.1, “StateManager
Implementation”.
Example 9.1. StateManager
Implementation
public abstract class StateManager { public boolean activate (); public boolean deactivate (boolean commit); public Uid get_uid (); // object’s identifier. // methods to be provided by a derived class public boolean restore_state (InputObjectState os); public boolean save_state (OutputObjectState os); protected StateManager (); protected StateManager (Uid id); };
- Recoverable
StateManager
attempts to generate and maintain appropriate recovery information for the object. The lifetimes of such objects do not exceed the application that created them.- Recoverable and Persistent
- The lifetime of the object is greater than that of the creating or accessing application. In addition to maintaining recovery information,
StateManager
attempts to automaticallyload
orunload
any existing persistent state for the object by calling theactivate
ordeactivate
operation at the appropriate times. - Neither Recoverable Nor Persistent
- No recovery information is ever kept nor is object activation or deactivation ever automatically attempted.
StateManager
invokes the save_state
method, as part of performing the deactivate
method, and the restore_state
, as part of performing the activate
, at various points during the execution of the application. The programmer must implement these methods, since StateManager
cannot detect user-level state changes. The programmer decides which parts of an object’s state should be made persistent. For example, in the case of a spreadsheet, you may not need to save all entries if some values can be recomputed instead. The Example 9.2, “save_state
Example” example shows the save_state
implementation for a class Example
that has integer member variables called A, B and C.
Example 9.2. save_state
Example
public boolean save_state(OutputObjectState o) { if (!super.save_state(o)) return false; try { o.packInt(A); o.packInt(B); o.packInt(C)); } catch (Exception e) { return false; } return true; }
Note
save_state
and restore_state
methods need to call super.save_state
and super.restore_state
, to take advantage of improvements in the crash recovery mechanisms.
9.2.4. The Life cycle of a Transactional Object for Java
Figure 9.2. Fundamental Life cycle of a Persistent Object in TXOJ
- The object is initially passive, and is stored in the object store as an instance of the class
OutputObjectState
. - When required by an application, the object is automatically activated by reading it from the store using a
read_committed
operation and is then converted from anInputObjectState
instance into a fully-fledged object by therestore_state
operation of the object. - When the application finishes with the object, it is deactivated by converting it back into an
OutputObjectState
instance using thesave_state
operation, and is then stored back into the object store as a shadow copy using thewrite_uncommitted
method. This shadow copy can be committed, overwriting the previous version, using thecommit_state
operation. The existence of shadow copies is normally hidden from the programmer by the transaction system. Object de-activation normally only occurs when the top-level transaction within which the object was activated commits.
Note
9.2.5. The Concurrency Controller
LockManager
class, which provides sensible default behavior which the programmer can override if necessary, by the particular semantics of the class being programmed. As with the StateManager
class and persistence, concurrency control implementations are accessed through interfaces. The current implementations of concurrency control available to interfaces include:
- Access to remote services
- Both local disk and database implementations, where locks are written to the local file system or database to make them persistent.
- A purely local implementation, where locks are maintained within the memory of the virtual machine which created them. This implementation performs better than writing locks to the local disk, but objects cannot be shared between virtual machines. Importantly, it is a basic Java object with no requirements which can be affected by the SecurityManager
setlock
operation. By default, the runtime system enforces strict two-phase locking following a multiple reader, single writer policy on a per object basis. However, as shown in Figure 9.1, “JBoss Transaction Service Class Hierarchy”, by inheriting from the Lock
class, programmers can provide their own lock implementations with different lock conflict rules to enable type specific concurrency control.
StateManager
cannot determine if an operation modifies an object, LockManager
cannot determine if an operation needs a read or write lock. Lock release, however, is under control of the system and requires no further intervention by the programmer. This ensures that the two-phase property can be correctly maintained.
public abstract class LockManager extends StateManager { public LockResult setlock (Lock toSet, int retry, int timeout); };
LockManager
class manages requests to set or release a lock on an object as appropriate. Since it is derived from the StateManager
class, it can also control when some of the inherited facilities are invoked. For example, LockManager
assumes that the setting of a write lock implies that the invoking operation must be about to modify the object, and may trigger the saving of recovery information if the object is recoverable. In a similar fashion, successful lock acquisition causes activate to be invoked.
Example 9.3. Trying to Obtain A Write Lock
public class Example extends LockManager { public boolean foobar () { AtomicAction A = new AtomicAction; boolean result = false; A.begin(); if (setlock(new Lock(LockMode.WRITE), 0) == Lock.GRANTED) { /* * Do some work, and TXOJ will * guarantee ACID properties. */ // automatically aborts if fails if (A.commit() == AtomicAction.COMMITTED) { result = true; } } else A.rollback(); return result; } }
9.2.6. The Transaction Protocol Engine
AtomicAction
class, which uses StateManager
to record sufficient information for crash recovery mechanisms to complete the transaction in the event of failures. It has methods for starting and terminating the transaction. For those situations where programmers need to implement their own resources, methods for registering them with the current transaction are also provided. Because JBoss Transaction Service supports subtransactions, if a transaction is begun within the scope of an already executing transaction, it is automatically nested.
Note
9.2.7. Example
Example 9.4. Relationships Between Activation, Termination, and Commitment
{ . . . O1 objct1 = new objct1(Name-A);/* (i) bind to "old" persistent object A */ O2 objct2 = new objct2(); /* create a "new" persistent object */ OTS.current().begin(); /* (ii) start of atomic action */ objct1.op(...); /* (iii) object activation and invocations */ objct2.op(...); . . . OTS.current().commit(true); /* (iv) tx commits & objects deactivated */ } /* (v) */
- Creation of bindings to persistent objects. This might involve the creation of stub objects and a call to remote objects. The above example re-binds to an existing persistent object identified by
Name-A
, and a new persistent object. A naming system for remote objects maintains the mapping between object names and locations and is described in a later chapter. - Start of the atomic transaction.
- Operation invocations. As a part of a given invocation, the object implementation ensures that it is locked in read or write mode, assuming no lock conflict, and initialized, if necessary, with the latest committed state from the object store. The first time a lock is acquired on an object within a transaction, the object’s state is also acquired from the object store.
- Commit of the top-level action. This includes updating the state of any modified objects in the object store.
- Breaking of the previously created bindings.
9.2.8. The Class Hierarchy
Example 9.5. JBoss Transaction Service Class Hierarchy
StateManager // Basic naming, persistence and recovery control LockManager // Basic two-phase locking concurrency control service User-Defined Classes Lock // Standard lock type for multiple readers/single writer User-Defined Lock Classes AbstractRecord // Important utility class, similar to Resource RecoveryRecord // handles object recovery LockRecord // handles object locking RecordList // Intentions list other management record types AtomicAction // Implements transaction control abstraction TopLevelTransaction Input/OutputBuffer // Architecture neutral representation of an objects’ state Input/OutputObjectState // Convenient interface to Buffer ObjectStore // Interface to the object storage services
LockManager
, Lock
and AtomicAction
classes. Other classes important to a programmer are Uid
, and ObjectState
. Most JBoss Transaction Service classes are derived from the base class StateManager
, which provides primitive facilities necessary for managing persistent and recoverable objects. These facilities include support for the activation and deactivation of objects, and state-based object recovery. The class LockManager
uses the facilities of StateManager
and Lock
to provide the concurrency control required for implementing the serializability property of atomic actions. The implementation of atomic action facilities is supported by AtomicAction
and TopLevelTransaction
.
Example
is a user-defined persistent class suitably derived from the LockManager
. An application containing an atomic transaction Trans accesses an object (called O) of type Example
by invoking the operation op1 which involves state changes to O. The serialisability property requires that a write lock must be acquired on O before it is modified; thus the body of op1 should contain a call to the setlock
operation of the concurrency controller:
public boolean op1 (...) { if (setlock (new Lock(LockMode.WRITE) == LockResult.GRANTED) { // actual state change operations follow ... } }
setlock
method, provided by the LockManager
class, performs the following functions in this case:
- Check write lock compatibility with the currently held locks, and if allowed:
- Call the
StateManager
operationactivate
, which loads, if not done already, the latest persistent state of O from the object store. Then call theStateManager
operationmodified
, which creates an instance of eitherRecoveryRecord
orPersistenceRecord
for O, depending upon whether O is persistent or not, and inserts it into theRecordList
ofTrans
. - Create and insert a LockRecord instance in the RecordList of Trans.
Trans
is aborted some time after the lock has been acquired, the rollback
operation of AtomicAction
processes the RecordList
instance associated with Trans
by invoking an appropriate Abort
operation on the various records. The implementation of this operation by the LockRecord
class releases the WRITE
lock while that of RecoveryRecord
/PersistenceRecord
restores the prior state of O.
Chapter 10. Using JBoss Transaction Service
10.1. Introduction
10.2. State management
10.2.1. Object States
Input/OutputObjectState
and Input/OutputBuffer
classes.
InputBuffer
class in Example 10.2, “InputBuffer” and the OutputBuffer
classe in Example 10.1, “OutputBuffer Example” maintain an internal array into which instances of the standard Java types can be contiguously packed (unpacked) using the pack (unpack) operations. This buffer is automatically resized as required. The instances are all stored in the buffer in a standard form called network byte order, making them machine-independent.
Example 10.1. OutputBuffer Example
public class OutputBuffer { public OutputBuffer (); public final synchronized boolean valid (); public synchronized byte[] buffer(); public synchronized int length (); /* pack operations for standard Java types */ public synchronized void packByte (byte b) throws IOException; public synchronized void packBytes (byte[] b) throws IOException; public synchronized void packBoolean (boolean b) throws IOException; public synchronized void packChar (char c) throws IOException; public synchronized void packShort (short s) throws IOException; public synchronized void packInt (int i) throws IOException; public synchronized void packLong (long l) throws IOException; public synchronized void packFloat (float f) throws IOException; public synchronized void packDouble (double d) throws IOException; public synchronized void packString (String s) throws IOException; };
Example 10.2. InputBuffer
public class InputBuffer { public InputBuffer (); public final synchronized boolean valid (); public synchronized byte[] buffer(); public synchronized int length (); /* unpack operations for standard Java types */ public synchronized byte unpackByte () throws IOException; public synchronized byte[] unpackBytes () throws IOException; public synchronized boolean unpackBoolean () throws IOException; public synchronized char unpackChar () throws IOException; public synchronized short unpackShort () throws IOException; public synchronized int unpackInt () throws IOException; public synchronized long unpackLong () throws IOException; public synchronized float unpackFloat () throws IOException; public synchronized double unpackDouble () throws IOException; public synchronized String unpackString () throws IOException; };
Example 10.3. OutputObjectState
class OutputObjectState extends OutputBuffer { public OutputObjectState (Uid newUid, String typeName); public boolean notempty (); public int size (); public Uidpublic class InputBuffer { public InputBuffer (); public final synchronized boolean valid (); public synchronized byte[] buffer(); public synchronized int length (); /* unpack operations for standard Java types */ public synchronized byte unpackByte () throws IOException; public synchronized byte[] unpackBytes () throws IOException; public synchronized boolean unpackBoolean () throws IOException; public synchronized char unpackChar () throws IOException; public synchronized short unpackShort () throws IOException; public synchronized int unpackInt () throws IOException; public synchronized long unpackLong () throws IOException; public synchronized float unpackFloat () throws IOException; public synchronized double unpackDouble () throws IOException; public synchronized String unpackString () throws IOException; };
Example 10.4. InputObjectState
class InputObjectState extends InputBuffer { public InputObjectState (Uid newUid, String typeName, byte[] b); public boolean notempty (); public int size (); public Uid stateUid (); public String type (); };
InputBuffer
and OutputBuffer
classes, through inheritance. They also add two additional instance variables that signify the Uid and type of the object for which the InputObjectState
or OutputObjectState
instance is a compressed image. These are used when accessing the object store during storage and retrieval of the object state.
10.2.2. The Object Store
Note
InputObjectState
and OutputObjectState
classes, which are named by the Uid and Type of the object that they represent. States are read using the read_committed
method and written by the system using the write_uncommitted
method. Normally, new object states do not overwrite old object states, but are written to the store as shadow copies. These shadows replace the original only when the commit_state
method is invoked. All interaction with the object store is performed by JBoss Transaction Service system components as appropriate, hiding the existence of any shadow versions of objects from the programmer.
public class ObjectStore { public static final int OS_COMMITTED; public static final int OS_UNCOMMITTED; public static final int OS_COMMITTED_HIDDEN; public static final int OS_UNCOMMITTED_HIDDEN; public static final int OS_UNKNOWN; /* The abstract interface */ public abstract boolean commit_state (Uid u, String name) throws ObjectStoreException; public abstract InputObjectState read_committed (Uid u, String name) throws ObjectStoreException; public abstract boolean write_uncommitted (Uid u, String name, OutputObjectState os) throws ObjectStoreException; . . . };
com.arjuna.ats.arjuna.objectstore.objectStoreSync
variable to OFF.
10.2.3. StateManager
StateManager
manages the state of an object and provides all of the basic state-management support mechanisms. StateManager
creates and registers appropriate resources for persistence and recovery of the transactional object. If a transaction is nested, then StateManager
propagates these resources between child transactions and their parents during the commit
phase.
StateManager
tries to generate and maintain appropriate recovery information for the object, storing the information in instances of the Input/OutputObjectState
class. The lifetimes of these objects are assumed to be shorter than the application which created them. Recoverable and persistent objects are assumed to live longer than the applications that created them, so StateManager
loads or unloads persistent states for the object by calling the activate
or deactivate
method. Objects which are neither recoverable nor persistent do not have any state data stored.
public class ObjectStatus { public static final int PASSIVE; public static final int PASSIVE_NEW; public static final int ACTIVE; public static final int ACTIVE_NEW; public static final int UNKNOWN_STATUS; }; public class ObjectType { public static final int RECOVERABLE; public static final int ANDPERSISTENT; public static final int NEITHER; }; public abstract class StateManager { public synchronized boolean activate (); public synchronized boolean activate (String storeRoot); public synchronized boolean deactivate (); public synchronized boolean deactivate (String storeRoot, boolean commit); public synchronized void destroy (); public final Uid get_uid (); public boolean restore_state (InputObjectState, int ObjectType); public boolean save_state (OutputObjectState, int ObjectType); public String type (); . . . protected StateManager (); protected StateManager (int ObjectType, ObjectName attr); protected StateManager (Uid uid); protected StateManager (Uid uid, ObjectName attr); . . . protected final void modified (); . . . }; public class ObjectModel { public static final int SINGLE; public static final int MULTIPLE; };
StateManager
invokes the save_state
method during the deactivation
method. The restore_state
is called during the activate
. The type
is called at various points during the execution of the application. The programmer must implement these methods, since StateManager
does not have access to a runtime description of the layout of an arbitrary Java object in memory. However, the capabilities provided by InputObjectState
and OutputObjectState
classes simplify the writing of these routines. For example, the save_state
implementation for a class Example
that had member variables called A, B and C might adhere to Example 10.5, “save_state
Example”
Example 10.5. save_state
Example
public boolean save_state ( OutputObjectState os, int ObjectType ) { if (!super.save_state(os, ObjectType)) return false; try { os.packInt(A); os.packString(B); os.packFloat(C); return true; } catch (IOException e) { return false; } }
save_state
and restore_state
methods of user objects must call super.save_state
and super.restore_state
.
Note
type
method determines the location in the object store where the state of instances of that class will be saved and ultimately restored. This can be any valid string. However, avoid using the hash character #, which is reserved for special directories required by JBoss Transaction Service.
get_uid
method of StateManager
provides read-only access to an object’s internal system name. The value of the internal system name can only be set when an object is created,by providing it as an explicit parameter or by generating a new identifier when the object is created.
destroy
method removes the object’s state from the object store. This is an atomic operation, which only removes the state if its invoking transaction commits. The programmer must guarante eexclusive access to the object before invoking this operation.
StateManager
class combines the management of both into a single mechanism. That is, it uses instances of the class Input/OutputObjectState both for recovery and persistence purposes. An additional argument passed to the save_state
and restore_state
operations allows the programmer to determine the purpose for which any given invocation is being made thus allowing different information to be saved for recovery and persistence purposes.
10.2.4. Object Models
- Single
- The application only contains a single copy of the object The object resides within a single JVM, and all clients must address their invocations to this server. The single model provides better performance, but creates a single point of failure. In a multi-threaded environment, the object may not be protected from corruption if a single thread fails.
- Multiple
- Logically, a single instance of the object exists. Copies of the object are distributed across multiple JVMs. Performance suffers compared to the single model, better failure isolation is achieved.
com.arjuna.ats.arjuna.gandiva.ObjectName
class when you create your object.
Note
ObjectName
class. Refer to Example 10.6, “Object Models” for an example.
- Create a new instance of
ObjectName
. - Set the object model attribute using the
com.arjuna.ats.arjuna.ArjunaNames.StateManager_objectModel()
name.
Example 10.6. Object Models
{ ObjectName attr = new ObjectName(“SNS:myObjectName”); attr.setLongAttribute(ArjunaNames.StateManager_objectModel(), ObjectModel.SINGLE); AtomicObject obj = new AtomicObject(ObjectType.ANDPERSISTENT, attr); }
10.2.5. JBoss Transaction Service Method Reference
StateManager
manages the state of objects and provides all of the basic support mechanisms required for recovery, persistence, or both. Some operations must be defined by you. These operations are: save_state
, restore_state
, and type
.
- boolean
save_state
(OutputObjectStatestate
, intObjectType
) - Invoked to save the state of an object for future use, for recovery or persistence. The
ObjectType
parameter indicates the reason for invocation. This allows you to save different pieces of information into theOutputObjectState
supplied as the first parameter, depending on whether recovery or persistence is desired. For example, pointers to other JBoss Transaction Service objects may be saved as pointers for recovery, but as UIDs for persistence. TheOutputObjectState
class provides convenient operations, so that you can save instances of all of the basic types in Java. To support crash recovery for persistent objects allsave_state
methods need to callsuper.save_state
.Note
Thesave_state
method assumes that an object is internally consistent and that all variables saved have valid values. Write and test your code to be sure this is true. - boolean
restore_state
(InputObjectStatestate
, intObjectType
) - Restores an object to the specified state. The second parameter allows different interpretations of the supplied state. To support crash recovery for persistent objects all
restore_state
methods need to callsuper.restore_state
. - String
type ()
- The JBoss Transaction Service persistence mechanism needs a way to determine the type of an object as a string, so that it can save and restore the state of the object. By convention, the position of the class in the hierarchy is used. For example,
StateManager
/LockManager
/Object
.Note
Thetype
method determines the location of the state of instanes of a specified class are saved into the object store. This can actually be any valid string. However, avoid using the hash character #, which is reserved for special directories required by JBoss Transaction Service.
10.2.6. Example
Array
class derived from the StateManager
class. To illustrate saving and restoring of an object’s state, the highestIndex
variable keeps track of the highest element of the array that has a non-zero value.
Example 10.7. Saving and Restoring an Object's State
public class Array extends StateManager { public Array (); public Array (Uid objUid); public void finalize ( super.terminate(); }; /* Class specific operations. */ public boolean set (int index, int value); public int get (int index); /* State management specific operations. */ public boolean save_state (OutputObjectState os, int ObjectType); public boolean restore_state (InputObjectState os, int ObjectType); public String type (); public static final int ARRAY_SIZE = 10; private int[] elements = new int[ARRAY_SIZE]; private int highestIndex; };
save_state
, restore_state
and type
operations can be defined as follows:
/* Ignore ObjectType parameter for simplicity */ public boolean save_state (OutputObjectState os, int ObjectType) { if (!super.save_state(os, ObjectType)) return false; try { packInt(highestIndex); /* * Traverse array state that we wish to save. Only save active elements */ for (int i = 0; i <= highestIndex; i++) os.packInt(elements[i]); return true; } catch (IOException e) { return false; } } public boolean restore_state (InputObjectState os, int ObjectType) { if (!super.restore_state(os, ObjectType)) return false; try { int i = 0; highestIndex = os.unpackInt(); while (i < ARRAY_SIZE) { if (i <= highestIndex) elements[i] = os.unpackInt(); else elements[i] = 0; i++; } return true; } catch (IOException e) { return false; } } public String type () { return '/StateManager/Array'; }
10.3. Lock Management and Concurrency Control
Note
Example 10.8. Example LockStore Class
public class LockStore { public abstract InputObjectState read_state (Uid u, String tName) throws LockStoreException; public abstract boolean remove_state (Uid u, String tname); public abstract boolean write_committed (Uid u, String tName, OutputObjectState state); };
10.3.1. Selecting a Lock Store Implementation
com.arjuna.ats.txoj.lockstore.lockStoreType
property. This variable can be either:
- BasicLockStore
- This is an in-memory implementation which does not include support for sharing of stored information between execution environments. You can extend it to include this functionality, if needed.
- BasicPersistentLockStore
- This is the default implementation. It stores locking information within the local file system. Execution environments that share the same file store can share concurrency control information. The root of the file system into which locking information is written is the
LockStore/
directory within the JBoss Transaction Service installation directory. To override this location, set thecom.arjuna.ats.txoj.lockstore.lockStoreDir
property accordingly, or include the location in theCLASSPATH
:How to Override the lockStoreDir Property
java -D com.arjuna.ats.txoj.lockstore.lockStoreDir=/var/tmp/LockStore myprogram
java –classpath $CLASSPATH;/var/tmp/LockStore myprogram
10.3.2. LockManager
LockManager
, which provides sensible default behavior that you can override if necessary. The setlock
method is the primary interface to the concurrency controller. By default, the JBoss Transaction Service runtime system enforces strict two-phase locking, following a multiple reader, single writer policy on a per-object basis. You, as the programmer, control lock acquisition, since the LockManager
class cannot predict whether an operation needs a read or write lock. Lock release, however, is normally under control of the system, requiring no action by the programmer.
LockManager
class manages requests to set a lock on an object or to release a lock. However, since it is derived from StateManager
, it can also control invocation of some of the inherited facilities. For example, if a request to set a write lock is granted, then LockManager
invokes the modified
method directly, since setting a write lock implies that the invoking method is about to modify the object. This may cause recovery information to be saved, if the object is recoverable. Successful lock acquisition also triggers invocation of the activate
.
LockManager
activates and deactivates persistent objects, and also registers Resources
used for managing concurrency control. By driving the StateManager
class, it also registers Resources
for persistent and recoverable state manipulation and object recovery. You only set the appropriate locks, start and end transactions, and extend the save_state
and restore_state
methods of the StateManager
class.
Example 10.9. LockResult Example
public class LockResult { public static final int GRANTED; public static final int REFUSED; public static final int RELEASED; }; public class ConflictType { public static final int CONFLICT; public static final int COMPATIBLE; public static final int PRESENT; }; public abstract class LockManager extends StateManager { public static final int defaultTimeout; public static final int defaultRetry; public static final int waitTotalTimeout; public synchronized int setlock (Lock l); public synchronized int setlock (Lock l, int retry); public synchronized int setlock (Lock l, int retry, int sleepTime); public synchronized boolean releaselock (Uid uid); /* abstract methods inherited from StateManager */ public boolean restore_state (InputObjectState os, int ObjectType); public boolean save_state (OutputObjectState os, int ObjectType); public String type (); protected LockManager (); protected LockManager (int ObjectType, ObjectName attr); protected LockManager (Uid storeUid); protected LockManager (Uid storeUid, int ObjectType, ObjectName attr); . . . };
setlock
method. The type is either READ
or WRITE
. If a lock conflict occurs, one of the following scenarios will take place:
- If the retry value is equal to
LockManager.waitTotalTimeout
, the thread which called thesetlock
method is blocked until the lock is released, or the total timeout specified has elapsed. In the case of a time-out, a value ofREFUSED
is returned. - If the lock cannot be obtained initially,
LockManager
retries the specified number of times, waiting for the specified timeout value between each failed attempt. The default is 100 attempts, each attempt being separated by a 0.25 seconds delay.
setlock
method returns a value of GRANTED
. Otherwise, a value of REFUSED
is returned. You need to ensure that the remainder of the code for an operation is only executed if a lock request is granted. Refer to Example 10.10, “setlock
Example” for a working example.
Example 10.10. setlock
Example
res = setlock(new Lock(WRITE), 10); // Attempts to set a write // lock 11 times (10 retries) // before giving up. res = setlock(new Lock(READ), 0); // Attempts to set a read lock // 1 time (no retries) before // giving up. res = setlock(new Lock(WRITE); // Attempts to set a write lock // 101 times (default of 100 // retries) before giving up.
releaselock
method to release the locks.
10.3.3. Locking policy
Lock
class is derived from StateManager
so that locks can be made persistent and can be named in a simple way. Furthermore, the LockManager
class does not know about the semantics of the actual policy for granting lock requests. Instances of the Lock
class maintain this information, and provide the conflictsWith
method, which LockManager
uses to determine whether two locks conflict. This separation allows you to derive new lock types from the basic Lock
class and provides appropriate definitions of the conflict operations, allowing enhanced levels of concurrency.
public class LockMode { public static final int READ; public static final int WRITE; }; public class LockStatus { public static final int LOCKFREE; public static final int LOCKHELD; public static final int LOCKRETAINED; }; public class Lock extends StateManager { public Lock (int lockMode); public boolean conflictsWith (Lock otherLock); public boolean modifiesObject (); public boolean restore_state (InputObjectState os, int ObjectType); public boolean save_state (OutputObjectState os, int ObjectType); public String type (); . . . };
Lock
class provides a modifiesObject
method, which LockManager
uses to determine a call or method is needed to grant a locking request. This allows locking modes other than simple read and write to be supported. The supplied Lock
class supports the traditional multiple reader/single writer policy.
10.3.4. Object construction and destruction
LockManager
provides two protected constructors for use by derived classes, each of which fulfils a distinct purpose:
LockManager ()
- Allows the creation of new objects, which have no prior state.
LockManager
(intObjectType
, ObjectNameattr
)- Allows the creation of new objects, which have no prior state. The
ObjectType
parameter denotes whether an object isrecoverable
, recoverable and persistent (indicated byANDPERSISTENT
) or neither (NEITHER
). If an object is marked as being persistent, its state is stored in one of the object stores. Theshared
parameter only has meaning if the object isRECOVERABLE
.; Ifattr
is not null and the object model isSINGLE
(the default behavior), then the recoverable state of the object is maintained within the object itself. Otherwise, the state of the object is stored in an in-memory object store between atomic actions.Constructors for new persistent objects should make use of atomic actions within themselves. This will ensure that the state of the object is automatically written to the object store either when the action in the constructor commits, or, if an enclosing action exists, when the appropriate top-level action commits. LockManager
(UidobjUid
)- Allows access to the existing persistent object named in the
objUid
parameter. The object's prior state, which is identified by the value of theobjUid
parameter), is loaded from an object store automatically. LockManager
(UidobjUid
, ObjectNameattr
)- Allows access to the existing persistent object named in the
objUid
parameter. The object's prior state, which is identified by the value of theobjUid
, is loaded from an object store automatically. If theattr
parameter is not null, and the object model isSINGLE
(the default behaviour), then the object is not reactivated at the start of each top-level transaction.
terminate
, to inform the state management mechanism that the object is about to be destroyed. Otherwise, unpredictable results may occur.
LockManager
class inherits from StateManager
, it passes any supplied ObjectName
instances to the StateManager
class. As such, you can set the StateManager
object model as described earlier.
Chapter 11. General Transaction Issues
11.1. Advanced Transaction Issues with JBoss Transaction Service
11.1.1. Checking Transactions
com.arjuna.ats.arjuna.coordinator.CheckedAction
class, which allows you to override the thread/transaction termination policy. Each transaction has an instance of this class associated with it, and you can provide your own implementations on a per-transaction basis.
public class CheckedAction { public CheckedAction (); public synchronized void check (boolean isCommit, Uid actUid, BasicList list); };
check
method on the transaction’s CheckedAction
object. The parameters to the check method are:
isCommit
- Indicates whether the transaction is in the process of committing or rolling back.
- actUid
- The transaction identifier.
- list
- A list of all of the threads currently active within this transaction.
check
method returns, the transaction is terminated. The state of the transaction may have changed from when the check
method was called.
11.1.2. Gathering Statistics
com.arjuna.ats.arjuna.coordinator.enableStatistics
property variable to YES
. This information includes the number of transactions created, and the outcomes of the transactions. You can request this information during the execution of a transactional application via the com.arjuna.TxCore.Atomic.TxStats
class, as in Example 11.1, “Transaction Statistics”.
Example 11.1. Transaction Statistics
public class TxStats { // Returns the number of transactions (top-level and nested) // created so far. public static int numberOfTransactions (); // Returns the number of nested (sub) transactions created so far. public static int numberOfNestedTransactions (); // Returns the number of transactions which have terminated with // heuristic outcomes. public static int numberOfHeuristics (); // Returns the number of committed transactions. public static int numberOfCommittedTransactions (); // Returns the number of transactions which have rolled back. public static int numberOfAbortedTransactions (); }
11.1.3. Last resource commit optimization
com.arjuna.ats.arjuna.coordinator.OnePhase
interface and be registered with the transaction through the BasicAction.add
method. Since this operation expects instances of AbstractRecord
, you need to create an instance of the com.arjuna.ats.arjuna.LastResourceRecord
class and pass your participant as the constructor parameter, as shown in the Example 11.2, “BasicAction.add Example”.
Example 11.2. BasicAction.add Example
try { boolean success = false; AtomicAction A = new AtomicAction(); OnePhase opRes = new OnePhase(); // used OnePhase interface System.err.println("Starting top-level action."); A.begin(); A.add(new LastResourceRecord(opRes)); A.add(new ShutdownRecord(ShutdownRecord.FAIL_IN_PREPARE)); A.commit(); }
11.1.4. Nested Transactions
11.1.5. Asynchronously Committing a Transaction
commit
protocol of a top-level transaction in a synchronous, single-threaded manner. All registered resources are directed to prepare in order by a single thread, and then to commit or rollback. This has several possible disadvantages.
- Often, the
prepare
operating is logically be invoked in parallel on each resource. The disadvantage is that if an early resource in the list of registered resource forces a rollback duringprepare
, many unnecessaryprepare
operations may have been performed. - If your application does not need heuristic reporting, the second phase of the
commit
protocol can be called asynchronously, since its success or failure is not important.
com.arjuna.ats.arjuna.coordinator.asyncPrepare
- If set to
YES
, a separate thread is created during theprepare
phase, for each registered participant within the transaction. com.arjuna.ats.arjuna.coordinator.asyncCommit
- If set to
YES
, a separate thread is created to complete the second phase of the transaction if you do not need information about heuristics outcomes.
11.1.6. Independent Top-Level Transactions
Figure 11.1. Independent Top-Level Actions
Begin
operation is invoked while B is active. However, because it is an independent top-level action, it commit
s or abort
s independently of the other actions within the structure. Because of the nature of independent top-level actions, use them with caution and only after careful testing and observation.
TopLevelTransaction
class, and using them in exactly the same way as other transactions.
11.1.7. Transactions Within the save_state
and restore_state
Methods
save_state
and restore_state
methods. Make sure not to start any atomic actions, either explicitly in the method, or implicitly through use of some other operation. The reason for this caution is that JBoss Transaction Service may invoke the restore_state
method when it commits, resulting in an attempt to execute a transaction during the commit
or abort
phase of another action. This might violate the atomicity properties of the action being committed or aborted, so it is strongly discouraged.
11.1.8. Example
set
and get
methods. The code is simplified, and ignores error conditions and exceptions.
Example 11.3. Nested Transaction Example
public boolean set (int index, int value) { boolean result = false; AtomicAction A = new AtomicAction(); A.begin(); // We need to set a WRITE lock as we want to modify the state. if (setlock(new Lock(LockMode.WRITE), 0) == LockResult.GRANTED) { elements[index] = value; if ((value > 0) && (index > highestIndex)) highestIndex = index; A.commit(true); result = true; } else A.rollback(); return result; } public int get (int index) // assume -1 means error { AtomicAction A = new AtomicAction(); A.begin(); // We only need a READ lock as the state is unchanged. if (setlock(new Lock(LockMode.READ), 0) == LockResult.GRANTED) { A.commit(true); return elements[index]; } else A.rollback(); return -1; }
11.1.9. Garbage Collecting Objects
11.1.10. Transaction Timeouts
AtomicAction
constructor. If the default value of AtomicAction.NO_TIMEOUT
is provided, the transaction is never automatically timed out. Any other positive value represents the number of seconds to wait for the transaction to terminate. A value of 0
is interpreted as a global default timeout, which you can provide using the property com.arjuna.ats.arjuna.coordinator.defaultTimeout
. This property's default value is 60
, or one minute.
JBossTS
uses a separate reaper thread to monitor all locally created transactions, forcing them to roll back if their timeouts elapse. To prevent the reaper thread from consuming application time, it only runs periodically. The default checking period is 120000 milliseconds, but you can override it by setting the com.arjuna.ats.arjuna.coordinator.txReaperTimeout property to another value, in microseconds. Alternatively, if the com.arjuna.ats.arjuna.coordinator.txReaperMode property is set to DYNAMIC
, the transaction reaper wakes up whenever a transaction times out. This has the advantage of terminating transactions early, but may continually reschedule the reaper thread.
0
for a top-level transaction, or no timeout is specified, JBoss Transaction Service does not impose any timeout on the transaction, and it is allowed to run indefinitely. You can override this default timeout by setting the com.arjuna.ats.arjuna.coordinator.defaultTimeout property.
Chapter 12. Hints and tips
12.1. General Tips
12.1.1. Using Transactions in Constructors
Example 12.1. Transactions causing System Inconsistencies
AtomicAction A = new AtomicAction(); Object obj1; Object obj2; obj1 = new Object(); // create new object obj2 = new Object("old"); // existing object A.begin(0); obj2.remember(obj1.get_uid()); // obj2 now contains reference to obj1 A.commit(true); // obj2 saved but obj1 is not
obj1
is a new object. obj2
is an old existing object. When the remember
method of obj2
is invoked, the object is activated and the Uid of obj1
is known. Since this action commits, the persistent state of obj2
may now contain the Uid of obj1
. However, the state of obj1
itself has not been saved, since it has not been manipulated under the control of any action. In fact, unless it is modified under the control of some action later in the application, it will never be saved. However, if the constructor would have used an atomic action, the state of obj1
would have automatically been saved at the time it was constructed, preventing this inconsistency.
12.1.2. More on the save_state
and restore_state
Methods
save_state
method of an object at any time during the lifetime of an object, including during the execution of the body of the object’s constructor. This is especially true if it uses atomic actions. All of the variables saved by save_state
are correctly initialized.
save_state
and restore_state
methods, to ensure that no transactions are explicitly or implicitly started. The reason is that JBoss Transaction Service may invoke the restore_state
method as part of its commit
processing, causing the execution of an atomic transaction during the commit
or abort
phase of another transaction. This may violate the atomicity properties of the transaction being committed or aborted, so it is discouraged.
save_state
and restore_state
methods of user objects need to call the super.save_state
and super.restore_state
.
12.1.3. Packing Objects
InputObjectState
or OutputObjectState
instances by using the pack
and unpack
methods provided by InputObjectState
and OutputObjectState
. However, you should handle packing and unpacking objects differently, because packing objects brings in the additional problems of aliasing. Alias means that two different object references may actually refer to the same item. See the Example 12.2, “Aliasing Problem with Packing Objects”.
Example 12.2. Aliasing Problem with Packing Objects
public class Test { public Test (String s); ... private String s1; private String s2; }; public Test (String s) { s1 = s; s2 = s; }
save_state
method has the potential to copy the string twice. From the perspective of the save_state
method, this is merely inefficient. However, it would cause the restore_state
method to unpack the two strings into different areas of memory, destroying the original aliasing information. JBoss Transaction Service packs and unpacks separate object references.
12.2. Direct Use of the StateManager
Class
LockManager
class. There are two reasons for this.
- Most importantly, the serializability constraints of atomic actions require it.
- It reduces the need for programmer intervention.
StateManager
.
StateManager
must make use of its state management mechanisms explicitly, rather than relying on LockManager
. You need to make appropriate use of the activate
, deactivate
, and modified
methods, since the constructors of StateManager
are effectively identical to those of LockManager
.
12.2.1. The activate
Method
boolean activate () boolean activate (String storeRoot)
activate
method loads an object from the object store. The object’s UID needs to already be set via the constructor, and the object must exist in the store. If the object is successfully read, the restore_state
method is called to build the object in memory. The activate
method operates such that once an object has been activated, further calls are ignored. The parameter represents the root name of the object store to search for the object. If the value is null, the default store is used.
12.2.2. The deactivate
Method
boolean deactivate () boolean deactivate (String storeRoot)
deactivate
is the inverse of activate. It first calls the save_state
method to build the compacted image of the object, then saves the object in the object store. Objects are only saved if they have been modified since activation. The parameter represents the root name of the object store into which the object should be saved. If the value is null, the default store is used.
12.2.3. The modified
Method
void modified ()
modified
method must be called before modifying the object in memory. Otherwise, the object will not be saved in the object store by the deactivate
method.
Chapter 13. Tools
13.1. Introduction
13.2. Starting the Transaction Service tools
- Windows
- Double-click the Start Tools link in the JBoss Transaction Service program group in the Start menu.
- Linux and UNIX-like Operating Systems
- At the command line, type
$JBOSS_HOME/run-tools.sh
- Section 13.2.1, “ Menu”
- Section 13.2.2, “ Menu”
- Section 13.2.3, “ Menu”
- Section 13.2.4, “ Menu”
13.3. Using the Performance Tool
Items Displayed in the Performance Tool Graph
- Number of transactions.
- Number of committed transactions.
- Number of aborted transactions.
- Number of nested transactions.
- Number of heuristics raised.
13.4. Using the JMX Browser
Information Displayed in the Details Panel
- The total number of MBeans registered on this server.
- The number of constructors exposed by this MBean.
- The number of attributes exposed by this MBean.
- The number of operations exposed by this MBean.
- The number of notifications exposed by this MBean.
- A brief description of the MBean.
13.4.1. Using Attributes and Operations
13.4.2. Using the Object Store Browser
- Object Store Roots
- A drop-down list of the currently-available object store roots. Selecting an option from the list repopulates the hierarchy view with the contents of the selected root.
- Object Store Hierarchy
- A tree showing the current object store hierarchy. Selecting a node from this tree displays the objects stored in that location.
- Objects
- A list of icons representing the objects stored in the selected location.
- Object Details
- Information about the currently selected object, only displayed if the object’s type is known to the state viewer repository. Refer to Section 13.4.3.1, “Writing an OSV” to ensure that your object will be displayed properly.
13.4.3. Object State Viewers (OSV)
13.4.3.1. Writing an OSV
com.arjuna.ats.tools.objectstorebrowser.stateviewers.StateViewerInterface
interface.
plugins/
directory. The example at Example 13.1, “AbstractRecord
Class” creates an OSV plugin for the AbstractRecord
class.
Example 13.1. AbstractRecord
Class
public class SimpleRecord extends AbstractRecord { private int _value = 0; ..... public void increase() { _value++; } public int get() { return _value; } public String type() { return “/StateManager/AbstractRecord/SimpleRecord”; } public boolean restore_state(InputObjectState os, int i) { boolean returnValue = true; try { _value = os.unpackInt(); } catch (java.io.IOException e) { returnValue = false; } return returnValue; } public boolean save_state(OutputObjectState os, int i) { boolean returnValue = true; try { os.packInt(_value); } catch (java.io.IOException e) { returnValue = false; } return returnValue; } }
getValue()
method to accomplish this easily.
public class SimpleRecordOSVPlugin implements StateViewerInterface { /** * A uid node of the type this viewer is registered against has been expanded. * @param os * @param type * @param manipulator * @param node * @throws ObjectStoreException */ public void uidNodeExpanded(ObjectStore os, String type, ObjectStoreBrowserTreeManipulationInterface manipulator, UidNode node, StatePanel infoPanel) throws ObjectStoreException { // Do nothing } /** * An entry has been selected of the type this viewer is registered against. * * @param os * @param type * @param uid * @param entry * @param statePanel * @throws ObjectStoreException */ public void entrySelected(ObjectStore os, String type, Uid uid, ObjectStoreViewEntry entry, StatePanel statePanel) throws ObjectStoreException { SimpleRecord rec = new SimpleRecord(); if ( rec.restore_state( os.read_committed(uid, type), ObjectType.ANDPERSISTENT ) ) { statePanel.setData( “Value”, rec.getValue() ); } } /** * Get the type this state viewer is intended to be registered against. * @return */ public String getType() { return “/StateManager/AbstractRecord/SimpleRecord”; } }
uidNodeExpanded
method is invoked when a Unique Identification (UID) representing the given type is expanded in the object store hierarchy tree. This abstract record is not visible in the object store directly. It is only viewable via one of the lists in an atomic action. The entrySelected
method is invoked when an entry is selected from the Object view, which represents an object with the given type. In both methods, the StatePanel is used to display information regarding the state of the object. The StatePanel includes the methods listed in StatePanel Methods to assist in display this information.
StatePanel Methods
setInfo
(Stringinfo
)- Shows general information.
setData
(Stringname
, Stringvalue
)- Puts information into the table which is displayed by the object store browser tool.
enableDetailsButton
(DetailsButtonListenerlistener
)- Enable the Details button. The listener interface allows a plug-in to be informed when the button is pressed. You, as the developer, control how to display this information.
getValue()
method is used to put an entry into the state panel table. The getType()
method returns the type of this plug-in for registration.
Example 13.2. Packing the Plug-In with Ant
<jar jarfile="osbv-simplerecord.jar"> <fileset dir="build" includes="*.class”/> <manifest> <section name="arjuna-tools-objectstorebrowser"> <attribute name="plugin-classname-1" value=" SimpleRecordOSVPlugin "/> </section> </manifest> </jar>
bin/tools/plugins
directory.
Chapter 14. Constructing an Application Using Transactional Objects for Java
14.1. Application Construction
save_state
and restore_state
methods, as well as setting appropriate locks in operations and invoking the appropriate JBoss Transaction Service class constructors. The application developer's concern is defining the general structure of the application, particularly with regard to the use of atomic actions, or transactions.
14.1.1. Queue description
QUEUE_SIZE
elements has been imposed for this example.
Example 14.1. Java Interface Definition of the Que Class
public class TransactionalQueue extends LockManager { public TransactionalQueue (Uid uid); public TransactionalQueue (); public void finalize (); public void enqueue (int v) throws OverFlow, UnderFlow, QueueError, Conflict; public int dequeue () throws OverFlow, UnderFlow, QueueError, Conflict; public int queueSize (); public int inspectValue (int i) throws OverFlow, UnderFlow, QueueError, Conflict; public void setValue (int i, int v) throws OverFlow, UnderFlow, QueueError, Conflict; public boolean save_state (OutputObjectState os, int ObjectType); public boolean restore_state (InputObjectState os, int ObjectType); public String type (); public static final int QUEUE_SIZE = 40; // maximum size of the queue private int[QUEUE_SIZE] elements; private int numberOfElements; };
14.1.2. Constructors and deconstructors
Example 14.2. Using an Existing Persistent Object
public TransactionalQueue (Uid u) { super(u); numberOfElements = 0; }
Example 14.3. Creating a New Persistent Object
public TransactionalQueue () { super(ObjectType.ANDPERSISTENT); numberOfElements = 0; try { AtomicAction A = new AtomicAction(); A.begin(0); // Try to start atomic action // Try to set lock if (setlock(new Lock(LockMode.WRITE), 0) == LockResult.GRANTED) { A.commit(true); // Commit } else // Lock refused so abort the atomic action A.rollback(); } catch (Exception e) { System.err.println(“Object construction error: “+e); System.exit(1); } }
begin
method. Then, the operation must set an appropriate lock on the object. Afterward, the main body of the constructor is executed. If successful, the atomic action is committed. Otherwise, it is aborted.
terminate
method of the LockManager
method.
Example 14.4. Destructor of the Queue Class
public void finalize () { super.terminate(); }
14.1.3. The save_state
, restore_state
, and type
Methods
Example 14.5. The save_state
Method
public boolean save_state (OutputObjectState os, int ObjectType) { if (!super.save_state(os, ObjectType)) return false; try { os.packInt(numberOfElements); if (numberOfElements > 0) { for (int i = 0; i < numberOfElements; i++) os.packInt(elements[i]); } return true; } catch (IOException e) { return false; } }
Example 14.6. The restore_state
Method
public boolean restore_state (InputObjectState os, int ObjectType) { if (!super.restore_state(os, ObjectType)) return false; try { numberOfElements = os.unpackInt(); if (numberOfElements > 0) { for (int i = 0; i < numberOfElements; i++) elements[i] = os.unpackInt(); } return true; } catch (IOException e) { return false; } }
Example 14.7. The type
Method
LockManager
class, the operation type should return a transactional queue.
public String type () { return "/StateManager/LockManager/TransactionalQueue"; }
14.1.4. enqueue/dequeue operations
enqueue
operation in Example 14.8, “The enqueue
Method” is appropriate as a guideline. The dequeue
would have a similar structure, but is not included as an example.
Example 14.8. The enqueue
Method
public void enqueue (int v) throws OverFlow, UnderFlow, QueueError { AtomicAction A = new AtomicAction(); boolean res = false; try { A.begin(0); if (setlock(new Lock(LockMode.WRITE), 0) == LockResult.GRANTED) { if (numberOfElements < QUEUE_SIZE) { elements[numberOfElements] = v; numberOfElements++; res = true; } else { A.rollback(); throw new UnderFlow(); } } if (res) A.commit(true); else { A.rollback(); throw new Conflict(); } } catch (Exception e1) { throw new QueueError(); } }
14.1.5. The queueSize
Method
public int queueSize () throws QueueError, Conflict { AtomicAction A = new AtomicAction(); int size = -1; try { A.begin(0); if (setlock(new Lock(LockMode.READ), 0) == LockResult.GRANTED) size = numberOfElements; if (size != -1) A.commit(true); else { A.rollback(); throw new Conflict(); } } catch (Exception e1) { throw new QueueError(); } return size; }
14.1.6. The inspectValue
and setValue
Methods
Note
setValue
is not shown, but it can be inferred from the inspectValue
method which is shown.
public int inspectValue (int index) throws UnderFlow, OverFlow, Conflict, QueueError { AtomicAction A = new AtomicAction(); boolean res = false; int val = -1; try { A.begin(); if (setlock(new Lock(LockMode.READ), 0) == LockResult.GRANTED) { if (index < 0) { A.rollback(); throw new UnderFlow(); } else { // array is 0 - numberOfElements -1 if (index > numberOfElements -1) { A.rollback(); throw new OverFlow(); } else { val = elements[index]; res = true; } } } if (res) A.commit(true); else { A.rollback(); throw new Conflict(); } } catch (Exception e1) { throw new QueueError(); } return val; }
14.1.7. The Client
Example 14.9. Creating an Instance of the TransactionalQueue
Object
public static void main (String[] args) { TransactionalQueue myQueue = new TransactionalQueue();
queueSize
method.
Example 14.10. The queueSize
Method
AtomicAction A = new AtomicAction(); int size = 0; try { A.begin(0); s try { size = queue.queueSize(); } catch (Exception e) { } if (size >= 0) { A.commit(true); System.out.println(“Size of queue: “+size); } else A.rollback(); } catch (Exception e) { System.err.println(“Caught unexpected exception!”); }
14.1.8. Notes
enqueue
operations atomically, you can nest the enqueue
operations inside another enclosing atomic action. In addition, concurrent operations on a persistent object are serialized, preventing inconsistencies in the state of the object. Be aware that since the elements of the queue objects are not individually concurrency controlled, certain combinations of concurrent operation invocations are executed serially, when logically they could be executed concurrently. This happens when modifying the states of two different elements in the queue.
Chapter 15. Configuration Options
15.1. Options
Name
|
Values
|
Description
| ||||
---|---|---|---|---|---|---|
com.arjuna.ats.arjuna.objectstore.storeSync
|
ON/OFF
|
Enables or disables synchronization of the object store. Use with caution.
| ||||
com.arjuna.ats.arjuna.objectstore.storeType
|
|
Specifies the type of object store implementation to use.
| ||||
com.arjuna.ats.arjuna.objectstore.hashedDirectories
|
Any integer
|
Sets the number of directories to hash object states over for the
HashedStore object store implementation.
| ||||
com.arjuna.ats.txoj.lockstore.lockStoreType
|
|
Specifies the type of lock store implementation to use.
| ||||
com.arjuna.ats.txoj.lockstore.lockStoreDir
|
|
Specifies the location of the lock store.
| ||||
com.arjuna.ats.arjuna.objectstore.objectStoreDir
|
Any location the application can write to.
|
Specifies the location of the object store.
| ||||
com.arjuna.ats.arjuna.objectstore.localOSRoot
|
defaultStore
|
Specifies the name of the object store root.
| ||||
com.arjuna.ats.arjuna.coordinator.actionStore
|
|
The transaction log implementation to use.
| ||||
com.arjuna.ats.arjuna.coordinator.asyncCommit
|
YES/NO
|
Turns on or off asynchronous
commit . Off by default.
|
Name
|
Values
|
Description
|
---|---|---|
com.arjuna.ats.arjuna.coordinator.asyncPrepare
|
YES/NO
|
Turns on or off asynchronous
prepare . Off by default.
|
com.arjuna.ats.arjuna.objectstore.transactionSync
|
ON/OFF
|
Turns synchronization of the object store on or off. Use with caution.
|
com.arjuna.ats.arjuna.objectstore.jdbcUserDbAccess
|
JDBCAccess class name
|
Specifies the JDBCAccess implementation to use for user-level object stores.
|
com.arjuna.ats.arjuna.objectstore.jdbcTxDbAccess
|
JDBCAccess class name
|
Specifies the JDBCAccess implementation to use for transaction object stores.
|
com.arjuna.ats.arjuna.coordinator.commitOnePhase
|
YES/NO
|
Enables or disables the one-phase
commit optimization.
|
com.arjuna.ats.arjuna.coordinator.readonlyOptimisation
|
YES/NO
|
Enables or disables read-only optimization for the second phase
abort .
|
com.arjuna.ats.arjuna.coordinator.enableStatistics
|
YES/NO
|
Starts or stops collecting transaction statistic information.
|
com.arjuna.ats.arjuna.coordinator.startDisabled
|
YES/NO
|
Start with the transaction system enabled or disabled. Toggle via the class mentioned in the footnote.[a]
|
com.arjuna.ats.arjuna.coordinator.defaultTimeout
|
Any integer
|
Timeout, in milliseconds
|
[a]
Toggle via the com.arjuna.ats.arjuna.coordinator.TxControl class.
|
Appendix A. Object Store Implementations
A.1. The ObjectStore
Example A.1. Object Store Type
/* * This is the base class from which all object store types are derived. * Note that because object store instances are stateless, to improve * efficiency we try to only create one instance of each type per process. * Therefore, the create and destroy methods are used instead of new * and delete. If an object store is accessed via create it *must* be * deleted using destroy. Of course it is still possible to make use of * new and delete directly and to create instances on the stack. */ public class ObjectStore { public static final int OS_COMMITTED; public static final int OS_COMMITTED_HIDDEN; public static final int OS_HIDDEN; public static final int OS_INVISIBLE; public static final int OS_ORIGINAL; public static final int OS_SHADOW; public static final int OS_UNCOMMITTED; public static final int OS_UNCOMMITTED_HIDDEN; public static final int OS_UNKNOWN; public ObjectStore (ClassName type); public ObjectStore (ClassName type, String osRoot); public ObjectStore (String osRoot); public synchronized boolean allObjUids (String s, InputObjectState buff) throws ObjectStoreException; public synchronized boolean allObjUids (String s, InputObjectState buff, int m) throws ObjectStoreException; public synchronized boolean allTypes (InputObjectState buff) throws ObjectStoreException; public synchronized int currentState(Uid u, String tn) throws ObjectStoreException; public synchronized boolean commit_state (Uid u, String tn) throws ObjectStoreException; public synchronized boolean hide_state (Uid u, String tn) throws ObjectStoreException; public synchronized boolean reveal_state (Uid u, String tn) throws ObjectStoreException; public synchronized InputObjectState read_committed (Uid u, String tn) throws ObjectStoreException; public synchronized InputObjectState read_uncommitted (Uid u, String tn) throws ObjectStoreException; public synchronized boolean remove_committed (Uid u, String tn) throws ObjectStoreException; public synchronized boolean remove_uncommitted (Uid u, String tn) throws ObjectStoreException; public synchronized boolean write_committed (Uid u, String tn, OutputObjectState buff) throws ObjectStoreException; public synchronized boolean write_uncommitted (Uid u, String tn, OutputObjectState buff) throws ObjectStoreException; public static void printState (PrintStream strm, int res); };
ObjectState
, which are named using a type derived via the object's type()
operation, and a Uid. Object states in the store are usually in one of two distinct states OS_COMMITTED
or OS_UNCOMMITTED
. An object state starts in the OS_COMMITTED
state, but when modified under the control of an atomic action, a new second object state may be written that is in the OS_UNCOMMITTED
state. If the action commits, this second object state replaces the original and becomes OS_COMMITTED
. If the action aborts, this second object state is discarded. All of the implementations provided with this release use shadow copies to handle these state transitions. However, you are allowed to implement them in a different way. Object states may become hidden and inaccessible under the control of the crash recovery system.
allTypes
and allObjUids
methods provide the ability to browse the contents of a store. The allTypes
method returns an InputObjectState containing all of the type names of all objects in a store, terminated by a null name. The allObjUids
method returns an InputObjectState that contains all of the Uids of all objects of a given type terminated by the special Uid.nullUid()
type.
A.2. Persistent Object Stores
In addition to the features mentioned earlier, all of the supplied persistent object stores obey the following rules:
- Each object state is stored in its own file, which is named using the
Uid
of the object. - The type of an object, provided by the
type()
operation, determines the directory where the object is placed. - All of the stores have a common root directory which is determined by the JBoss Transaction Service configuration. This directory name is automatically prepended to any store-specific root information.
- All stores can also use a localized root directory that is automatically prepended to the type of the object to determine the ultimate directory name. The localized root name is specified when the store is created. The default localized root name is
defaultStore
.
Item
|
Example Value
|
---|---|
ObjectStore root Directory from configure
| /JBossTS/ObjectStore/
|
ObjectStore Type 1
| FragmentedStore/
|
Default root
| defaultStore/
|
StateManager
| StateManager
|
LockManager
| LockManager/
|
User Types
|
|
Localised root 2
| myStore/
|
StateManager
| StateManager/
|
ObjectStore Type2
| ActionStore/
|
Default root
| defaultStore/
|
A.2.1. The Shadowing Store
ShadowingStore
class. It is simple but slow, using pairs of files to represent objects: the shadow version and the committed version. Files are opened, locked, operated upon, unlocked, and closed during every interaction with the object store. This can take more resources than strictly necessary just to open, close, and rename files.
A.2.2. No file-level locking
LockManager
method, no additional locking is needed at the file level. Therefore, the default object store implementation for JBoss Transaction Service, ShadowNoFileLockStore
, relies upon user-level locking, enabling it to provide better performance than the ShadowingStore
implementation.
A.2.3. The Hashed Store
HashedStore
implementation uses the same structure for object states as the shadowing store, but uses an alternate directory structure that is designed to store large numbers of objects of the same type. Objects are scattered throughout a set of directories by means of a hashing function which uses the object's Uid. By default, 255 sub-directories are used, but you can override this by setting the HASHED_DIRECTORIES
environment variable.
A.2.4. The JDBC Store
JDBCStore
implementation stores persistent object states in a JDBC database. Nested transaction support is available when the JBDCStore
is used in conjunction with the Transactional Objects for Java API. All object states are stored as Binary Large Objects (BLOBs) within a single table. Object state size is limited to 64k. If you try to store an object state which exceeds this limit, an exception is thrown and the state is not stored. The transaction is forced to roll back.
JDBCAccess
interface, located in the com.arjuna.ats.arjuna.objectstore package. See the Example A.2, “JDBCAccess Implementation Example”.
Example A.2. JDBCAccess Implementation Example
public interface JDBCAccess { public Connection getConnection () throws SQLException; public void putConnection (Connection conn) throws SQLException; public void initialise (ObjectName objName); }
JDBCAccess
class provides the Connection
used by the JDBC ObjectStore to save and restore object states. Refer to JDBCAccess
Connection
Methods for details.
JDBCAccess
Connection
Methods
getConnection
- Returns the Connection to use. This method will be called whenever a connection is required and the implementation should use whatever policy is necessary for determining what connection to return. This method need not return the same Connection instance more than once.
putConnection
- Returns one of the Connections acquired from getConnection. Connections are returned if any errors occur when using them.
initialise
- Passes additional arbitrary information to the implementation.
Connections
defined in the com.arjuna.ats.arjuna.objectstore.jdbcPoolSizeInitial property, and uses no more than defined in the com.arjuna.ats.arjuna.objectstore.jdbcPoolSizeMaximum property.
JDBCAccess
interface to use should be set in the com.arjuna.ats.arjuna.objectstore.jdbcUserDbAccess property variable.
JDBCAccess
method should be provided via the com.arjuna.ats.arjuna.objectstore.jdbcTxDbAccess property. The default table name is JBossTSTxTable
.
Note
JDBCAccess
implementation for both the user object store and the transaction log.
A.2.5. The Cached Store
Configuration Options for the Cached Store
- com.arjuna.ats.internal.arjuna.objectstore.cacheStore.hash
- Sets the number of internal stores to hash the states over. The default value is
128
. - com.arjuna.ats.internal.arjuna.objectstore.cacheStore.size
- The maximum size the cache can reach before a flush is triggered. The default is value is
10240
bytes. - com.arjuna.ats.internal.arjuna.objectstore.cacheStore.removedItems
- The maximum number of removed items that the cache can contain before a flush is triggered. By default, calls to remove a state that is in the cache actually only remove the state from the cache, leaving a blank entry. This improves performance. The entries are removed when the cache is flushed. The default value is twice the size of the hash.
- com.arjuna.ats.internal.arjuna.objectstore.cacheStore.workItems
- The maximum number of items the cache is able to contain before it is flushed. The default value is
100
. - com.arjuna.ats.internal.arjuna.objectstore.cacheStore.scanPeriod
- The length of time, in milliseconds, for periodically flushing the cache. The default is
120
seconds. - com.arjuna.ats.internal.arjuna.objectstore.cacheStore.sync
- Determines whether flushes of the cache are synchronized to disk. The default is
OFF
, and the other possible value isON
.
Appendix B. Class Definitions
B.1. Introduction
B.2. Class library
Example B.1. Lock Manager
public class LockResult { public static final int GRANTED; public static final int REFUSED; public static final int RELEASED; }; public class ConflictType { public static final int CONFLICT; public static final int COMPATIBLE; public static final int PRESENT; }; public abstract class LockManager extends StateManager { public static final int defaultRetry; public static final int defaultTimeout; public static final int waitTotalTimeout; public final synchronized boolean releaselock (Uid lockUid); public final synchronized int setlock (Lock toSet); public final synchronized int setlock (Lock toSet, int retry); public final synchronized int setlock (Lock toSet, int retry, int sleepTime); public void print (PrintStream strm); public String type (); public boolean save_state (OutputObjectState os, int ObjectType); public boolean restore_state (InputObjectState os, int ObjectType); protected LockManager (); protected LockManager (int ot); protected LockManager (int ot, ObjectName attr); protected LockManager (Uid storeUid); protected LockManager (Uid storeUid, int ot); protected LockManager (Uid storeUid, int ot, ObjectName attr); protected void terminate (); };
Example B.2. StateManager
public class ObjectStatus { public static final int PASSIVE; public static final int PASSIVE_NEW; public static final int ACTIVE; public static final int ACTIVE_NEW; }; public class ObjectType { public static final int RECOVERABLE; public static final int ANDPERSISTENT; public static final int NEITHER; }; public abstract class StateManager { public boolean restore_state (InputObjectState os, int ot); public boolean save_state (OutputObjectState os, int ot); public String type (); public synchronized boolean activate (); public synchronized boolean activate (String rootName); public synchronized boolean deactivate (); public synchronized boolean deactivate (String rootName); public synchronized boolean deactivate (String rootName, boolean commit); public synchronized int status (); public final Uid get_uid (); public void destroy (); public void print (PrintStream strm); protected void terminate (); protected StateManager (); protected StateManager (int ot); protected StateManager (int ot, ObjectName objName); protected StateManager (Uid objUid); protected StateManager (Uid objUid, int ot); protected StateManager (Uid objUid, int ot, ObjectName objName); protected synchronized final void modified (); };
Example B.3. Input/OutputObjectState
class OutputObjectState extends OutputBuffer { public OutputObjectState (Uid newUid, String typeName); public boolean notempty (); public int size (); public Uid stateUid (); public String type (); }; class InputObjectState extends ObjectState { public OutputObjectState (Uid newUid, String typeName, byte[] b); public boolean notempty (); public int size (); public Uid stateUid (); public String type (); };
Example B.4. Input/OutputBuffer
public class OutputBuffer { public OutputBuffer (); public final synchronized boolean valid (); public synchronized byte[] buffer(); public synchronized int length (); /* pack operations for standard Java types */ public synchronized void packByte (byte b) throws IOException; public synchronized void packBytes (byte[] b) throws IOException; public synchronized void packBoolean (boolean b) throws IOException; public synchronized void packChar (char c) throws IOException; public synchronized void packShort (short s) throws IOException; public synchronized void packInt (int i) throws IOException; public synchronized void packLong (long l) throws IOException; public synchronized void packFloat (float f) throws IOException; public synchronized void packDouble (double d) throws IOException; public synchronized void packString (String s) throws IOException; }; public class InputBuffer { public InputBuffer (); public final synchronized boolean valid (); public synchronized byte[] buffer(); public synchronized int length (); /* unpack operations for standard Java types */ public synchronized byte unpackByte () throws IOException; public synchronized byte[] unpackBytes () throws IOException; public synchronized boolean unpackBoolean () throws IOException; public synchronized char unpackChar () throws IOException; public synchronized short unpackShort () throws IOException; public synchronized int unpackInt () throws IOException; public synchronized long unpackLong () throws IOException; public synchronized float unpackFloat () throws IOException; public synchronized double unpackDouble () throws IOException; public synchronized String unpackString () throws IOException; };
Example B.5. Uid
public class Uid implements Cloneable { public Uid (); public Uid (Uid copyFrom); public Uid (String uidString); public Uid (String uidString, boolean errorsOk); public synchronized void pack (OutputBuffer packInto) throws IOException; public synchronized void unpack (InputBuffer unpackFrom) throws IOException; public void print (PrintStream strm); public String toString (); public Object clone () throws CloneNotSupportedException; public synchronized void copy (Uid toCopy) throws UidException; public boolean equals (Uid u); public boolean notEquals (Uid u); public boolean lessThan (Uid u); public boolean greaterThan (Uid u); public synchronized final boolean valid (); public static synchronized Uid nullUid (); };
Example B.6. AtomicAction
public class AtomicAction { public AtomicAction (); public void begin () throws SystemException, SubtransactionsUnavailable, NoTransaction; public void commit (boolean report_heuristics) throws SystemException, NoTransaction, HeuristicMixed, HeuristicHazard,TransactionRolledBack; public void rollback () throws SystemException, NoTransaction; public Control control () throws SystemException, NoTransaction; public Status get_status () throws SystemException; /* Allow action commit to be supressed */ public void rollbackOnly () throws SystemException, NoTransaction; public void registerResource (Resource r) throws SystemException, Inactive; public void registerSubtransactionAwareResource (SubtransactionAwareResource sr) throws SystemException, NotSubtransaction; public void registerSynchronization (Synchronization s) throws SystemException, Inactive; };
Part III. XTS Development
Chapter 16. Introduction
Protocols Included in XTS
- WS-Coordination (WS-C) is a generic coordination framework developed by IBM, Microsoft and BEA.
- WS-Atomic Transaction (WS-AT) and WS-Business Activity (WS-BA) together comprise the WS-Transaction (WS-T) transaction protocols that utilize this framework.
Note
Properties of Web Services
- Application components that are exposed as Web Services may be owned by third parties, which provides benefits in terms of cost of maintenance, but drawbacks in terms of having exclusive control over their behavior.
- Web Services are usually remotely located, increasing risk of failure due to increased network travel for invocations.
16.1. Managing service-Based Processes
The application in question allows a user to plan a social evening. This application is responsible for reserving a table at a restaurant, and reserving tickets to a show. Both activities are paid for using a credit card. In this example, each service represents exposed Web Services provided by different service providers. XTS is used to envelop the interactions between the theater and restaurant services into a single (potentially) long-running business transaction. The business transaction must insure that seats are reserved both at the restaurant and the theater. If one event fails the user has the ability to decline both events, thus returning both services back to their original state. If both events are successful, the user’s credit card is charged and both seats are booked. As you may expect, the interaction between the services must be controlled in a reliable manner over a period of time. In addition, management must span several third-party services that are remotely deployed.
16.2. Servlets
Note
16.3. SOAP
16.4. Web Services Description Language (WDSL)
Chapter 17. Transactions Overview
Note
Figure 17.1. Components Involved in an XTS Transaction
17.1. The Coordinator
create
request to a coordination service, which creates the coordinator and returns its details to the client. This service may be located in its own container or may be colocated with the application client or with one of the transactional web services for improved performance. The coordination service is typically responsible for managing many transactions in parallel, so each coordinator is identified by a unique transaction identifier.
17.2. The Transaction Context
Contents of a Context
- Transaction Identifier
- Guarantees global uniqueness for an individual transaction.
- Transaction Coordinator Location
- The endpoint address participants contact to enroll.
Figure 17.2. Web Services and Context Flow
17.3. Participants
17.4. ACID Transactions
ACID Properties
- Atomicity
- The transaction executes completely, or not at all.
- Consistency
- The effects of the transaction preserve the internal consistency of an underlying data structure.
- Isolated
- The transaction runs as if it were running alone, with no other transactions running, and is not visible to other transactions.
- Durable
- The transaction's results are not lost in the event of a failure.
17.5. Two Phase Commit
Figure 17.3. Two-Phase Commit Overview
Note
17.6. The Synchronization Protocol
Procedure 17.1. The "Four Phase Protocol" Created By Synchronizations
Step 1
Before the transaction starts the two-phase commit, all registered Synchronizations are informed. Any failure at this point will cause the transaction to roll back.Steps 2 and 3
The coordinator then conducts the normal two-phase commit protocol.Step 4
Once the transaction has terminated, all registered Synchronizations are informed. However, this is a courtesy invocation because any failures at this stage are ignored: the transaction has terminated so there’s nothing to affect.
17.7. Optimizations to the Protocol
Variant
|
Description
|
---|---|
Presumed Abort
|
If a transaction is going to roll back, the coordinator may record this information locally and tell all enlisted participants. Failure to contact a participant has no effect on the transaction outcome. The coordinator is informing participants only as a courtesy. Once all participants have been contacted, the information about the transaction can be removed. If a subsequent request for the status of the transaction occurs, no information will be available and the requester can assume that the transaction has aborted. This optimization has the benefit that no information about participants need be made persistent until the transaction has progressed to the end of the
prepare phase and decided to commit, since any failure prior to this point is assumed to be an abort of the transaction.
|
One-Phase
|
If only a single participant is involved in the transaction, the coordinator does not need to drive it through the
prepare phase. Thus, the participant is told to commit, and the coordinator does not need to record information about the decision, since the outcome of the transaction is the responsibility of the participant.
|
Read-Only
|
When a participant is asked to prepare, it can indicate to the coordinator that no information or data that it controls has been modified during the transaction. Such a participant does not need to be informed about the outcome of the transaction since the fate of the participant has no affect on the transaction. Therefore, a read-only participant can be omitted from the second phase of the commit protocol.
|
Note
17.8. Non-Atomic Transactions and Heuristic Outcomes
prepare
phase are allowed to make autonomous decisions about whether to commit or rollback. Such a participant must record its decision, so that it can complete the original transaction if it eventually gets a request to do so. If the coordinator eventually informs the participant of the transaction outcome, and it is the same as the choice the participant made, no conflict exists. If the decisions of the participant and coordinator are different, the situation is referred to as a non-atomic outcome, and more specifically as a heuristic outcome.
Outcome
|
Description
|
---|---|
Heuristic Rollback
|
The commit operation failed because some or all of the participants unilaterally rolled back the transaction.
|
Heuristic Commit
|
An attempted rollback operation failed because all of the participants unilaterally committed. One situation where this might happen is if the coordinator is able to successfully
prepare the transaction, but then decides to roll it back because its transaction log could not be updated. While the coordinator is making its decision, the participants decides to commit.
|
Heuristic Mixed
|
Some participants commit ed, while others were rolled back.
|
Heuristic Hazard
|
The disposition of some of the updates is unknown. For those which are known, they have either all been committed or all rolled back.
|
17.9. Interposition
Figure 17.4. Interpositions
prepare
, the top-level coordinator only needs to send one prepare
message to the subordinate coordinator, and receive one prepared
or aborted
reply. The subordinate coordinator forwards a prepare
locally to each participant and combines the results to decide whether to send a single prepared
or aborted
reply.
17.10. A New Transaction Protocol
Reasons ACID is Not Suitable for Web Services
- Classic ACID transactions assume that an organization that develops and deploys applications owns the entire infrastructure for the applications. This infrastructure has traditionally taken the form of an Intranet. Ownership implies that transactions operate in a trusted and predictable manner. To assure ACIDity, potentially long-lived locks can be kept on underlying data structures during two-phase commit. Resources can be used for any period of time and released when the transaction is complete.In Web Services, these assumptions are no longer valid. One obvious reason is that the owners of data exposed through a Web service refuse to allow their data to be locked for extended periods, since allowing such locks invites denial-of-service attacks.
- All application infrastructures are generally owned by a single party. Systems using classical ACID transactions normally assume that participants in a transaction will obey the directives of the transaction manager and only infrequently make unilateral decisions which harm other participants in a transaction.Web Services participating in a transaction can effectively decide to resign from the transaction at any time, and the consumer of the service generally has little in the way of quality of service guarantees to prevent this.
17.10.1. Transaction in Loosely Coupled Systems
Requirements of Web Services
- Ability to handle multiple successful outcomes to a transaction, and to involve operations whose effects may not be isolated or durable.
- Coordination of autonomous parties whose relationships are governed by contracts, rather than the dictates of a central design authority.
- Discontinuous service, where parties are expected to suffer outages during their lifetimes, and coordinated work must be able to survive such outages.
- Interoperation using XML over multiple communication protocols. XTS uses SOAP encoding carried over HTTP.
Chapter 18. Overview of Protocols Used by XTS
Note
18.1. WS-Coordination
Figure 18.1. WS-C Architecture
Generic Requirements for WS-C
- Instantiation, or activation, of a new coordinator for the specific coordination protocol, for a particular application instance.
- Registration of participants with the coordinator, such that they will receive that coordinator’s protocol messages during (some part of) the application’s lifetime.
- Propagation of contextual information between Web Services that comprise the application.
- An entity to drive the coordination protocol through to completion.
Figure 18.2. Four Roles in WS-C
18.1.1. Activation
CreateCoordinationContext
operation. This operation takes an input specfying the details of the transaction to be created, including the type of coordination required, timeout, and other relevant information. It returns an output containing the details of the newly-created transaction context: the transaction identifier, coordination type, and registration service URL.
Example 18.1.
<!-- Activation Service portType Declaration --> <wsdl:portType name="ActivationCoordinatorPortType"> <wsdl:operation name="CreateCoordinationContext"> <wsdl:input message="wscoor:CreateCoordinationContext"/> <wsdl:output message="wscoor:CreateCoordinationContextResponse"/> </wsdl:operation> </wsdl:portType>
Note
18.1.2. Registration
Register
operation. This operation takes an input specifying the details of the participant which is to be registered, including the participant protocol type. It returns a corresponding output response.
Example 18.2. Registration ServiceWSDL Interface
<!-- Registration Service portType Declaration --> <wsdl:portType name="RegistrationCoordinatorPortType"> <wsdl:operation name="Register"> <wsdl:input message="wscoor:Register"/> <wsdl:output message="wscoor:RegisterResponse"/> </wsdl:operation> </wsdl:portType>
Note
18.1.3. Completion
18.2. WS-Transaction
18.2.1. WS-Transaction Foundations
Figure 18.3. WS-Coordination, WS-Transaction, and WS-Business Activity
- It extends the WS-C context to create a transaction context.
- It augments the activation and registration services with a number of additional services (Completion, Volatile2PC, Durable2PC, BusinessAgreementWithParticipantCompletion, and BusinessAgreementWithCoordinatorCompletion) and two protocol message sets (one for each of the transaction models supported in WS-Transaction), to build a fully-fledged transaction coordinator on top of the WS-C protocol infrastructure.
- An important aspect of WS-Transaction that differs from traditional transaction protocols is that a synchronous request/response model is not assumed. Sequences of one way messages are used to implement communications between the client/participant and the coordination services appropriate to the transaction's coordination and participant protocols. This is significant because it means that the client and participant containers must deploy XTS service endpoints to receive messages from the coordinator service.This requirement is visible in the details of the
Register
andRegisterResponse
messages declared in the Registration Service WSDL in Example 18.2, “Registration ServiceWSDL Interface”. TheRegister
message contains the URL of an endpoint in the client or web service container. This URL is used when a WS-Transaction coordination service wishes to dispatch a message to the client or web service. Similarly, theRegisterResponse
message contains a URL identifying an endpoint for the protocol-specific WS-Transaction coordination service for which the client/web service is registered, allowing messages to be addressed to the transaction coordinator.
18.2.2. WS-Transaction Architecture
Figure 18.4. WS-Transaction Global View
Figure 18.5. WS-Transaction Web Services and Participants
18.2.3. WS_Transaction Models
18.2.3.1. Atomic Transactions
Procedure 18.1. Atomic Transaction Process
- To begin an atomic transaction, the client application first locates a WS-C Activation Coordinator web service that supports WS-Transaction.
- The client sends a WS-C
CreateCoordinationContext
message to the service, specifying http://schemas.xmlsoap.org/ws/2004/10/wsat as its coordination type. - The client receives an appropriate WS-Transaction context from the activation service.
- The response to the
CreateCoordinationContext
message, the transaction context, has itsCoordinationType
element set to the WS-Atomic Transaction namespace, http://schemas.xmlsoap.org/ws/2004/10/wsat. It also contains a reference to the atomic transaction coordinator endpoint, the WS-C Registration Service, where participants can be enlisted. - The client normally proceeds to invoke Web Services and complete the transaction, either committing all the changes made by the web services, or rolling them back. In order to be able to drive this completion activity, the client must register itself as a participant for the
Completion
protocol, by sending aRegister
message to the Registration Service whose endpoint was returned in the Coordination Context. - Once registered for Completion, the client application then interacts with Web Services to accomplish its business-level work. With each invocation of a business Web service, the client inserts the transaction context into a SOAP header block, such that each invocation is implicitly scoped by the transaction. The toolkits that support WS-Atomic Transaction-aware Web Services provide facilities to correlate contexts found in SOAP header blocks with back-end operations. This ensures that modifications made by the Web service are done within the scope of the same transaction as the client and subject to commit or rollback by the transaction coordinator.
- Once all the necessary application-level work is complete, the client can terminate the transaction, with the intent of making any changes to the service state permanent. The completion participant instructs the coordinator to try to commit or roll back the transaction. When the commit or roll-back operation completes, a status is returned to the participant to indicate the outcome of the transaction.
- Volatile2pc
- The first of these protocols is the optional Volatile2PC (2PC is an abbreviation referring to the two-phase commit). The Volatile2PC protocol is the WS-Atomic Transaction equivalent of the synchronization protocol discussed earlier. It is typically executed where a Web service needs to flush volatile (cached) state, which may be used to improve performance of an application, to a database prior to the transaction committing. Once flushed, the data is controlled by a two-phase aware participant.When the completion participant initiates a
commit
operation, all Volatile2PC participants are informed that the transaction is about to complete, via theprepare
message. The participants can respond with one of three messages:prepared
,aborted
, orreadonly
. A failure at this stage causes the transaction to roll back. - Durable2PC
- The next protocol in the WS-Atomic Transaction is Durable2PC. The Durable2PC protocol is at the core of WS-Atomic Transaction. It brings about the necessary consensus between participants in a transaction, so the transaction can safely be terminated.The Durable2PC protocol ensures atomicity between participants, and is based on the classic technique of two-phase commit with presumed abort.
Procedure 18.2. Durable2PC Procedure
- During the first phase, when the coordinator sends the prepare message, a participant must make durable any state changes that occurred during the scope of the transaction, so these changes can either be rolled back or committed later. None of the original state information can be lost at this point, since the atomic transaction may still roll back. If the participant cannot
prepare
, it must inform the coordinator, by means of theaborted
message. The transaction will ultimately roll back. If the participant is responsible for a service that did not change any of the transaction's data,, it can return thereadonly
message, causing it to be omitted from the second phase of the commit protocol. Otherwise, theprepared
message is sent by the participant. - If no failures occur during the first phase, Durable2PC proceeds to the second phase, in which the coordinator sends the
commit
message to participants. Participants then make permanent the tentative work done by their associated services, and send acommitted
message to the coordinator. If any failures occur, the coordinator sends therollback
message to all participants, causing them to discard tentative work done by their associated services, and delete any state information saved to persistent storage atprepare
, if they have reached that stage. Participants respond to a rollback by sending anaborted
message to the coordinator.
Note
The semantics of the WS-Atomic Transaction protocol do not include the one-phase commit optimization. A full two-phase commit is always used, even where only a single participant is enlisted.
Figure 18.6. WS-Atomic Two-Phase Participant State Transitions
Completion
protocol that originally began the termination of the transaction can complete, and inform the client application whether the transaction was committed or rolled back. Additionally, the Volatile2PC protocol may complete.
prepare
phase of Volatile2PC, the final phase is optional and can be used to inform participants about the transaction's completion, so that they can release resources such as database connections.
Figure 18.7.
18.2.3.2. Business Activities
Procedure 18.3. BA Process Overview
- Services are requested to do work.
- Where those services have the ability to undo any work, they inform the BA, in case the BA later decides the cancel the work. If the BA suffers a failure. it can instruct the service to execute its
undo
behavior.
Assumptions of WS-BA
- All state transitions are reliably recorded, including application state and coordination metadata (the record of sent and received messages).
- All request messages are acknowledged, so that problems are detected as early as possible. This avoids executing unnecessary tasks and can also detect a problem earlier when rectifying it is simpler and less expensive.
- As with atomic transactions, a response is defined as a separate operation, not as the output of the request. Message I/O implementations typically have timeout requirements too short for BA responses. If the response is not received after a timeout, it is re-sent, repeatedly, until a response is received. The receiver discards all but one identical request received.
BusinessAgreementWithParticipantCompletion
and BusinessAgreementWithCoordinatorCompletion
. Unlike the AT protocols which are driven from the coordinator down to participants, this protocol takes the opposite approach.
- BusinessAgreementWithParticipantCompletion
- A participant is initially created in the Active state.
- If it finishes its work and it is no longer needed within the scope of the BA (such as when the activity operates on immutable data), the participant can unilaterally decide to exit, sending an
exited
message to the coordinator. However, if the participant finishes and wishes to continue in the BA, it must be able to compensate for the work it has performed. In this case, it sends acompleted
message to the coordinator and waits for the coordinator to notify it about the final outcome of the BA. This outcome is either aclose
message, meaning the BA has completed successfully, or acompensate
message indicating that the participant needs to reverse its work.
- BusinessAgreementWithCoordinatorCompletion
- The
BusinessAgreementWithCoordinatorCompletion
differs from theBusinessAgreementWithParticipantCompletion
protocol in that the participant cannot autonomously decide to complete its participation in the BA, even if it can be compensated.- Instead, the completion stage is driven by the client which created the BA, which sends a
completed
message to the coordinator. - The coordinator sends a
complete
message to each participant, indicating that no further requests will be sent to the service associated with the participant. - The participant continues on in the same manner as in the BusinessAgreementWithParticipantCompletion protocol.
BusinessAgreementWithParticipantCompletion
participant and the message exchanges between coordinator and participant. Messages generated by the coordinator are shown with solid lines, while the participants' messages are illustrated with dashed lines.
Figure 18.8.
BusinessAgreementWithCoordinatorCompletion
participant and the message exchanges between coordinator and participant. Messages generated by the coordinator are shown with solid lines, while the participants' messages are illustrated with dashed lines.
Figure 18.9.
18.2.4. Application Messages
18.2.4.1. WS-C, WS-Atomic Transaction, and WS-Business Activity Messages
begin
and prepare
.
Note
18.3. Summary
Chapter 19. Getting Started
19.1. Installing the XTS Service Archive into JBoss Transaction Service
$JBOSS_HOME/docs/examples/transactions/
. To install it, follow Procedure 19.1, “Installing the XTS Module”.
Procedure 19.1. Installing the XTS Module
- Create a sub-directory in the
$JBOSS_HOME/server/[name]/deploy/
directory, calledjbossxts.sar/
. - Unpack the SAR, which is a ZIP archive, into this new directory.
- Restart JBoss Enterprise Application Platform to activate the module.
19.2. Creating Client Applications
begin
, commit
, and rollback
, which the client application can use to initialize, manage, and terminate transactions. Internally, this API uses SOAP to invoke operations on the various WS-C, WS-AT and WS-BA services, in order to create a coordinator and drive the transaction to completion.
19.2.1. User Transactions
UserTransactionFactory
and UserTransaction
classes to create and manage WS-AT transactions. These classes provide a simple API which operates in a manner similar to the JTA API. A WS-AT transaction is started and associated with the client thread by calling the begin
method of the UserTransaction
class. The transaction can be committed by calling the commit
method, and rolled back by calling the rollback
method.
TransactionManagerFactory
and TransactionManager
classes.
19.2.2. Business Activities
UserBusinessActivityFactory
and UserBusinessActivity
classes. A WS-BA activity is started and associated with the client thread by calling the begin
method of the UserBusinessActivity
class. A client can terminate a business activity by calling the close
method, and cancel it by calling the cancel
method.
BusinessActivityWithCoordinatorCompletion
protocol, the client can call the completed
method before calling the close
method, to notify the services that it has finished making service invocations in the current activity.
BusinessActivityManagerFactory
and BusinessActivityManager
classes.
19.2.3. Client-Side Handler Configuration
- It must forward details of the current transaction to the server when invoking a web service.
- It must process any responses from the server in the context of the correct transaction.
Note
19.2.3.1. JAX-WS Client Context Handlers
javax.xml.ws.BindingProvider
and javax.xml.ws.Binding
classes, to install a handler chain on the service proxy which is used to invoke the remote endpoint. Refer to the example application client implementation located in the src/com/jboss/jbosstm/xts/demo/BasicClient.java
file for an example.
javax.jws.HandlerChain
annotation to the interface class, which declares the JAX-WS client API. This interface is normally generated from the web service WSDL port definition.
com.arjuna.mw.wst11.client.JaxWSHeaderContextProcessor
class when registering a JAX-WS client context handler.
19.3. Creating Transactional Web Services
19.3.1. Participants
com.arjuna.wst11.Durable2PCParticipant
, com.arjuna.wst11.Volatile2PCParticipant
, com.arjuna.wst11.BusinessAgreementWithParticipantCompletionParticipant
, or com.arjuna.wst11.BusinessAgreementWithCoordinatorCompletionParticipant
.
19.3.2. Service-Side Handler Configuration
Note
Note
19.3.2.1. JAX-WS Service Context Handlers
javax.jws.WebService
, must be supplemented with a javax.jws.HandlerChain
annotation which identifies a handler configuration file deployed with the application. Please refer to the example application configuration file located at dd/jboss/context-handlers.xml
and the endpoint implementation classes located in src/com/jboss/jbosstm/xts/demo/services
for an example.
com.arjuna.mw.wst11.service.JaxWSHeaderContextProcessor
class. If you need coordinator interposition, employ the com.arjuna.mw.wst11.service.JaxWSSubordinateHeaderContextProcessor
instead.
Figure 19.1. Context Handlers Registered with the SOAP Server
19.4. Summary
Chapter 20. Participants
20.1. Overview
Figure 20.1. Transactions, Participants, and Back-End Transaction Control
20.1.1. Atomic Transaction
20.1.1.1. Durable2PCParticipant
com.arjuna.wst11.Durable2Participant
interface.
Durable2PCParticipant Signatures
prepare
- The participant should perform any work necessary, so that it can either commit or roll back the work performed by the Web service under the scope of the transaction. The implementation is free to do whatever it needs to in order to fulfill the implicit contract between it and the coordinator.The participant indicates whether it can
prepare
by returning an instance of thecom.arjuna.wst11.Vote
, with one of three values.ReadOnly
indicates that the participant does not need to be informed of the transaction outcome, because it did not update any state information.Prepared
indicates that the participant is ready to commit or roll back, depending on the final transaction outcome. Sufficient state updates have been made persistent to accomplish this.Aborted
indicates that the participant has aborted and the transaction should also attempt to do so.
commit
- The participant should make its work permanent. How it accomplishes this depends upon its implementation. For instance, in the theater example, the reservation of the ticket is committed. If commit processing cannot complete, the participant should throw a
SystemException
error, potentially leading to a heuristic outcome for the transaction. rollback
- The participant should undo its work. If rollback processing cannot complete, the participant should throw a
SystemException
error, potentially leading to a heuristic outcome for the transaction. unknown
- This method has been deprecated and is slated to be removed from XTS in the future.
error
- In rare cases when recovering from a system crash, it may be impossible to complete or roll back a previously prepared participant, causing the
error
operation to be invoked.
20.1.1.2. Volatile2PCParticipant
com.arjuna.wst11.Volatile2Participant
interface.
Volatile2PCParticipant Signatures
prepare
- The participant should perform any work necessary to flush any volatile data created by the Web service under the scope of the transaction, to the system store. The implementation is free to do whatever it needs to in order to fulfill the implicit contract between it and the coordinator.The participant indicates whether it can
prepare
by returning an instance of thecom.arjuna.wst11.Vote
, with one of three values.ReadOnly
indicates that the participant does not need to be informed of the transaction outcome, because it did not change any state information during the life of the transaction.Prepared
indicates that the participant wants to be notified of the final transaction outcome via a call tocommit
orrollback
.Aborted
indicates that the participant has aborted and the transaction should also attempt to do so.
- commit
- The participant should perform any cleanup activities required, in response to a successful transaction commit. These cleanup activities depend upon its implementation. For instance, it may flush cached backup copies of data modified during the transaction. In the unlikely event that commit processing cannot complete, the participant should throw a
SystemException
error. This will not affect the outcome of the transaction but will cause an error to be logged. This method may not be called if a crash occurs during commit processing. - rollback
- The participant should perform any cleanup activities required, in response to a transaction abort. In the unlikely event that rollback processing cannot complete, the participant should throw a
SystemException
error. This will not affect the outcome of the transaction but will cause an error to be logged. This method may not be called if a crash occurs during commit processing. - unknown
- This method is deprecated and will be removed in a future release of XTS.
- error
- This method should never be called, since volatile participants are not involved in recovery processing.
20.1.2. Business Activity
20.1.2.1. BusinessAgreementWithParticipantCompletion
BusinessAgreementWithParticipantCompletion
interface supports the WS-Transactions BusinessAgreementWithParticipantCompletion
protocol with the signatures listed in BusinessAgreementWithParticipantCompletion
Signatures, as per interface com.arjuna.wst11.BusinessAgreementWithParticipantCompletionParticipant
.
BusinessAgreementWithParticipantCompletion
Signatures
close
- The transaction has completed successfully. The participant has previously informed the coordinator that it was ready to complete.
cancel
- The transaction has canceled, and the participant should undo any work. The participant cannot have informed the coordinator that it has completed.
compensate
- The transaction has canceled. The participant previously informed the coordinator that it had finished work but could compensate later if required, and it is now requested to do so. If compensation cannot be performed, the participant should throw a
FaultedException
error, potentially leading to a heuristic outcome for the transaction. If compensation processing cannot complete because of a transient condition then the participant should throw aSystemException
error, in which case the compensation action may be retried or the transaction may finish with a heuristic outcome. status
- Return the status of the participant.
unknown
- This method is deprecated and will be removed a future XTS release.
- error
- In rare cases when recovering from a system crash, it may be impossible to compensate a previously-completed participant. In such cases the
error
operation is invoked.
20.1.2.2. BusinessAgreementWithCoordinatorCompletion
BusinessAgreementWithCoordinatorCompletion
protocol with the signatures listed in BusinessAgreementWithCoordinatorCompletion Signatures, as per the com.arjuna.wst11.BusinessAgreementWithCoordinatorCompletionParticipant
interface.
BusinessAgreementWithCoordinatorCompletion Signatures
close
- The transaction completed successfully. The participant previously informed the coordinator that it was ready to complete.
cancel
- The transaction canceled, and the participant should undo any work.
compensate
- The transaction canceled. The participant previously informed the coordinator that it had finished work but could compensate later if required, and it is now requested to do so. In the unlikely event that compensation cannot be performed the participant should throw a
FaultedException
error, potentially leading to a heuristic outcome for the transaction. If compensation processing cannot complete because of a transient condition, the participant should throw aSystemException
error, in which case the compensation action may be retried or the transaction may finish with a heuristic outcome. complete
- The coordinator is informing the participant all work it needs to do within the scope of this business activity has been completed and that it should make permanent any provisional changes it has made.
status
- Returns the status of the participant.
unknown
- This method is deprecated and will be removed in a future release of XTS.
error
- In rare cases when recovering from a system crash, it may be impossible to compensate a previously completed participant. In such cases, the
error
method is invoked.
20.1.2.3. BAParticipantManager
BAParticipantManager Methods
exit
- The participant uses the method
exit
to inform the coordinator that it has left the activity. It will not be informed when and how the business activity terminates. This method may only be invoked while the participant is in theactive
state (or thecompleting
state, in the case of a participant registered for theParticipantCompletion
protocol). If it is called when the participant is in any other state, aWrongStateException
error is thrown. Anexit
does not stop the activity as a whole from subsequently being closed or canceled/compensated, but only ensures that the exited participant is no longer involved in completion, close or compensation of the activity. completed
- The participant has completed its work, but wishes to continue in the business activity, so that it will eventually be informed when, and how, the activity terminates. The participant may later be asked to compensate for the work it has done or learn that the activity has been closed.
fault
- The participant encountered an error during normal activation and has done whatever it can to compensate the activity. The
fault
method places the business activity into a mandatorycancel-only
mode. The faulted participant is no longer involved in completion, close or compensation of the activity.
20.2. Participant Creation and Deployment
20.2.1. Implementing Participants
Note
com.arjuna.wst
.
20.2.2. Deploying Participants
Warning
.jar
, .war
, and configuration files bundled with the application. This deployment method is no longer supported in the Enterprise Application Platform.
Chapter 21. The XTS API
21.1. API for the Atomic Transaction Protocol
21.1.1. Vote
com.arjuna.wst11.Vote
listed in Subclasses of com.arjuna.wst11.Vote
.
Subclasses of com.arjuna.wst11.Vote
- Prepared
- Indicates that the participant can prepare if the coordinator requests it. Nothing has been committed, because the participant does not know the final outcome of the transaction.
- Aborted
- The participant cannot prepare, and has rolled back. The participant should not expect to get a second phase message.
- ReadOnly
- The participant has not made any changes to state, and it does not need to know the final outcome of the transaction. Essentially the participant is resigning from the transaction.
Example 21.1. Example Implementation of 2PC Participant's prepare
Method
public Vote prepare () throws WrongStateException, SystemException { // Some participant logic here if(/* some condition based on the outcome of the business logic */) { // Vote to confirm return new com.arjuna.wst.Prepared(); } else if(/*another condition based on the outcome of the business logic*/) { // Resign return new com.arjuna.wst.ReadOnly(); } else { // Vote to cancel return new com.arjuna.wst.Aborted(); } }
21.1.2. TXContext
TxContext Return Values
- valid
- Indicates whether the contents are valid.
- equals
- Can be used to compare two instances for equality.
Note
21.1.3. UserTransaction
com.arjuna.mw.wst11.UserTransaction
is the class that clients typically employ. Before a client can begin a new atomic transaction, it must first obtain a UserTransaction
from the UserTransactionFactory
. This class isolates the user from the underlying protocol-specific aspects of the XTS implementation. A UserTransaction
does not represent a specific transaction. Instead, it provides access to an implicit per-thread transaction context, similar to the UserTransaction
in the JTA specification. All of the UserTransaction
methods implicitly act on the current thread of control.
userTransaction
Methods
- begin
- Used to begin a new transaction and associate it with the invoking thread.
Parameters
- timeout
- This optional parameter, measured in milliseconds, specifies a time interval after which the newly created transaction may be automatically rolled back by the coordinator
Exceptions
WrongStateException
- A transaction is already associated with the thread.
- commit
- Volatile2PC and Durable2PC participants enrolled in the transaction are requested first to prepare and then to commit their changes. If any of the participants fails to prepare in the first phase then all other participants are requested to abort.
Exceptions
UnknownTransactionException
- No transaction is associated with the invoking thread.
TransactionRolledBackException
- The transaction was rolled back either because of a timeout or because a participant was unable to commit.
- rollback
- Terminates the transaction. Upon completion, the
rollback
method disassociates the transaction from the current leaving it unassociated with any transactions.Exceptions
UnknownTransactionException
- No transaction is associated with the invoking thread.
21.1.4. UserTransactionFactory
getUserTransaction
method to obtain a Section 21.1.3, “UserTransaction” instance from a UserTransactionFactory
.
21.1.5. TransactionManager
TransactionManager
does not represent a specific transaction. Instead, it provides access to an implicit per-thread transaction context.
Methods
currentTransaction
- Returns a
TxContext
for the current transaction, or null if there is no context. Use thecurrentTransaction
method to determine whether a web service has been invoked from within an existing transaction. You can also use the returned value to enable multiple threads to execute within the scope of the same transaction. Calling thecurrentTransaction
method does not disassociate the current thread from the transaction. suspend
- Dissociates a thread from any transaction. This enables a thread to do work that is not associated with a specific transaction.The
suspend
method returns aTxContext
instance, which is a handle on the transaction. resume
- Associates or re-associates a thread with a transaction, using its
TxContext
. Prior to association or re-association, the thread is disassociated from any transaction with which it may be currently associated. If theTxContext
is null, then the thread is associated with no transaction. In this way, the result is the same as if thesuspend
method were used instead.Parameters
- txContext
- A TxContext instance as return by
suspend
, identifying the transaction to be resumed.
Exceptions
UnknownTransactionException
- The transaction referred to by the
TxContext
is invalid in the scope of the invoking thread.
enlistForVolitaleTwoPhase
- Enroll the specified participant with the current transaction, causing it to participate in the Volatile2PC protocol. You must pass a unique identifier for the participant.
Parameters
- participant
- An implementation of interface Volatile2PCParticipant whose prepare, commit and abort methods are called when the corresponding coordinator message is received.
- id
- A unique identifier for the participant. The value of this String should differ for each enlisted participant. It should also be possible for a given identifier to determine that the participant belongs to the enlisting web service rather than some other web service deployed to the same container.
Exceptions
- UnknownTransactionException
- No transaction is associated with the invoking thread.
WrongStateException
- The transaction is not in a state that allows participants to be enrolled. For instance, it may be in the process of terminating.
enlistForDurableTwoPhase
- Enroll the specified participant with the current transaction, causing it to participate in the Durable2PC protocol. You must pass a unique identifier for the participant.
Exceptions
- UnknownTransactionException
- No transaction is associated with the invoking thread.
WrongStateException
- The transaction is not in a state that allows participants to be enrolled. For instance, it may be in the process of terminating.
21.1.6. TransactionManagerFactory
getTransactionManager
method to obtain a Section 21.1.5, “TransactionManager” from a TransactionManagerFactory
.
21.2. API for the Business Activity Protocol
21.2.1. Compatibility
21.2.2. UserBusinessActivity
com.arjuna.wst11.UserBusinessActivity
is the class that most clients employ. A client begins a new business activity by first obtaining a UserBusinessActivity
from the UserBusinessActivityFactory
. This class isolates them from the underlying protocol-specific aspects of the XTS implementation. A UserBusinessActivity does not represent a specific business activity. Instead, it provides access to an implicit per-thread activity. Therefore, all of the UserBusinessActivity
methods implicitly act on the current thread of control.
Methods
begin
- Begins a new activity, associating it with the invoking thread.
Parameters
- timeout
- The interval, in milliseconds, after which an activity times out. Optional.
Exceptions
WrongStateException
- The thread is already associated with a business activity.
close
- First, all Coordinator Completion participants enlisted in the activity are requested to complete the activity. Next all participants, whether they enlisted for Coordinator or Participant Completion, are requested to close the activity. If any of the Coordinator Completion participants fails to complete at the first stage then all completed participants are asked to compensate the activity while any remaining uncompleted participants are requested to cancel the activity.
Exceptions
- UnknownTransactionException
- No activity is associated with the invoking thread.
- TransactionRolledBackException
- The activity has been cancelled because one of the Coordinator Completion participants failed to complete. This exception may also thrown if one of the Participant Completion participants has not completed before the client calls close.
- cancel
- Terminates the business activity. All Participant Completion participants enlisted in the activity which have already completed are requested to compensate the activity. All uncompleted Participant Completion participants and all Coordinator Completion participants are requested to cancel the activity.
Exceptions
UnknownTransactionException
- No activity is associated with the invoking thread. Any participants that previous completed are directed to compensate their work.
21.2.3. UserBusinessActivityFactory
getuserbusinessActivity
method to obtain a Section 21.2.2, “UserBusinessActivity” instance from a userBusinessActivityFactory
.
21.2.4. BusinessActivityManager
BusinessActivityManager
does not represent a specific activity. Instead, it provides access to an implicit per-thread activity.
Methods
currentTransaction
- Returns the
TxContext
for the current business activity, orNULL
if there is noTxContext
. The returned value can be used to enable multiple threads to execute within the scope of the same business activity. Calling thecurrenTransaction
method does not dissociate the current thread from its activity. suspend
- Dissociates a thread from any current business activity, so that it can perform work not associated with a specific activity. The
suspend
method returns aTxContext
instance, which is a handle on the activity. The thread is then no longer associated with any activity. resume
- Associates or re-associates a thread with a business activity, using its
TxContext
. Before associating or re-associating the thread, it is disassociated from any business activity with which it is currently associated. If theTxContext
isNULL
, the thread is disassociated with all business activities, as though thesuspend
method were called.Parameters
- txContext
- A TxContext instance as returned by
suspend
, identifying the transaction to be resumed.
Exceptions
UnknownTransactionException
- The business activity to which the
TxContext
refers is invalid in the scope of the invoking thread.
enlistForBusinessAgreementWithParticipantCompletion
- Enroll the specified participant with current business activity, causing it to participate in the
BusinessAgreementWithParticipantCompletion
protocol. A unique identifier for the participant is also required.The return value is an instance of BAParticipantManager which can be used to notify the coordinator of changes in the participant state. In particular, since the participant is enlisted for the Participant Completion protcol it is expected to call the completed method of this returned instance when it has completed all the work it expects to do in this activity and has made all its changes permanent. Alternatively, if the participant does not need to perform any compensation actions should some other participant fail it can leave the activity by calling the exit method of the returned BAParticipantManager instance.Parameters
- participant
- An implementation of interface
BusinessAgreementWithParticipantCompletionParticipant
whoseclose
,cancel
, andcompensate
methods are called when the corresponding coordinator message is received. - id
- A unique identifier for the participant. The value of this String should differ for each enlisted participant. It should also be possible for a given identifier to determine that the participant belongs to the enlisting web service rather than some other web service deployed to the same container.
Exceptions
- UnknownTransactionException
- No transaction is associated with the invoking thread.
- WrongStateException
- The transaction is not in a state where new participants may be enrolled, as when it is terminating.
enlistForBusinessAgreementWithCoordinatorCompletion
- Enroll the specified participant with current activity, causing it to participate in the
BusinessAgreementWithCoordinatorCompletion
protocol. A unique identifier for the participant is also required.The return value is an instance ofBAParticipantManager
which can be used to notify the coordinator of changes in the participant state. Note that in this case it is an error to call thecompleted
method of this returned instance. With the Coordinator Completion protocol the participant is expected to wait until itscompleted
method is called before it makes all its changes permanent. Alternatively, if the participant determiens that it has no changes to make, it can leave the activity by calling theexit
method of the returnedBAParticipantManager
instance.Parameters
- participant
- An implementation of interface BusinessAgreementWithCoordinatorCompletionParticipant whose completed, close, cancel and compensate methods are called when the corresponding coordinator message is received.
- id
- A unique identifier for the participant. The value of this String should differ for each enlisted participant. It should also be possible for a given identifier to determine that the participant belongs to the enlisting web service rather than some other web service deployed to the same container.
Exceptions
- >UnknownTransactionException
- No transaction is associated with the invoking thread.
- WrongStateException
- The transaction is not in a state where new participants may be enrolled, as when it is terminating.
21.2.5. BusinessActivityManagerFactory
getBusinessActivityManager
method to obtain a Section 21.2.4, “BusinessActivityManager” instance from a BusinessActivityManagerFactory
.
Chapter 22. Stand-Alone Coordination
22.1. Introduction
Reasons for Choosing a Stand-Alone Coordinator
- Efficiency: if a client application invokes Web Services on a remote Enterprise Application Platform server, coordinating the transaction from the remote server might be more efficient, since the protocol-specific messages between the coordinator and the participants do not need to travel over the network.
- Reliability: if the coordinator service runs on a dedicated host, there is no danger of failing applications or services affecting the coordinator and causing failures for unrelated transactions.
- A third reason might be to use a coordination service provided by a third party vendor.
22.2. Configuring the Activation Coordinator
-D
option specifies a setting for a System property. Several configuration options can be enabled, taking effect in Section 22.2.1, “Command-Line Options Passed with the -D
Parameter, Ordered by Priority”.
22.2.1. Command-Line Options Passed with the -D
Parameter, Ordered by Priority
Absolute URL
- Property:
org.jboss.jbossts.xts11.coordinatorURL
- The value assigned to these URLs depends upon the configuration of the remote coordinator host. The sample values listed with the property names are appropriate when the coordinator is another JBoss Transaction Service XTS service. Substitute the coord.host and coord.port with the appropriate values for the Enterprise Application Platform instance running the Activation Coordinator service.
Coordinator Host Information
Property
- org.jboss.jbossts.xts11.coordinator.host
- org.jboss.jbossts.xts11.coordinator.port
- org.jboss.jbossts.xts11.coordinator.path
Format
- server.bind.address
- jboss.web.bind.port
- ws-c11/ActivationService
- If you set any of these three components, the coordinator URL is constructed using whichever of the component values is defined and substituting the default values specified for any undefined components. The values server.bind.address and jboss.web.bind.port represent the server bind address and the web service listener port obtained either from the application server command-line or the server configuration files.
Chapter 23. Participant Crash Recovery
Procedure 23.1. Presumed Abort Policy
- If the coordinator crashes, it can assume that any transaction it does not know about is invalid, and reject a participant request which refers to such a transaction.
- If the participant crashes, it can forget any provisional changes it has made, and reject any request from the coordinator service to prepare a transaction or complete a business activity.
- WS-AT Transaction
- The transaction needs to commit all provisional changes or roll them all back to the state before the transaction started.
- WS-Business Activity Transaction
- All participants need to close the activity or cancel the activity, and run any required compensating actions.
23.1. WS-AT Recovery
23.1.1. WS-AT Coordinator Crash Recovery
prepare
message and have responded with a prepared
message, the coordinator writes a log record storing each participant's details, indicating that the transaction is ready to complete. If the coordinator service crashes after this point has been reached, completion of the two-phase commit protocol is still guaranteed, by reading the log file after reboot and sending a commit
message to each participant. Once all participants have responded to the commit
with a committed
message, the coordinator can safely delete the log entry.
prepared
messages returned by the participants imply that they are ready to commit their provisional changes and make them permanent, this type of recovery is safe. Additionally, the coordinator does not need to account for any commit messages which may have been sent before the crash, or resend messages if it crashes several times. The XTS participant implementation is resilient to redelivery of the commit
messages. If the participant has implemented the recovery functions described in Section 23.1.2.1, “WS-AT Participant Crash Recovery APIs”, the coordinator can guarantee delivery of commit
messages if both it crashes, and one or more of the participant service hosts also crash, at the same time.
prepare
phase completes, the presumed abort protocol ensures that participants are rolled back. After system restart, the coordination service has the information about about all the transactions which could have entered the commit
phase before the reboot, since they have entries in the log. It also knows about any active transactions started after the reboot. If a participant is waiting for a response, after sending its prepared
message, it automatically re sends the prepared
message at regular intervals. When the coordinator detects a transaction which is not active and has no entry in the log file after the reboot, it instructs the participant to abort, ensuring that the web service gets a chance to roll back any provisional state changes it made on behalf of the transaction.
23.1.2. WS-AT Participant Crash Recovery
prepare
, the Web service is expected to save to persistent storage the transactional state it needs to commit or roll back the transaction. The specific information it needs to save is dependent on the implementation and business logic of the Web Service. However, the participant must save this state before returning a Prepared
vote from the prepare
call. If the participant cannot save the required state, or there is some other problem servicing the request made by the client, it must return an Aborted
vote.
prepare
, commit
, and rollback
methods. The XTS implementation tracks the local state of every enlisted participant. If the prepare
call returns a Prepared
vote, the XTS implementation ensures that the participant state is logged to the local transaction log before forwarding a prepared
message to the coordinator.
commit
process to completion, or roll it back if some other Web Service fails to prepare
. This information might be as simple as a String key which the participant can use to locate the data it made persistent before returning its Prepared vote. It may be as complex as a serialized object tree containing the original participant instance and other objects created by the Web service.
commit
or rollback
method is called.
Warning
commit
method is called, a commit
or rollback
method may be called twice.
23.1.2.1. WS-AT Participant Crash Recovery APIs
23.1.2.1.1. Saving Participant Recovery State
java.lang.Serializable
interface. Alternatively it may implement Example 23.1, “The PersistableATParticipant
Interface”.
Example 23.1. The PersistableATParticipant
Interface
public interface PersistableATParticipant { byte[] getRecoveryState() throws Exception; }
Serializable
interface, the XTS participant services implementation uses the serialization API to create a version of the participant which can be appended to the participant log entry. If it implements the PersistableATParticipant
interface, the XTS participant services implementation call the getRecoveryState
method to obtain the state to be appended to the participant log entry.
23.1.2.1.2. Recovering Participants at Reboot
XTSATRecoveryManager
defined in package org.jboss.jbossts.xts.recovery.participant.at.
Example 23.2. Registering for Recovery
public abstract class XTSATRecoveryManager { . . . public static XTSATRecoveryManager getRecoveryManager() ; public void registerRecoveryModule(XTSATRecoveryModule module); public abstract void unregisterRecoveryModule(XTSATRecoveryModule module) throws NoSuchElementException; . . . }
XTSATRecoveryModule
, located in the org.jboss.jbossts.xts.recovery.participant.at, as argument to both the register
and unregister
calls. This instance is responsible for identifying saved participant recovery records and recreating new, recovered participant instances.
Example 23.3. XTSATRecoveryModule
Implementation
public interface XTSATRecoveryModule { public Durable2PCParticipant deserialize(String id, ObjectInputStream stream) throws Exception; public Durable2PCParticipant recreate(String id, byte[] recoveryState) throws Exception; }
deserialize
method is called to recreate the participant. Normally, the recovery module is required to read, cast, and return an object from the supplied input stream. If a participant's recovery state was saved using the PersistableATParticipant
interface, the recovery module's recreate
method is called to recreate the participant from the byte array it provided when the state was saved.
null
. The participant identifier, which is supplied as argument to the deserialize
or recreate
method, is the identifier used by the Web service when the original participant was enlisted in the transaction. Web Services participating in recovery processing should ensure that participant identifiers are unique per service. If a module recognizes that a participant identifier belongs to its Web service, but cannot recreate the participant, it should throw an exception. This situation might arise if the service cannot associate the participant with any transactional information which is specific to the business logic.
deserialization
operation must employ a class loader capable of loading classes specific to the Web service. XTS fulfills this requirement by devolving responsibility for the deserialize
operation to the recovery module.
23.2. WS-BA Recovery
23.2.1. WS-BA Coordinator Crash Recovery
CoordinatorCompletion
participants receive a complete
message and respond with a completed
message. At this point, all ParticipantCompletion
participants should have sent a completed
message. The coordinator writes a log record storing the details of each participant, and indicating that the transaction is ready to close. If the coordinator service crashes after the log record is written, the close
operation is still guaranteed to be successful. The coordinator checks the log after the system reboots and re sends a close
message to all participants. After all participants respond to the close
with a closed
message, the coordinator can safely delete the log entry.
close
messages sent before the crash, nor resend messages if it crashes several times. The XTS participant implementation is resilient to redelivery of close
messages. Assuming that the participant has implemented the recovery functions described below, the coordinator can even guarantee delivery of close
messages if both it, and one or more of the participant service hosts, crash simultaneously.
compensate
message. Recovery must be initiated from the participant side.
cancel
or compensate
request, the coordinator logs a warning and continues. The combination of the presumed abort protocol and participant-led recovery ensures that all participants eventually get canceled or compensated, as appropriate, even if the participant host crashes.
completed
response a suitable number of times, it switches to sending getstatus
messages, to determine whether the coordinator still knows about it. If a crash occurs before writing the log record, the coordinator has no record of the participant when the coordinator restarts, and the getstatus
request returns a fault. The participant recovery manager automatically compensates the participant in this situation, just as if the activity had been canceled by the client.
getstatus
messages to each participant's coordinator host, to determine whether the activity still exists. If the coordinator has not crashed and the activity is still running, the participant switches back to resending completed
messages, and waits for a close
or compensate
response. If the coordinator has also crashed or the activity has been canceled, the participant is automatically canceled.
23.2.2. WS-BA Participant Crash Recovery APIs
23.2.2.1. Saving Participant Recovery State
java.lang.Serializable
interface. An alternative is to implement the Example 23.4, “PersistableBAParticipant
Interface”.
Example 23.4. PersistableBAParticipant
Interface
public interface PersistableBAParticipant { byte[] getRecoveryState() throws Exception; }
Serializable
interface, the XTS participant services implementation uses the serialization API to create a version of the participant which can be appended to the participant log entry. If the participant implements the PersistableBAParticipant
, the XTS participant services implementation call the getRecoveryState
method to obtain the state, which is appended to the participant log entry.
23.2.2.2. Recovering Participants at Reboot
XTSBARecoveryManager
, defined in the org.jboss.jbossts.xts.recovery.participant.ba package.
Example 23.5. XTSBARecoveryManager
Class
public abstract class XTSBARecoveryManager { . . . public static XTSBARecoveryManager getRecoveryManager() ; public void registerRecoveryModule(XTSBARecoveryModule module); public abstract void unregisterRecoveryModule(XTSBARecoveryModule module) throws NoSuchElementException; . . . }
XTSBARecoveryModule
in the org.jboss.jbossts.xts.recovery.participant.ba, as an argument to the register
and unregister
calls. This instance identifies saved participant recovery records and recreates new, recovered participant instances:
Example 23.6. XTSBARecoveryModule
Interface
public interface XTSATRecoveryModule { public BusinessAgreementWithParticipantCompletionParticipant deserializeParticipantCompletionParticipant(String id, ObjectInputStream stream) throws Exception; public BusinessAgreementWithParticipantCompletionParticipant recreateParticipantCompletionParticipant(String id, byte[] recoveryState) throws Exception; public BusinessAgreementWithCoordinatorCompletionParticipant deserializeCoordinatorCompletionParticipant(String id, ObjectInputStream stream) throws Exception; public BusinessAgreementWithCoordinatorCompletionParticipant recreateCoordinatorCompletionParticipant(String id, byte[] recoveryState) throws Exception; }
deserialize
methods is called, so that it can recreate the participant. Which method to use depends on whether the saved participant implemented the ParticipantCompletion
protocol or the CoordinatorCompletion
protocol. Normally, the recovery module reads, casts and returns an object from the supplied input stream. If a participant's recovery state was saved using the PersistableBAParticipant
interface, one of the recovery module's recreate
methods is called, so that it can recreate the participant from the byte array provided when the state was saved. The method to use depends on which protocol the saved participant implemented.
null
. The participant identifier supplied as an argument to the deserialize
or recreate
calls is the identifier used by the Web service when the original participant was enlisted in the transaction. Web Services which participate in recovery processing should ensure that the participant identifiers they employ are unique per service. If a module recognizes a participant identifier as belonging to its Web service, but cannot recreate the participant, it throws an exception. This situation might arise if the service cannot associate the participant with any transactional information specific to business logic.
deserialization
operation must employ a class loader capable of loading Web service-specific classes. The XTS implementation achieves this by delegating responsibility for the deserialize
operation to the recovery module.
Appendix C. Revision History
Revision History | |||||
---|---|---|---|---|---|
Revision 5.1.0-111.400 | 2013-10-31 | ||||
| |||||
Revision 5.1.0-111 | 2012-07-18 | ||||
| |||||
Revision 5.1.0-110 | Wed Sep 15 2010 | ||||
|
Index
A
- ACID, Transactions Overview
- activation, Overview of Protocols Used by XTS
- Activation Coordinator, Overview of Protocols Used by XTS
- activation coordinator, Stand-Alone Coordination
- active component, Introduction
- API, The XTS API
- atomic transactions
- atomicity, Participants
B
- BAParticipantManager, Participants
- business activities, Getting Started
- BusinessActivityManager, The XTS API
- BusinessActivityManagerFactory, The XTS API
- BusinessAgreementWithCoordinatorCompletion, Overview of Protocols Used by XTS, Participants
- BusinessAgreementWithParticipantCompletion, Overview of Protocols Used by XTS, Participants
C
- com.arjuna.mw.wst11
- XTS API, Getting Started
- command-line options, Stand-Alone Coordination
- completion, Overview of Protocols Used by XTS
- context handlers, Getting Started
- coordination context, Overview of Protocols Used by XTS
- Coordinator, Transactions Overview
D
- DE
- Document Exchange, Introduction
- deployment, Participants
- Durable2PC, Overview of Protocols Used by XTS
- Durable2PCParticipant, Participants
F
- fault-tolerance, Introduction
H
- Heuristic Outcomes, Transactions Overview
I
- implementation, Participants
- Interpositions, Transactions Overview
J
- JAX-RPC, Getting Started
N
- Non-atomic, Transactions Overview
O
- One-Phase Commit
- Optimizations to Synchronization Protocols, Transactions Overview
P
- Participant, Transactions Overview
- participant recovery, Participant Crash Recovery
- participants, Getting Started, Participants
- transaction participants, Introduction
- presumed abort policy, Participant Crash Recovery
R
- recovery, Participant Crash Recovery
- registration, Overview of Protocols Used by XTS
- RPC
- Remote Procedure Calls, Introduction
S
- SAR
- Service Archive, Stand-Alone Coordination
- service-side handlers, Getting Started
- servlets
- Java servlets, Introduction
- SOAP, Introduction
- stand-alone coordination, Stand-Alone Coordination
- Synchronization Protocol, Transactions Overview
T
- Transaction Context, Transactions Overview
- Transaction Service, Transactions Overview
- TransactionManager, The XTS API
- TransactionManagerFactory, The XTS API
- transactions, Introduction, Transactions Overview
- Two-Phase Commit
- TXContext, The XTS API
U
- undesirable outcomes, Introduction
- user transactions, Getting Started
- UserBusinessActivity, The XTS API
- UserBusinessActivityFactory, The XTS API
- UserTransaction, The XTS API
- UserTransactionFactory, The XTS API
V
- Volatile2PC, Overview of Protocols Used by XTS
- Volatile2PCParticipant, Participants
- vote, The XTS API
W
- Web Service, Transactions Overview
- Web Services, Introduction
- WS-Atomic Transaction
- WS-Business Activity
- WS-Coordination
- WSDL
- Web Services Description Language, Introduction
X
- XTS
- XML Transaction Service, Introduction
- XTS 1.0
- XTS 1.1, Introduction