JavaEnterprise JavaTransaction Services with JTA and JTS

Transaction Services with JTA and JTS

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.


This material is from Chapter 14, Transaction Services with JTA and JTS, from the book J2EE Developer’s Handbook (ISBN: 0-672-32348-6) written by Paul J. Perrone, Venkata S.R. “Krishna” R. Chaganti, and Tom Schwenk, published by Sams Publishing.


Chapter 14: Transaction Services with JTA and JTS

Chapter 14: Transaction Services with JTA and JTS

In this chapter, we describe more than the mere application of transactions to databases. We explore those services used to manage transactions in a distributed enterprise system. Distributed objects need to coordinate and define boundaries for access to shared resources. Transaction services provide such support. This chapter expands on the transaction problem and generic transaction service architecture, the CORBA Object Transaction Service (OTS), the Java Transaction API (JTA), and the Java Transaction Service (JTS). As you'll see, the JTS is a Java mapping of the OTS. Finally, we also touch on the latest developments in industry and with Java as it regards transactional Web services.

The JTA and OTS/JTS are all core underlying components that can be utilized by J2EE-based servers. The J2EE specification, in fact, requires that certain APIs defined by the JTA be incorporated into J2EE-compliant servers. Although the J2EE's declarative model for using transactions simplifies application programming, much of the literature and declarative programming conventions describing transaction usage with the J2EE is described in the context of JTA and OTS/JTS constructs and concepts. A basic understanding of the underlying transactions framework will help you make better decisions as an enterprise developer to determine what the best model for declaring transactions is for your components, as well as perhaps being useful for creating standalone distributed enterprise applications.

In this chapter, you will learn:

  • The concept of transactions and the problems encountered by distributed objects with transaction management.

  • How transaction services solve the problems encountered by distributed objects with transactions.

  • The CORBA Object Transaction Service as a standard distributed transaction service solution.

  • The Java Transaction API for specifying local Java interfaces between a transaction manager and the various distributed entities involved in a transaction.

  • The JTA high-level transaction manager interface for allowing an application server to control the boundaries of an application under control of an application server.

  • The JTA high-level application interface that allows a transaction-savvy application to delineate transaction boundaries.

  • The JTA mapping of the X/Open XA standard protocol that enables a resource manager to take part in a transaction controlled by an external transaction manager.

  • The Java Transaction Service for implementation of the OTS via a Java mapping, as well as the implementation of a Transaction Manager supporting the JTA specification.

  • The latest developments with Web service transaction standards and the Java APIs, such as JAXTX, that are being created to encapsulate such standards.

Transactions

Recall from Chapter 2 in the discussion of transactions that we covered ACID principles. ACID stands for Atomicity, Consistency, Isolation, and Durability. Guaranteeing that your enterprise system adheres to the ACID principles is an important first step in understanding the need for transactions

Atomicity for a collection of operations can be very important for enterprise
applications. For example, as illustrated in Figure
14.1, our BeeShirts.com application may desire to place a customer's
order with a particular T-shirt supplier. The customer's order and associated
credit-card information may then be used to charge the customer's account.
If for some reason the order cannot be placed (for example, an item is out of
stock), we would not want to charge the customer's account. Likewise, if
for some reason the customer's account could not be charged (for example,
the customer exceeded his maximum credit), we would not want to place the order
with the supplier. Some means for treating these individual operations as an
atomic and inseparable operation need to be provided. In enterprise applications,
much more complicated requirements for atomicity can exist when many individual
operations can have such a codependence.


Figure 14.1

Transaction atomicity.

Consistency of system state is also important for enterprise applications.
As shown in Figure 14.2, the placement of
an order without the charging of an order can lead to the display of inconsistent
information. It could be particularly troublesome to a customer visiting your
e-commerce site if she sees that her account has been charged for an order that
does not exist. Similarly, it could be particularly troublesome to the e-commerce
storefront owner to discover that an order has been placed with one of his suppliers
but that a customer was never charged. Thus, consistency of system state is
a key requirement for your applications. This involves making sure that state
embedded in different distributed objects and database elements is consistent.


Figure 14.2

Transaction consistency.

