In a simple Java application that interacts with a database management system (DBMS), the application can demarcate transaction boundaries using explicit SQL commits and rollbacks. A more sophisticated application environment, with multiple transactional resources distributed across a network, requires a dedicated component to manage the complexity of coordinating transactions to completion.
A transaction manager works with applications and application servers to provide services to control the scope and duration of transactions. A transaction manager also helps coordinate the completion of global transactions across multiple transactional resource managers (e.g., database management systems), provides support for transaction synchronization and recovery, and may provide the ability to communicate with other transaction manager instances.
Two separate but interconnected Java specifications pertain to the operation and implementation of Java transaction managers. These are detailed in the next sections.
|Transaction Manager versus TP Monitor|
|Transaction processing (TP) monitors, such as CICS and IMS/DC, enhance the underlying operating system's scalability and its ability to manage large transaction volumes, by taking on some of the roles of the underlying operating system. For example, a TP monitor, in addition to managing transactions, also performs connection pooling and task/thread pooling and scheduling. Transaction management is only one function of a TP monitor. In today's J2EE environment, application servers perform a similar function and may be thought of as modern equivalents of TP monitors.|
Two-Phase Commit and Global Transactions
Global transactions span multiple resource managers. To coordinate global transactions, the coordinating transaction manager and all participating resource managers should implement a multiphased completion protocol, such as the two-phasecommit (2PC) protocol (Figure 1). Although there are several proprietary implementations of the this protocol, X/Open XA is the industry standard. Two distinct phases ensure that either all the participants commit or all of them roll back changes.
Two phase commit and Global transactions
Figure 1 The two-phase commit protocol
During the first, or prepare phase, the global coordinator inquires if all participants are prepared to commit changes. If the participants respond in the affirmative (if they feel that the work can be committed), the transaction progresses to the second, or commit phase, in which all participants are asked to commit changes.
The two-phase commit protocol ensures that either all participants commit changes or none of them does. A simplified explanation follows of how this happens in a typical transaction manager. To keep the discussion brief, we examine only a few failure scenarios. Once a transaction starts, it is said to be in-flight. If a machine or communication failure occurs when the transaction is in-flight, the transaction will be rolled back eventually.
In the prepare phase, participants log their responses (preparedness to commit) to the coordinator, and the state of the transaction for each participant is marked in-doubt. At the end of the prepare phase, the transaction is in-doubt. If a participant cannot communicate with the global coordinator after it is in the in-doubt state, it will wait for resynchronization with the coordinator. If resyn-chronization cannot take place within a predefined time, the participant may make a heuristic decision either to roll back or commit that unit of work. (Heuristic or arbitrary decisions taken by the participant are a rare occurrence. We emphasize this because it is a conceptual difference between current transaction models and those such as BTP, discussed later in the chapter).
During the second phase, the coordinator asks all participants to commit changes. The participants log the request and begin commit processing. If a failure occurs during commit processing at one of the participants, the commit is retried when the participant restarts.
Transactions managers can provide transactional support for applications using different implementation models. The most common is the flat transaction model. A transaction manager that follows the flat transaction model does not allow transactions to be nested within other transactions. The flat transaction model can be illustrated by examining the transaction model employed in J2EE application servers today.
As an example, Flute Bank provides a bill payment service. The service is implemented by an EJB that interacts with two other EJBs the account management EJB (to update account balance) and the check writing EJB (to write out a check to the payee).
Table 1a illustrates the scope of transactions in the scenario where all three EJBs are deployed with declarative transaction attribute of Required.
Table 1b illustrates the scope of transactions where the bill payment service EJB and account management EJB are deployed with transaction attribute Required but the check writing EJB is deployed with a transaction policy of RequiresNew. In this scenario, when the check writing EJB method is executed, the container suspends T1 and starts a new transaction, T2. Check writing occurs within the scope of the second transaction. When control returns to the bill payment EJB, T2 is committed, and the previous transaction is activated. So, in a flat transaction model, two transactions are executed in different scopes—T2's scope is not within T1's scope.