In the 1th installment of this series on business, we talked about the basics, including what transactions are and why transactions are critical to building reliable, distributed applications. In this section, we'll explore how to build a Java application into a transaction, and how JTS and Java-ee containers try to make transactional services (including transaction partitioning, resource expropriation, and transactional propagation) virtually invisible to component programmers. Please click on the discussion at the top or bottom of the article to share your thoughts on this article with the author and other readers in the discussion forum.
In the 1th part of this series, we discussed transactions and studied their basic properties-atomicity (atomicity), consistency (consistency), isolation (isolation), and persistence (durability). Transactions are an essential component of an enterprise application, and without them, it is almost impossible to build a fault tolerant enterprise application. Fortunately, the Java Transaction service (Java Transaction service,jts) and the EE container automatically do a lot of transaction management work for you, so you don't have to integrate the transaction consciousness directly into the component code. The result is simply a trick--by following a few simple rules, the Java application can automatically obtain transactional semantics with little or no additional component code. This article aims to uncover the mysteries of this magic by demonstrating how transaction management takes place and where it occurs.
What is JTS?
JTS is a component transaction monitor (component transaction). What does that mean? In the 1th part, we introduced the concept of Transaction Monitor (TPM), a program that represents applications that coordinate the execution of distributed transactions. The TPM has the same length of time as the database; In the late 60, IBM first developed CICS, which is still being used by people. The classic (or programmatic) TPM management is programmed to define transactions for the sequence of operations for transactional resources such as databases. With the advent of distributed object protocols such as CORBA, DCOM, and RMI, people want to see a more object-oriented outlook for transactions. Informing an object-oriented component of transactional semantics requires extending the TPM model--in which transactions are defined by the calling method of a transactional object. JTS is just a component transaction monitor (sometimes referred to as Object Transaction Monitor), or CTM.
The transaction support design of JTS and Java EE is greatly influenced by CORBA object transaction Service (CORBA objects Transaction service,ots). In fact, JTS implements OTS and acts as the Java Transaction API (Java Transaction API)-an interface between low-level api― and OTS that define transaction boundaries. Using OTS instead of creating a new object Transaction protocol follows the existing standards and enables Java EE and CORBA to be compatible with each other.
At first glance, the shift from a programmatic transaction monitor to a CTM seems to be just a change in the terminology name. However, the difference is more than that. When a transaction is committed or rolled back in CTM, all changes made by the object associated with the transaction are committed or canceled together. But how does CTM know what the object did during the transaction? Transactional components such as EJB components do not have a commit () or rollback () method, nor do they register themselves with the transaction monitor. So how does the operation of the Java EE component become part of the transaction?
Transparent expropriation of resources
When application state is manipulated by a component, it is still stored in transactional resource managers (for example, databases and Message Queuing servers) that can be registered as resource managers in a distributed transaction. In the 1th part, we discussed how to enlist multiple resource managers in a single transaction, and how the transaction manager coordinates these resource managers. The resource manager knows how to associate changes in application state with a particular transaction.
But this only shifts the focus of the problem from the component to the resource Manager-how does the container determine what resources are relevant to the transaction and can be requisitioned for it? Consider the following code, which you might find in a typical EJB session bean:
Listing 1. Transparent resource requisition for transactions managed by the Bean
InitialContext ic = new InitialContext();
UserTransaction ut = ejbContext.getUserTransaction();
ut.begin();
DataSource db1 = (DataSource) ic.lookup("java:comp/env/OrdersDB");
DataSource db2 = (DataSource) ic.lookup("java:comp/env/InventoryDB");
Connection con1 = db1.getConnection();
Connection con2 = db2.getConnection();
// perform updates to OrdersDB using connection con1
// perform updates to InventoryDB using connection con2
ut.commit();
Note that the code for JDBC connections in the current transaction is not enlisted in this example-the container will complete this task for us. Let's take a look at how it happened.