The isolation of dependent operation changes to the system should be restricted
to the application inducing the operations. Figure
14.3 illustrates the case in which an application Bar does not
see the effect of a placed order by an application Foo until the changes
can be committed by Foo. Isolation of change is thus important to present
a consistent and accurate view of the system to other applications. Applications
like Bar can then see changes only when they are committed.


Figure 14.3

Transaction isolation.

Finally, Figure 14.4 depicts the need for
ensuring durability or dependability of system state changes. If a failure occurs
during the processing of operations before a change can even be committed or
rolled back, a certain level of assurance must be provided that the system will
still remain in a stable state when it comes back online. Durability of a system
ensures that the system still behaves appropriately even in the event of system
failure during the processing of inseparable operations.


Figure 14.4

Transaction durability.

A transaction, as depicted in Figure 14.5,
is a sequence of processing steps that either must all take place or must have
no individual step take place at all. We can commit the transaction and make
it permanent when all steps occur as an inseparable operation. When no steps
are allowed to occur because one or more steps failed, we say that the transaction
must be rolled back to the original system state. By building your enterprise
systems with transactions, you can guarantee that your system follows the ACID
principles.


Figure 14.5

Transactions.

Distributed transactions are particularly important for enterprise applications.
Transactions may need to encapsulate operations that affect the state of the
system where the elements making up the state reside in multiple distributed
system locations as illustrated in Figure 14.6.
Such a distributed system state may rest in a database or perhaps within another
enterprise resource such as a distributed communications server.


Figure 14.6

Distributed transaction state.

Transactions may also need to encapsulate operations invoked by different distributed
applications as illustrated in Figure 14.7.


Figure 14.7

Distributed transaction applications.

Transaction Services Overview

Guaranteeing that your enterprise applications employ transactions and adhere to ACID principles can require a lot of hand-coding overhead. It is true that you could conceivably identify every scenario in your system in which a collection of operations must occur within a transaction and subsequently write code to commit or rollback depending on the outcome of processing. For a few simple transactional scenarios, this may be a reasonable approach. However, for even moderately more complex applications, the number of transaction scenarios and number of operations per transaction scenario add a significant burden to your set of programming tasks and keep you from focusing on application logic.

Furthermore, the large-scale distribution of both application and state in an enterprise system mandates a need for sophisticated distributed transaction management services. The heterogeneity of platforms on which these applications run can further complicate matters as you strive to implement a standard distributed transaction processing methodology. As we saw in Chapter 2, standards such as the X/Open Distributed Transaction Processing Model (as shown in Figure 2.2) provide a common framework within which transactions may operate in a heterogeneous distributed environment. The standard propagation of transaction context information between distributed applications enables a standard mechanism within which distributed transaction applications may operate.

Transaction services are middleware services that facilitate the provision of transaction semantics and ACID principle behavior for your enterprise applications. Transaction services provide an API for programmers to use that enables them to encapsulate which operations should be contained within a transaction. J2EE relies on an underlying transaction service infrastructure with an exposed programmatic interface and also provides a means to declaratively define transactional semantics for enterprise components using separate descriptor files, as you'll see later in this book.

Transaction Attributes

Declarative programming of transactions involves defining transaction attributes for components or their individual operations. The container then manages transactional processing for the component by using an underlying transaction service. J2EE enables the declaration of transactional attributes for application components such as Enterprise JavaBeans (EJB). These are the latest standard transaction attribute classifications defined by the J2EE, with older EJB standard style analogues shown in parentheses:

  • Required (TX_REQUIRED): The component is required to operate inside of a transaction. If the calling client provides a transaction context within which the component operation is invoked, that transaction context is used. Otherwise, the container environment will provide a new transaction context within which the operation runs and will then attempt to commit the transaction when the operation completes.

  • RequiresNew (TX_REQUIRES_NEW): The container creates a new transaction when the component is invoked and attempts to commit the transaction when the operation completes. Any transactions that were propagated by the calling client will be suspended and then resumed when the operation completes.

  • NotSupported (TX_NOT_SUPPORTED): The container will not support the operation of a component within a transaction context. Any transaction context that was propagated by the calling client will be suspended and then resumed when the operation completes.

  • Never (some TX_BEAN_MANAGED similarities): The container requires that the client does not propagate a transaction context for use with the invoked component operation. Otherwise, an exception will be thrown. In such cases, the component may manage its own transaction programmatically.

  • Supports (TX_SUPPORTS): The container itself will not create any new transaction context within which the component may operate. However, any transaction context that was propagated by the calling context can be used with the called component. That is, the operation of the component will process within the context of the propagated transaction.

  • Mandatory (TX_MANDATORY): The container requires that the client propagate a transaction context for use with the invoked component operation. Otherwise, an exception will be thrown.

