The EJB architecture implements transactions with the assistance of a transaction service (see Figure 7-2). This service operates as a central instance that takes over the coordination of all participants in a transaction.
Figure 7-2: Communication paths in EJB transactions.
The participants in a transaction are a client, one or more transactional systems, one or more beans, and the EJB container. The client is the interface to the user and generally controls the execution of the processes. The transactional systems store the data that are changed in the course of the transaction. The most frequently used transactional system is a database. The beans are normally based on the data in the transactional systems, and the consistency of their states is ensured by the transaction. The EJB container works closely with the transaction service to provide an environment for the beans that in particular supports simple dealings with transactions.
Transaction management can be taken over by the client, the bean, or even the EJB container. In the last case one speaks of declarative transactions, since the transaction management is not programmed in the application logic, but is declared only at the time of deployment by the developer and handled at run time by the EJB container. This promotes the reuse of beans, since for a single bean various transactional behaviors can be declared. This allows beans to be more easily used and reused in a variety of applications.
For transaction management it is necessary that the Enterprise Bean support the remote or local client view, or both. The discussion in this chapter applies without restriction to both cases. Therefore, in this chapter we shall make no distinction between the remote and local client views. The implementations will relate to the standard case, the remote client view.
The distribution of roles in the EJB concept determines the principles for the management and control of transactions. Transaction control is handled completely by the creator of the EJB container, and thus the bean developer is completely relieved of such responsibility. This strategy has already long been used in database systems. However, in transaction management the EJB concept goes one step further. With declarative transactions the application developer can be freed from the problems of transaction management. This task is left to the experts who have an overview of how applications work together and can thus better determine the required transactional behavior and performance metrics for optimal performance.
EJB supports distributed transactions. One speaks of a distributed transaction when several transactional objects are involved in various services (such as JMS, database, EJB container) of a transaction (see Figure 7-3).
Figure 7-3: Example of a system involved in a distributed transaction.
The various services involved in the transaction can run on the same server or on different servers. For example, in a distributed transaction, data in a number of databases can be changed in a single transaction. A transaction can affect different databases of a single EJB container or those of different EJB containers.
View consistency (isolation of transactions) is only in part the responsibility of the EJB container. In most products the consistency level can be specified in the configuration of the application server for the database connection. The application server could also provide a nonstandard service to enable the setting of the consistency level in the application logic.
Java Transaction API (JTA) and Java Transaction Service (JTS) are specifications of Sun Microsystems. JTA defines the interfaces that the participating instances of a distributed transaction need for communication. The interfaces are located at a sufficiently high level of abstraction so that they are suitable for use by application programmers.
JTS is designed for those who offer transaction services. A transaction service controls the transaction. It coordinates the functioning of transaction in cooperation with various transactional systems. JTS contains the necessary definitions for developing a transaction service that supports JTA.
JTS is the link between Java and the Object Transaction Service 1.1 (OTS). This is a standard of the OMG (Object Management Group), which defines transaction management and control with CORBA objects. JTS is a compatible subset of OTS.
The programming of the following example on transactions is based exclusively on a part of JTA. The complex mechanism of transaction management is invisible to the bean developer. Even though this quite simple interface hides the complexity, one must know the exact processes in order to write efficient programs.
In what follows we wish to give an overview of JTS. The concepts used here form the basis for the following representation of transactions by Enterprise JavaBeans. One should pay particular attention to the communication paths in the use of transactions. The complete specification of JTA and JTS can be found at the following Sun Microsystems web sites :
JTS and OTS distinguish among types of objects according to their roles in transactions. The EJB concept is also reflected in the various object types:
Transactional clients are programs that access objects on the server. They can take over the transaction management. They do not themselves store any transaction-secured data. Not all clients that work with Enterprise JavaBeans are transactional clients. With declarative transactions it is possible to decouple the client completely from the transaction management.
Transactional objects are objects on a server that take part in transactions but do not store any of their own transaction-secured data. They do not actually take over transaction management, but can force a transaction to be aborted. All Enterprise JavaBeans are transactional objects.
Recoverable objects are the objects that store the actual data. Access always proceeds in a transaction-secure manner. In the EJB model the database manages most of the recoverable objects. A recoverable object can then be a line in a database table. Moreover, other services, such as Java Messaging Service (JMS), can work with recoverable objects.
Furthermore, two fundamental types of transactions are distinguished:
Local transactions deal only with data from a single database or from another single transactional system. The transactional object can manage the coordination with an independent transaction service.
Global transactions can handle data from various databases and other transactional systems. The coordination is managed by an independent transaction service, which synchronizes the participating systems.
A method that is executed in a global transaction has a transaction context. The transaction context describes the unique identity of the transaction, its state, and possibly other attributes as well.
The transaction service coordinates all global transactions. It ensures that all operations on recoverable objects are transaction-secured. To make this possible, each object involved in a transaction must know its transaction context. The transaction service then associates the transaction context with the thread. In this way the transaction context is available to each object in the same thread.
In the case of a method call over a network or across a process boundary there is another concept that is necessary to consider. The transactional context propagation ensures that in such cases the transaction context is transmitted. The implementation is the responsibility of the application server and is usually based on an extension of the network protocol (RMI / IIOP).
Figure 7-4 shows schematically the interaction of objects involved in a transaction:
A central system, the transaction service, coordinates all transactions. It communicates directly with all objects that participate in a transaction (transactional clients, transactional objects, and recoverable objects).
At the start of a transaction the transaction context is generated by the transactional client. This contains information about the transaction and the user. In Java, the transaction context is associated with a running thread. On the one hand, this means that all actions of this thread are executed in the transaction, and on the other hand, that there can always be only one transaction per thread.
Every new transaction is registered with the transaction service. The transaction service knows the transaction context and the state of each running transaction.
During a transaction the transactional client calls, once or several times, methods of transactional objects on the server. The methods of the transactional objects, in turn, call additional methods, either of additional transactional objects or recoverable objects.
Every object that is involved in the transaction through some chain of calls must gain knowledge of the transaction context. As long as the calls remain in one system, this is no problem, since the transaction context is associated with a thread, and EJB forbids the initiation of new threads. However, if a network must be traversed, then there will be a necessary extension of the protocol, which relays, in addition to the data of the function call, the transaction context as well. This is called transactional context propagation.
Every recoverable object that participates in a transaction through a chain of calls uses the transaction context to register its data with the transaction service. It informs the transaction service about local transactions that it uses for access. In this way, the transaction service knows all the data that are involved in a running transaction.
At the end of the transaction the transactional client signals a successful conclusion (commit) or an aborting (rollback) of the transaction. If the transaction is to be successfully concluded, then all participating objects must give their consent. The transaction cannot be successfully concluded if a recoverable object experiences an error during access to its data or if a transactional system has previously set the status of the transaction to rollback only.
The transaction service coordinates the conclusion of a transaction with the two-phase-commit (2PC) protocol. It ensures that all local transactions are either successfully concluded or aborted.
Figure 7-4: JTS and EJB.
The Java Transaction API (JTA) is the client API responsible for transaction management. With JTA we are dealing with a part of the interface of the Java Transaction Service (JTS) that is relevant for regular application developers. Since this concept is not taken into account with older application servers, access via JTS must be used to some extent.
import instruction for JTA:
import instruction for JTS:
The following examples of transactions use exclusively the interface javax.transaction.UserTransaction.