Now that we have introduced the concept of a transaction and distributed transactions, let us now look at how transactions are supported and used in existing Java applications. 11.2.1 JDBC transactionsJava applications can include transactional constructs at different levels. An application interacting with a datastore using JDBC can use JDBC level transactions. A JDBC transaction is controlled by the transaction manager of the underlying datastore and is demarcated using the commit and rollback methods of the java.sql.Connection interface. For example: Connection conn =DriverManager.getConnection ("jdbc:oracle:thin:@jdo:Oracle"); conn.setAutoCommit(false); try{ Statement stmt = con.createStatement(); stmt.executeUpdate(" UPDATE USERS SET username ='corejdo' WHERE ACCOUNTID=1829 "); stmt.executeUpdate(" UPDATE ACCOUNTS set ACCOUNTTYPE=09 WHERE ACCOUNTID=1829 "); conn.commit(); }catch(Exception e){ conn.rollback(); } JDBC transactions, although simple, are not suitable for controlling transactions that span multiple application components . The connection-based demarcation is local to the component in which it is used, and the transaction context is not propagated. For distributed environments such as J2EE, a different framework is needed that caters to transactional resources in general, not just databases. This is where JTA and JTS come in. 11.2.2 JTA and JTSThe Java Transaction API (JTA) and Java Transaction Service (JTS) provide the necessary and generic framework for applications to use transactions across multiple components and datastores. The OMG Object Transaction Service (OTS) specifies how a transaction service can be implemented and the associated IDL interfaces. OTS is the transaction service used in CORBA to provide the transaction- related plumbing. JTS is the Java mapping of the IDL interfaces that defines how the service should be implemented in Java and the functionality that it must expose. Vendors (such as J2EE application server vendors ) use and provide the implementation of the JTS in their products; developers never work directly with JTS. Java Transaction API (JTA) provides the API and the standard Java interface for developers to access the facilities of a transaction service (i.e., the JTS implementation). It provides an interface for the transaction manger, which manages the underlying transaction service. The following list summarizes (and Figure 11-3 illustrates) how JTA and JTS work together:
Figure 11-3. Different entities in JTA.
The code below shows how the UserTransaction can be used in an application: UserTransaction tx =// lookup user transaction object tx.begin(); // do some work across multiple components and datastores tx.rollback(); In the above code, the reference to the UserTransaction can be obtained from the JNDI context of the J2EE application or by using the EJB context if the component is an EJB. For example: Properties p= new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY,"some.vendor.factor.class"); p.put(Context.PROVIDER_URL, "applciation serve URL); InitialContext ic = new InitialContext(p); UserTransaction tx = UserTransaction)ic.lookup("javax.transaction.UserTransaction"); //Or in EJB's UserTransaction tx = ejbContext.getUserTransaction() ; The UserTransaction is simple and is used only to mark the transactional boundary. The application code never has access to the actual Transaction object. In this sense, the UserTransaction name is a misnomer because it works as more of a user transaction manager. It does not represent a single transaction, but the application's ability to begin and commit transactions. Table 11-1 lists some of the important methods in the UserTransaction interface. Table 11-1. Methods in the UserTransaction
The interface javax.transaction.TransactionManager has methods identical to the UserTransaction with the additional ability to return the Transaction object. The TransactionManager also has two additional methods that allow the transaction to be suspended and resumed. These are listed in Table 11-2. J2EE does not mandate that a container expose the TransactionManager interface to application code (application code always works with UserTransaction ); therefore, some containers may not expose this. Typically, containers bind the TransactionManager to a specific JNDI name for their product. Table 11-2. Additional Methods in the TransactionManager
The javax.transaction.Transaction object is used by the TransactionManager as an abstraction to the actual executing transaction. Application code almost never accesses the actual Transaction object. It is here that the resource enlistment and de-enlistment takes place. Table 11-3 summarizes the methods in this interface. Table 11-3. The Methods in the javax.transaction.Transaction interface
Now that you have an overall understanding of how transactions work and how they are abstracted by JTA and JTS for use in Java and J2EE, look at how JDO deals with transactions. |