Transaction Isolation Levels

Transaction services also allow for the specification of isolation levels. The isolation level defines how and when changes made to data within a transaction are visible to other applications accessing that data. Isolation levels range from rigidly restricting visibility of changes to not limiting visibility of changes at all. We defined and introduced the concept of isolation levels in Chapter 6 in the context of JDBC updates to databases. However, because isolation levels can also apply to concurrent transactions involving general back-end enterprise information systems (EISs) and messaging services, we redefine transaction isolation levels here to incorporate the broader definition of transactions:

  • TRANSACTION_NONE: Transactions are not supported at all when identified by this isolation level.

  • TRANSACTION_READ_UNCOMMITTED: This level allows other transactions to see state changes made by this transaction before a commit has been issued.

  • TRANSACTION_READ_COMMITTED: This level does not allow other transactions to see state changes made by this transaction until a commit has been issued (that is, does not allow "dirty reads"). Also sometimes referred to as ReadCommitted.

  • TRANSACTION_REPEATABLE_READ: In addition to TRANSACTION_READ_ COMMITTED level support, this level also does not allow a transaction to read data more than once and observe different data values because some other transaction made state changes to that data in the meantime (that is, does not allow "nonrepeatable reads" or "dirty reads"). Also sometimes referred to as RepeatableRead.

  • TRANSACTION_SERIALIZABLE: In addition to TRANSACTION_REPEATABLE_READ level support, this level does not allow a transaction to read a collection of data more than once and as constrained by a particular predicate condition. It also does not allow a transaction to observe newly added data because some other transaction added data satisfying the same predicate condition in the meantime (that is, does not allow "phantom reads," "nonrepeatable reads," or "dirty reads"). Also sometimes referred to as Serializable.

Transaction Models

Transaction services can also support different models for encapsulating operations in a transaction. Simple transactions need to simply define the beginning of a transaction at some stage of processing and then conclude with either committing or aborting (that is, rolling back) the transaction. More complicated models of transaction processing also exist, however. The primary models for transaction processing are illustrated in Figures 14.8 through 14.10.

The flat transaction model depicted in Figure
14.8 relies on simple begin, commit, and abort functionality of a transaction
service. A transaction context is created by a transaction service and encapsulates
all operations until the transaction is committed or aborted.


Figure 14.8

The flat transaction model.

The chained transaction model depicted in Figure
14.9 allows for one to persistently save a portion of the work accomplished
up until a certain point. Rollback to the beginning of the chained transaction
is allowed if the chained transaction follows the "saga model."


Figure 14.9

The chained transaction model.

The nested transaction model depicted in Figure
14.10 allows transactions to be nested within other transactions. A nested
subtransaction can be committed or aborted individually. Thus, complex transactions
can be decomposed into more manageable subtransactions. Subtransactions can
commit or rollback without requiring the entire transaction to commit or rollback.


Figure 14.10

The nested transaction model.

X/Open Distributed Transaction Processing Standard

Chapter 2 described the standard X/Open Distributed Transaction Processing (DTP) model utilized by the Java transactions architecture for providing a standard distributed transaction processing framework (see Figure 2.2). An X/Open resource manager (RM) is used to describe a management process for any shared resource but is most often used to mean a DBMS. The X/Open transaction manager (TM) is the module responsible for coordinating transactions among the various distributed entities. A TX interface between application programs and TMs enables applications to initiate the begin, commit, and rollback of transactions, as well as to obtain the status of transactions. RMs participate in distributed transactions by implementing a transaction resource interface (XA) to communicate information needed by TMs for coordinating transactions.

TMs are often configured to manage a particular domain of distributed RMs and applications. Communication resource managers (CRMs) provide a standard means for connecting distributed transaction managers to propagate transaction information between different transaction domains for more widely distributed transactions. The standard interface between TMs and CRMs is defined by an XA+ interface, whereas communication resource manager to application program interfaces are defined by three interfaces known as TxRPC, XATMI, and CPI-C.

