7.3. Transaction ManagementOne of the value-added features that Enterprise JavaBeans provides over regular remote objects is semiautomated transaction management. I'll periodically mention transaction-related issues when we look at creating, deploying, and using EJB objects, so this section introduces some basic transaction-management concepts. If you're not interested in using the transaction-management features of your EJB server, you can safely skip this section and jump to the material on implementing EJB object. If you plan to make JDBC calls from within your bean, however, you should note the information in the section on database transactions. Transactions break up a series of interactions into units of work that can be either committed if they are successfully executed or rolled back at any time before the transaction is committed. If a transaction is rolled back, all parties involved in the transaction are responsible for restoring their state to its pretransaction condition. Transaction support is especially important in a distributed environment, since agents may lose network contact with each other or one agent may die while engaged in a series of interactions with another agent. The EJB container is the principal player in the area of transaction management, since it is responsible for either generating transactions around client interactions with the bean, or detecting client-requested transactions and then notifying the EJB objects about transaction boundaries (start and end). The Enterprise JavaBeans architecture relies on the Java Transaction API (JTA) for transaction support. The JTA represents a transaction with the javax.transaction.UserTransaction interface.[3] Complete coverage of the JTA and the concepts of transaction-based processing are beyond the scope of this chapter, but a few words of overview here should be enough for you to get an understanding of how this can be a valuable feature of Enterprise JavaBeans. In addition, the JTA interfaces and classes are documented in Part 3, "API Quick Reference".
A client or an EJB object can declare a new transaction by creating a UserTransaction object. The transaction is started by calling the begin() method on the transaction object, and ended by calling either the commit() method (for a successful completion) or the rollback() method (to abort the transaction and revert to the state before the transaction began). The following code shows the (now cliché) example of a banking transaction in an EJB context: // Get the JNDI context, and use it to get the Account home interface Context ctx = new InitialContext(props); AccountHome acctHome = (AccountHome)ctx.lookup("Accounts"); // Get two accounts Account savings = acctHome.findByNameAndType("Jim Farley", "savings"); Account checking = acctHome.findByNameAndType("Jim Farley", "checking"); // Get a transaction object, using a JNDI lookup on the EJB context javax.transaction.UserTransaction xaction = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction"); // Perform a transaction xaction.begin(); try { savings.deposit(1500.0); checking.transfer(savings, 750.0); xaction.commit(); } // If anything goes wrong, roll back the work we've done. catch (Exception e) { xaction.rollback(); } This code might be seen in a client application using an EJB server for banking services. In this case, the client is using the transaction to ensure that both the deposit to savings and the transfer to checking are committed only if both operations are successful. If either one fails, the rollback() method is called on the transaction to ensure that any changes are undone. An EJB object might use similar procedures if it is managing its own transactions, the only difference being that the bean would be able to use its EJBContext to get a transaction from its container: xaction = myContext.getUserTransaction(); The use of the EJBContext in enterprise beans is covered later in the chapter. In the context of an Enterprise JavaBeans component, transaction boundaries can be defined by the client of the EJB object, the container, or the EJB object itself. In all cases, the EJB container decides how to handle the transaction context whenever a remote method is invoked on an EJB object. During a bean's lifetime, the container decides whether to execute the bean's business methods within the client's transaction or within a transaction that the container defines, or to allow the bean to manage its own transaction boundaries. When it is deployed, a bean can choose one of the following transaction-support attributes:
7.3.1. Making the EJB Server Aware of Database TransactionsIn order for an EJB server to properly implement the various transaction levels listed previously, it needs to be aware of JDBC connections and database transactions that you make from within your enterprise bean. This is key to the EJB server's ability to provide your beans with semiautomatic transaction management. While your bean methods are executing within a given transaction context, the EJB server needs to ensure all database transactions that you make are held pending the commit or rollback of the transaction. If the transaction is committed, the pending database updates are committed to their respective data sources. If the transaction is rolled back, the pending database updates are rolled back as well. To allow the EJB server to do this, your enterprise bean typically needs to acquire JDBC connections in a manner specified by your EJB server. Unfortunately, the EJB 1.0 specification does not provide a standard method for acquiring database connections from an EJB container. Until this oversight in the EJB specification is amended, EJB server vendors have to provide their own methods for an EJB object to get connections that are monitored by the EJB container. Most EJB vendors provide a way to define a pool of JDBC connections and a means for requesting connections from this pool at runtime. BEA's WebLogic server, for example, allows you to specify a connection pool in a server property file and then use a JDBC URL to pull connections from this pool at runtime. An example properties entry might look like this: weblogic.jdbc.connectionPool.myPool=\ url=jdbc:weblogic:oracle,\ driver=weblogic.jdbc.oci.Driver,\ loginDelaySecs=1,\ initialCapacity=5,\ maxCapacity=10,\ capacityIncrement=1,\ props=user=jsmith;password=foobar;server=main This line of the properties file asks the server to create a connection pool named myPool with the specified JDBC driver and connection properties. The server reads this information from the properties file on startup and creates the pool, and then your EJB object can ask for connections from the pool using a specific JDBC URL: Connection conn = DriverManager.getConnection("jdbc:weblogic:jts:myPool"); This allows the WebLogic server to issue your bean a JDBC connection that is controlled by the server. However, there is currently no consensus among EJB providers concerning support for this method of providing JDBC connections to EJB objects and clients. Before using JDBC code in your enterprise beans, make sure to consult your EJB server documentation to see specifically how it provides JDBC connection management. 7.3.2. Transaction Isolation LevelsNormally, you would expect multiple transactions originating from multiple client requests on your bean to be effectively serialized. In other words, if multiple client transactional requests are made of your bean, the end effect of satisfying all these requests by timesharing the bean between each client/transaction should be the same as if each request were serialized at the boundaries of each transaction. The ANSI SQL standard defines three ways in which this transaction isolation rule can be violated:
When you deploy your enterprise bean within an EJB container, you can specify what level of transaction isolation you want it to enforce for you, using one of the following isolation levels:
These levels can be applied to an entire bean or to individual methods on the bean. If you don't specify one of these isolation levels, the EJB server typically uses the default isolation level dictated by the database being used for persistent storage. For more information on these isolation levels and their meaning, consult the JDBC specification or the ODBC specification. Chapter 2, "JDBC", also briefly discusses database isolation levels. I mention them here just so that you are aware that they exist and can seek out more information if the details of transaction isolation are important for your enterprise beans. Copyright © 2001 O'Reilly & Associates. All rights reserved. |
|