Java Enterprise in a Nutshell (In a Nutshell (OReilly))
6.9. Transaction Management
One of the advanced value-added features that Enterprise JavaBeans provides over regular remote objects is transaction management. The EJB container can broker transaction contexts on behalf of your EJBs, making sure to "do the right thing" in terms of handling transaction defers, commits, or rollbacks. The Enterprise JavaBeans architecture relies on the Java Transaction API (JTA ) for transaction support. Chapter 16 provides a general overview of transaction management concepts and the JTA. In that chapter, you'll also find some extended topics related to bean- and container-managed transactions with EJBs. If you're looking for material specifically about transaction management within an EJB context, we recommend that you start with the material in this section and then turn to Chapter 16 if you need to know more about the general concepts of transaction management and the JTA. If you need to delve into the broader context of transaction management in general (e.g., if you need to integrate distributed transactions across multiple resource managers into your application), you may want to start with the general overview provided in Chapter 16, then return to the EJB-specific details provided here. 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 commit/rollback). This is another reason all interactions with EJB instances are brokered by the containerso it can properly manage transactions for EJBs that support/require it. In the context of an Enterprise JavaBeans component, transactions can be defined by any of the three runtime roles that participate in the EJB architecture: the client of the EJB object, the EJB container, or the EJB object itself. In all cases, the EJB container decides how to handle the transaction context whenever a 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. JTA supports what is called a flat transaction model, meaning that transactions can't be nested within each other. If a client defines its own transaction (as shown previously) and invokes an EJB method, which attempts to define its own, separate transaction context, the EJB container needs to decide how to mitigate these two transaction contexts so that there is only one (or else throw an exception if the situation can't be resolved). What the container does in a particular transactional situation is determined largely by deployment descriptor elements that indicate how an EJB transaction is to be managed. 6.9.1. Transaction Management: Bean-Managed Versus Container-Managed
First, at a high level, you need to specify to the container whether your EJB will manage its own transactions (by creating its own UserTransaction objects and starting/committing them in its business methods) or will rely on the container to manage its transactions. This is done in the deployment descriptor using the <transaction-type> element: ... <enterprise-beans> <session> ... <transaction-type>Container</transaction-type> ... </session> ... </enterprise-beans> ...
A Container value indicates container-managed transactions; a Bean value indicates bean management. If you specify bean-managed transactions, the container will automatically suspend any client-defined transactions before calling methods on your EJB and resume them after any bean-defined transaction contexts have been committed/rolled back. If you use container-managed transactions, the container will use the method-level transaction support attributes discussed in the next section to determine how it deals with transactions. Normally you will want to use container-managed transactions since managing your own transaction boundaries within your bean code isn't usually necessary. Bean-managed transactions may be necessary when you need to define multiple transaction contexts in the span of a single method. But situations like this are rare, and where possible you should avoid the additional complexity in your code and leave the transaction management to the EJB container. Entity beans aren't allowed to use bean-managed transaction management because the persistence management services of the EJB container require that entity beans never create their own UserTransactions. So you never specify a <transaction-type> for entity beans in their deployment descriptor; it's always assumed to be Container. 6.9.2. Transaction Support Attributes
If your EJB uses container-managed transaction management, you can further specify how each method on the EJB "supports" transactions, and therefore how the container should deal with different transaction contexts when it invokes these methods on your beans. The following <transaction-support> values are available when specifying them in your deployment descriptor:
These attributes are associated with methods on the EJB in the <assembly-descriptor> section of the deployment descriptor. You provide <container-transaction> elements that specify one or more methods and a transaction support attribute to apply to those methods. Using our stateless session ProfileManager EJB as an example, we can specify that its getProfile( ) method "supports" transactions using this XML stanza: ... <assembly-descriptor> ... <container-transaction> <method> <ejb-name>ProfileManagerBean</ejb-name> <method-name>getProfile</method-name> </method> <trans-attribute>Supports</trans-attribute> </container-transaction> ... </assembly-descriptor> ...
There are some restrictions on the use of these attribute values for some types of EJBs, as described next. 6.9.2.1. Message-driven beans
For message-driven beans, only the NotSupported and Required attributes are allowed since client transactions can't be propagated to the EJB through a message passed to a JMS service. 6.9.2.2. CMP entity beans
Entity beans using CMP use transactions by definition when the container interacts with the persistent store on their behalf. Therefore, entity EJBs using CMP should use either the Required, RequiresNew, or Mandatory attributes since the others allow for contexts with no transactions. Technically, you can use the other attribute values with CMP beans, but EJB containers are not required to support them in this situation, so it's wise to avoid them. 6.9.2.3. Stateful session beans
Stateful session beans that implement the session synchronization interface, as discussed at the end of "Session Bean Specifics" earlier in this chapter, depend on transaction notifications from the container to keep their state in sync. Without a transaction, the container is not able to invoke the session synchronization callbacks. Therefore, this flavor of stateful session bean can use only attribute values that result in a transaction: Required, RequiresNew, and Mandatory. 6.9.2.4. Stateless session beans
If a stateless session bean is published as a web service (as detailed in Chapter 12), you are not allowed to use the Mandatory attribute value. A transaction context initiated by a SOAP client cannot be propagated across a SOAP call to the session bean, so mandating that the client initiate a transaction for the bean request doesn't make sense. |