Two-Phase Commit Protocol

A TM can guarantee that all steps in a distributed transaction are atomically completed using information from the distributed RMs. A TM accomplishes this using a two-phase commit protocol. The two-phase commit protocol helps guarantee ACID principles by ensuring that all RMs commit to transaction completion or rollback to an original state in the event of a failure. These are the two-phase commit protocol steps:

  • Phase One—Commit Preparation: A prepare for commit message is first sent to each resource manager (for example, DBMS) with updated data involved in a transaction. Each resource manager then persists a description of the updates it has made within the context of the current transaction. Resource managers can also opt to abort the transaction at this stage, and then the whole transaction can be aborted by the transaction manager.

  • Phase Two—Actual Commit: If the transaction was not aborted, the transaction manager will send a commit message to all resource managers involved in the transaction. The resource managers will then commit their updates.

Object Transaction Service

The CORBAservice known as the Object Transaction Service (http://www.omg.org/cgi-bin/doc?formal/00-06-28) defines interfaces to implement transactional behavior for distributed CORBA objects. Distributed CORBA objects can participate in transaction via an ORB and the OTS. The OTS supports both flat and nested transactions. Because OTS relies on the X/Open DTP standard, non–CORBA-based applications can also interoperate with OTS. OTS is defined primarily in the org::omg::CosTransactions module, but an auxiliary org::omg::CosTSPortability module also defines two interfaces defined for portable transaction context propagation.

OTS currently represents perhaps the only CORBAservice that has been wholeheartedly adopted by the J2EE distributed computing services paradigm. As you'll see later in the chapter, the Java Transaction Service (JTS) is simply a Java mapping of the OTS. At the time of this writing, the OTS and JTS were not required by J2EE vendors to be implemented as a means for providing transactional interoperability between J2EE servers. However, the J2EE specifications do recommend that J2EE vendors support OTS and JTS for more greater interoperability and suggest that such support may be mandatory in a future specification.

Core OTS Types

As with other CORBA specifications, the OTS depends on a set of fundamental
types. Two IDL enum types and three IDL struct types define
the most important types defined in the CosTransactions IDL module.
The Java mapping for these types is depicted in Figure
14.11. The five types of interest are listed here:

  • Status: Status is an IDL enum that identifies the various states of a transaction.

  • Vote: Vote is an IDL enum that identifies the responses from resource managers after the commit preparation phase (Phase One) of a two-phase commit protocol.

  • otid_t: otid_t is an IDL struct that is a transaction identifier. It is based on the X/Open notion of a transaction ID referred to as XID.

  • TransIdentity: TransIdentity is an IDL struct that encapsulates a handle to a transaction. A TransIdentity has an otid_t transaction identifier as well as a handle to its transaction coordinator and terminator.

  • PropagationContext: PropagationContext is an IDL struct that encapsulates transaction context information to be propagated between distributed entities involved in a transaction. A transaction timeout and current transaction identity are part of the context. A sequence of parent transaction identities in a nested transaction can also be included. Implementation-specific data can also be added to a propagation context.


Figure 14.11

Basic OTS types.

OTS Interfaces

The primary OTS interfaces involved in encapsulating access to transactional
objects, resources, and their coordination are shown in Figure
14.12. A transaction coordinator manages communication with transactional
objects and resources that participate in transactions. Each interface of Figure
14.12 is described here:

  • TransactionalObject: This marker interface is implemented by those objects that want to participate in a transaction. An ORB will automatically propagate the transaction context of a client thread when a method on a TransactionalObject implementation is invoked.

  • Synchronization: The Synchronization interface is used to notify TransactionalObject instances before a commit is prepared (that is, before_completion()) and after a commit or rollback operation is performed (that is, after_completion()) during a two-phase commit protocol.

  • Resource: The Resource interface is implemented by resources that participate in a two-phase commit protocol.

  • SubtransactionAwareResource: This sub-interface of the Resource interface is implemented by resources that participate in a two-phase commit protocol that employs a nested transaction model.

  • Coordinator: The Coordinator interface can be used to create transactions and manage their behavior, obtain transaction status and information, compare transactions, register resources and synchronization objects, and create subtransactions in a nested transaction.

  • RecoveryCoordinator: When a Resource is registered with the Coordinator, a RecoveryCoordinator handle is returned to enable the handling of certain recovery scenarios. The resource can ask the coordinator to replay the transaction completion sequence if it did not receive a transaction completion request within a certain transaction timeout.


Figure 14.12

OTS coordination, resource, and transactional object interfaces.

Figure 14.13 depicts those OTS interfaces
used to create and manage transactions. We have already described the Coordinator
interface, but the interfaces that rely on the Coordinator interface
are also shown here. APIs such as the Current interface can be utilized
by application programs to manage transactions at a higher level. The transaction
management interfaces depicted in Figure 14.13
are described here:

  • Terminator: A Terminator interface is used to commit or rollback a transaction. Thus, although a transaction may have been created by another application, this interface provides a mechanism to terminate the transaction from another application.

  • Control: The Control interface provides a handle to manage a transaction context that can be propagated between applications. Can return a handle to a transaction coordinator or terminator to accomplish these tasks.

  • Current: Current is a frontline IDL interface for applications to use when creating transactions. Current provides operations to begin, commit, rollback, suspend, and resume transactions. The status of a transaction can also be obtained from the Current object. The current transaction context can be obtained from the initial ORB references.

  • TransactionFactory: A transaction can also be created with a TransactionFactory. Operations exist to create a new transaction with a particular timeout value and to re-create an existing transaction given a propagation context.


Figure 14.13

OTS transaction creation and management interfaces.

Java Transaction API

The Java Transaction Architecture (JTA) specifies standard interfaces for Java-based
applications and application servers to interact with transactions, transaction
managers, and resource managers (http://java.sun.com/products/jta/).
The JTA model follows the basic X/Open DTP model described earlier in this chapter
and in Chapter 2, as depicted in Figure 2.2. The main components of the JTA
architecture are shown in Figure 14.14. The
JTA components in this diagram are defined in both the javax.transaction
and the javax.transaction.xa packages. Three main interface groupings
of the JTA are also shown, including JTA transaction management, JTA application
interfacing, and JTA XA resource management. The relation to the Java Transaction
Service (JTS) is also shown in this diagram.


Figure 14.14

The JTA architecture.

JTA transaction management provides a set of interfaces utilized by an application server to manage the beginning and completion of transactions. Transaction synchronization and propagation services are also provided under the domain of transaction management. The JTA Transaction, TransactionManager, Synchronization, and Status interfaces all belong to the realm of JTA transaction management. An application server will typically implement a container environment within which enterprise application components can run and utilize the services of transaction management.

An application server environment such as J2EE can provide a declarative model for applications to utilize transaction management services. JTA application interfacing also provides a programmatic interface to transaction management for use by applications. An application uses the UserTransaction interface for this very purpose.

The X/Open XA resource management interface provides a standard means for transaction managers to interact with resources (for example, a DBMS) involved in a distributed transaction. A resource adapter, such as JDBC, implements the XAResource interface that is also used by an application server environment.

Finally, the Java mapping of OTS known as the JTS provides a lower-level interface to a distributed transaction service. A JTS implementation will propagate transaction context to other transaction managers via standard X/Open communications resource manager interfaces.

The JTA interfaces are required as a part of the J2EE and thus JTA application interfaces must be implemented by J2EE server products. No specific protocol for transaction propagation interoperability across J2EE servers has been defined. However, the J2EE v1.4 standards indicate that a future version of the J2EE specification will require OTS-based interfaces and therefore require standard protocol interoperability via IIOP.

JTA Transaction Manager Interface

The JTA supports a standard interface to transaction management services. An
application server accesses these services primarily through the TransactionManager
and Transaction interfaces. Figure 14.15
depicts these interfaces and two other key JTA interfaces utilized by an application
server to interact with an underlying transaction manager.


Figure 14.15

JTA transaction management.

The Status interface defines a set of static constants that indicate the state of a transaction. The Synchronization interface is provided to enable notification before a commit is prepared (that is, beforeCompletion()) and after a commit or rollback operation is performed (that is, afterCompletion()). A call to Transaction.registerSynchronization() can register a Synchronization object with a transaction associated with a current thread so that the beforeCompletion() and afterCompletion() calls can be made by a transaction manager.

The Transaction interface, as the name implies, encapsulates a transaction. A Transaction is created by a transaction manager and enables operations to be invoked on a transaction that is associated with a target transactional object. A Transaction object can be told to commit or rollback by invoking the methods commit() or rollback(), respectively. A Transaction object can also be told to only enable rollbacks (that is, and no commits) to be performed on a transaction using the setRollbackOnly() call. The constant Status of a transaction can be obtained via a call to Transaction.getStatus(). You'll learn more about the enlistResource() and delistResource() methods in a subsequent section.

The TransactionManager interface is used by an application server to manage transactions for a user application. The TransactionManager associates transactions with threads. The methods begin(), commit(), and rollback() on a TransactionManager are called by an application server to begin, commit, and rollback transactions for a current thread, respectively. The TransactionManager also supports a setRollbackOnly() method to designate the fact that only a rollback will be supported for the current thread's transaction. A setTransactionTimeout() method also defines a timeout for a transaction in terms of seconds, and a getStatus() method returns the static constant Status of the current thread's transaction.

A handle to the current thread's transaction can be obtained by calling TransactionManager.getTransaction(). By calling TransactionManager.suspend(), you can suspend the current transaction and also obtain a handle to the Transaction object. The TransactionManager.resume() method can resume the current transaction.

JTA Application Interface

The JTA application interface consists of the javax.transaction.UserTransaction
Java interface, which is of most importance to an enterprise Java application
developer. UserTransaction is used by an application to control transaction
boundaries. Figure 14.16 depicts this interface
and the relation between it, an application, and the underlying JTA transaction
management architecture.


Figure 14.16

JTA user application interfacing.

The UserTransaction.begin() method can be called by an application to begin a transaction that gets associated with the current thread in which the application is running. An underlying transaction manager actually handles the thread to transaction association. A NotSupportedException will be thrown by the begin() call if the current thread is already associated with a transaction and there is no capability to nest the transaction.

The UserTransaction.commit() method terminates the transaction associated with the current thread. The UserTransaction.rollback() method induces an abort of the current transaction associated with the current thread. With a call to UserTransaction.setRollbackOnly(), the transaction associated with the current thread can only be aborted.

A timeout associated with the transaction can be set by calling UserTransaction.setTransactionTimeout() with an int value in seconds. Finally, the constant Status of a transaction can be yielded from the UserTransaction.getStatus() call.

J2EE application server components (that is, Enterprise JavaBeans) by and large can rely on the declarative and container-managed transaction semantics, but they also utilize the UserTransaction interface if it is desired to have the component programmatically manage its own transactions. Java Web components (that is, Java Servlets and JavaServer Pages) can also utilize the UserTransaction interface to demarcate transactions. Java Web components may look to using the UserTransaction interface directly when there is not an Enterprise JavaBeans tier involved with managing transactions or if the business logic for a particular set of transactional related actions are embedded directly within the Java Web components themselves. A handle to a UserTransaction may be gotten from a JNDI lookup or directly from the container environment in the case of Enterprise JavaBeans.

For example, you might retrieve the UserTransaction via JNDI using this:

UserTransaction trans
  = (UserTransaction) jndiContext.lookup("java:comp/UserTransaction");

Or an EJB may obtain the UserTransaction directly from the container context using this:

UserTransaction trans = containerContext.getUserTransaction();

The transaction can then be demarcated programmatically using this:

trans.begin();

// Do some work...

// rollback if there is an issue...
trans.rollback();

// commit if all was ok...
trans.commit();

JTA and X/Open XA

The XA interface defined by the X/Open group (http://www.opengroup.org)
specifies the interface to distributed resource managers as accessed by distributed
transaction managers in the X/Open standard DTP model. The JTA encapsulates
this interface using the XAResource and Xid interfaces depicted
in Figure 14.17. The XAResource
interface is utilized by a transaction manager to manage distributed transactions
among resources.


Figure 14.17

JTA resource management interfaces.

The Xid interface is an identifier for a distributed transaction specified in X/Open standard parlance. The standard X/Open format identifier, global transaction identifier bytes, and branch identifier bytes may all be retrieved from the Xid interface. Additionally, two static constants define characteristics of a transaction.

The XAResource interface is a Java mapping of the standard X/Open interface between a transaction manager and a resource manager. A resource manager's resource adapter must implement the XAResource interface to enable a resource to participate in a distributed transaction. A sample resource manager is a DBMS and a sample resource adapter is the JDBC interface to a DBMS. A transaction manager obtains an XAResource handle for every resource that participates in a distributed transaction.

The XAResource.start() method is used to associate a distributed transaction with a resource. In addition to the Xid, one of the XAResource static constant flags TMJOIN, TMRESUME, or TMNOFLAGS is used to, respectively, indicate whether the caller is joining an existing transaction, the caller is resuming a suspended transaction, or no flags are to be set. The XAResource.end() method is called to disassociate the resource from the transaction. In addition to an Xid, the end() call uses a flag TMSUSPEND, TMRESUME, TMFAIL, or TMSUCCESS to, respectively, indicate whether the transaction is suspended, is resumed, is to be rolled back, or is to be committed. The XAResource also provides methods to commit, prepare for a commit, rollback, recover, and forget about distributed transactions. The transaction timeout can also be set and retrieved from the XAResource.

Java Transaction Service

Figure 14.18 presents the system context
in which the JTS architecture operates. JTS (http://java.sun.com/products/jts/)
is a Java mapping of the OTS. Therefore, the JTS API is by and large defined
by the org.omg.CosTransactions and org.omg.CosTSPortability
packages. Java-based applications and Java-based application servers access
transaction management functionality via the JTA interfaces. The JTA interacts
with a transaction management implementation via JTS. Similarly, the JTS can
access resources via the JTA XA interfaces or can access OTS-enabled non-XA
resources. JTS implementations can interoperate via CORBA OTS interfaces. JTS
supports a flat transaction model. JTS can support, but is not required to support,
a nested transaction model.


Figure 14.18

The JTS system context.

There is no specified mechanism for an OTS-based transaction manager and an ORB to locate one another. The javax.jts.TransactionService interface is provided to facilitate a transaction manager and an ORB being able to locate one another, and is the only non-OTS standard interface defined by JTS.

The TransactionService.identifyORB() method is called by an ORB during initialization to let a transaction manager be aware of the ORB identity and attributes. The TSIdentification interface defined as an extension to the standard CORBA framework by the OTS is used by a JTS implementation to register Sender and Receiver objects with an ORB. Sender objects are registered with an ORB during initialization so that the ORB can issue a callback on the transaction service during the propagation of a transaction context from the transaction service. Receiver callback objects are also registered with the ORB to receive propagated transaction contexts. A Sender can also receive context propagation replies, and a Receiver can send propagation replies.

Web Services Transactions

In a Web services environment, many remote Web services communicate in a loosely coupled and widely distributed environment. Although use of OTS is the current recommended means by the J2EE standards for enhancing the interoperability of transaction context propagation, OTS and its dependence on IIOP are catered more for closely coupled albeit distributed environments. Furthermore, the strict adherence to ACID principles by mechanisms such as OTS do not map well to all Web service communication scenarios. Because of these reasons, a new set of standards needs to be crafted for the broader transaction interoperability needs of Web services.

The bad news is that at the time of this writing, there was no widely adopted standard means for incorporating transaction context into Web service communications. However, standards bodies such as the W3C and OASIS were working toward defining such a standard. Their aim is to ensure that the needs of Web services are met to enable loosely coupled transactional behavior as well as both strict and relaxed requirements for adhering to ACID principles. The good news is that there is a Java Specification Request (JSR) that is actively working on the incorporation of such standards into Java-based Web services when such standards become final.

The XML Transactioning API for Java (JAXTX), http://www.jcp.org/en/jsr/ detail?id=156, is being created to define a standard Java API for creating, parsing, and exchanging transactional information in a Web services communication paradigm. Thus, JAXTX largely focuses on defining how standard transaction context information can be read from and written to SOAP message headers. The JAXTX specification members are closely in tune with the W3C and OASIS standards bodies that are defining the general way for encapsulating transactional information inside of SOAP message headers. When such standard bodies converge on a solution, the intention is that JAXTX will incorporate such standards.

Additionally, another JSR called is being created and intended to be utilized by JAXTX to further broaden the scope for how transactions are managed in loosely coupled distributed environments. The J2EE Activity Service for Extended Transactions, http://jcp.org/en/jsr/detail?id=9, is being created to provide Java support for the OMG's Activity Service standard (http://cgi.omg.org/cgi-bin/doc?orbos/2000-06-19), which is an extension to the OTS. Such a standard and associated Java API will provide support for allowing long-running business transactions to be implemented more efficiently. That is, if a transaction spans a long amount of time and perhaps crosses multiple system boundaries, such as can be the case for Web services, then a more efficient means is needed to decompose the transaction into shorter running transactions. This is accomplished to prevent the locking up of all involved resources for the entire duration of the long-running transaction.

So stay tuned to the Web sites mentioned previously and keep an eye out for when a standard means for Web service transaction context propagation is defined and for when the Java APIs implementing such standards become available.

Conclusions

The need for transaction semantic support in distributed enterprise applications very frequently arises in the context of managing transactions that involve DBMS resources. There is a distinct and standard model for providing transaction service support to Java enterprise applications. The transaction services model available to Java enterprise applications revolves around the standard CORBA OTS and X/Open DTP models. The OTS is a CORBAservice for transactions, and the JTS is the Java mapping of this standard model. The JTA defines standard interfaces with the OTS/JTS, between applications and the transaction service, between transaction managers and application servers, and between transaction managers and X/Open XA–compliant resource managers. Finally, a set of standards and associated Java APIs are now brewing to enable interoperability in the Web services world.

Transaction services in Java are thus one of the J2EE components perhaps most in sync with other industry-standard transaction models. Because transaction services are one of the core components of a middle-ware architecture, many vendors will be able to better support the J2EE standard. Furthermore, interoperability with other DTP frameworks is better enabled. As you'll discover later in the book, interfacing with such transaction services is tremendously simplified for the application programmer when the J2EE declarative model for component transaction specification is used.

About the Authors

Paul J. Perrone is the Founder, President, and CTO at Assured Technologies, Inc. Through Assured Technologies (www.assuredtech.com), Paul provides software architecture and development consulting, mentoring, and training related to J2EE, XML, Web services, and object-oriented technologies. Paul has been involved with the architecture, design, and development of numerous large-scale enterprise systems and products for both Fortune 500 and medium-sized organizations. Paul also has co-authored Building Java Enterprise Systems with J2EE and the Java Security Handbook, has published articles on Java, and has spoken at conferences such as JavaOne and Web Services Edge. He has an MS from the University of Virginia and a BS from Rutgers University. He is a member of the IEEE and ACM, has served as chapter chair for the Northern Virginia IEEE Computer Society, has helped in the startup of the Northern Virginia Java User’s Group (NOVAJUG), and chairs the NOVAJUG’s enterprise SIG. Paul is also an avid Java-based robot and AI tinkerer. Paul can be reached at pperrone@assuredtech.com.

Venkata S. R. “Krishna” R. Chaganti is a senior software-engineering consultant and has been developing commercial applications software for the past 12 years. Krishna has cross-platform background in designing and developing Internet-based distributed systems across wide range of technologies, including DCE, CORBA, EJB, Web Services using Java and C/C++ programming languages. Krishna’s experience also includes development of GUI based applications using Swing, JSP, Servlets, etc. Krishna has also been teaching and speaking Java and related technologies for five years. He has an MSEE in Computer Engineering and an MSEE in Electrical Engineering from the University of Alabama in Huntsville. He also has a B.Tech in Electronics and Communications Engineering from Nagarjuna University, A.P., India. Krishna can be reached at chaganti@erols.com.

Tom Schwenk is a Senior Software Consultant with Assured Technologies, Inc. Since 1995, he has been working with Java, specializing in highly scalable, distributed application design and development. He has been involved in the design and implementation of Java enterprise and e-commerce applications for both Fortune 500 and smaller size companies. He holds a BS in Electrical Engineering and an ME in Biomedical Engineering, both from the University of Virginia. Tom can be reached at tschwenk@assuredtech.com.

Source of this material

This material is from Chapter 14, Transaction Services with JTA and JTS , from the book J2EE Developer’s Handbook (ISBN: 0-672-32348-6) written by Paul J. Perrone, Venkata S.R. “Krishna” R. Chaganti, and Tom Schwenk, published by Sams Publishing.

To access the full Table of Contents for the book


Other Chapters from Sams Publishing:

Web Services and Flows (WSFL)

Overview of JXTA

Introduction to EJBs

Processing Speech with Java

P2P Dynamic Networks


Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories