Section 16.2. Programmatic Transactions Versus Declarative Transactions


16.2. Programmatic Transactions Versus Declarative Transactions

You can approach coding transactions in two basic ways: programmatically or declaratively. When possible, declarative transactions are a better choice since they allow the container to manage the transaction for you, and this saves you from having to put JTA transaction management calls into your application code. But as we'll see, not every scenario can be adapted to use declarative transactions. We'll start by examining programmatic transaction management, then discuss how declarative transaction management can supplant some programmatic calls.

16.2.1. Programmatic Transactions

Typically, you implement transactions in an application using one of the resource-specific transaction APIs such as JDBC or JMS. If the application requires distributed transactions, you implement the transaction code using JTA.

The JTA can be used in a number of programming contexts, including web and EJB components, Swing- or SWT-based desktop clients, and many others. The application code begins a transaction and then performs some operations against one or more resource managers (databases accessed via JDBC, message servers accessed through JMS, EJB components accessed via the EJB API, etc.). At some point, the application decides to either commit or roll back the transaction. The container managing the application's runtime environment, including its transaction manager, propagates the transactional context to the different components and resources that the client directly or indirectly invokes. Figure 16-6 depicts client-managed transaction management.

The JTA exposes these capabilities to applications through the javax.transaction.UserTransaction interface. Example 16-1 illustrates client-managed transaction management in a generic client application. A JTA client acquires a UserTransaction from the transaction manager through a JNDI lookup using a standardized name, java:comp/UserTransaction. The JNDI context used has to be the same context accessed by the transaction manager handling the distributed transaction (e.g., the application server managing web or EJB components). Once the client has a UserTransaction, a transaction is explicitly started by invoking the begin( ) method of a javax.transaction.UserTransaction instance. The transaction is committed by invoking the commit( ) method and rolled back by invoking the rollback( ) method of the UserTransaction instance. The same UserTransaction reference can be used to start additional transactions if needed. If the underlying transaction manager supports nested transactions, you can begin a nested transaction by calling begin( ) on the UserTransaction before committing or rolling back the current transaction. If the transaction manager doesn't support nested transactions, attempting to create one this way will result in a javax.transaction.NotSupportedException.

Example 16-1. Client-managed transaction demarcation
 InitialContext aInitialContext = new InitialContext( ); UserTransaction aUserTransaction = (UserTransaction)     aInitialContext.lookup("java:comp/UserTransaction"); try {     aUserTransaction.begin( );     PersonHome aPersonHome = (PersonHome)       aInitialContext.lookup("java:comp/env/ejb/Person");     Person p = aPersonHome.create(aPersonValue.getEmail( ),                                   aPersonValue.getPassword( ));     p.setWorkPhone(aPersonValue.getWorkPhone( ));     p.setHomePhone(aPersonValue.getHomePhone( ));     sLogger.info(" created a person with id : " + p.getPersonId( ));     aUserTransaction.commit( ); } catch (Exception e) {     try {         aUserTransaction.rollback( );     } catch (Exception aException) {         String aMessage =           "Exception occured in client command.execute transaction rollback";         sLogger.log(Level.SEVERE, aMessage, aException);         throw aException;     }     String aMessage = "Exception occured in client command.execute ";     sLogger.log(Level.SEVERE, aMessage, e);     throw e; } 

16.2.2. Declarative Transactions

Declarative transaction management is similar in concept to declarative security management as discussed in Chapter 10. In your component deployment descriptors, you declare whether and where the underlying transaction manager should intercept resource manager requests made by the application code and perform the necessary transaction management (begin, suspend, commit, or roll back transactions). Declarative transaction management can also include the specification of transactional parameters, such as isolation levels. Declarative transaction management facilities are available in EJB deployment descriptors and in certain Hibernate configuration parameters. Refer to Chapter 6 and Chapter 20, respectively, for specific details on declaratively configuring transactions in these contexts. Appendix A provides details on the structure of EJB deployment descriptors as well.

Declarative transaction management can lead to much cleaner separation of business logic and transaction code, and applications written to depend on declarative transaction management can be much easier to maintain and evolve. All of the complexity of transaction management is ceded to the transaction manager, leaving strictly business-related code in the application. However, as mentioned earlier, in some circumstances, declarative transactions are insufficient and programmatic transactions are required.



Java Enterprise in a Nutshell
Java Enterprise in a Nutshell (In a Nutshell (OReilly))
ISBN: 0596101422
EAN: 2147483647
Year: 2004
Pages: 269

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net