Container-Managed Transaction Demarcation

You've spent the last three days writing and deploying EJBs without really having to worry too much about transactions. This isn't to say that there have been no transactions in use; far from it. Every interaction with the database performed in the case study has involved transactions. However, the Session and Entity beans deployed have used container manager transaction demarcation (here referred to as CMTD, though the abbreviation isn't used in the EJB specification). Information in the deployment descriptor indicates when the EJB container should start and commit transactions.

Figure 8.1 shows a diagram that you saw first on Day 6.

Figure 8.1. The EJB proxy objects implement transaction (and security) control.


This shows how the EJB proxy objects (those implementing the javax.ejb.EJBObject or javax.ejb.EJBLocalObject interfaces) implement the transaction semantics. This is one of the reasons that a bean must never implement its own remote interface. To do so would mean that it could unwittingly return a reference to itself as a Remote interface, subverting any security and transaction checks performed by its proxy.

Listing 8.2 shows a fragment of the deployment descriptor for the AdvertiseJob Session bean from Day 7.

Listing 8.2. Deployment Descriptor for AdvertiseJob Session Bean
 1: <ejb-jar>
 2:     <display-name>Agency</display-name>
 3:     <enterprise-beans>
 4:         <session>
 5:             <display-name>AdvertiseJobBean</display-name>
 6:             ... lines omitted ...
 7:             <transaction-type>Container</transaction-type>
 8:             ... lines omitted ...
 9:         </session>
10:     </enterprise-beans>
11:     <assembly-descriptor>
12:         <container-transaction>
13:             <method>
14:                 <ejb-name>AdvertiseJobBean</ejb-name>
15:                     <method-intf>Remote</method-intf>
16:                     <method-name>updateDetails</method-name>
17:                     <method-params>
18:                         <method-param>java.lang.String</method-param>
19:                         <method-param>java.lang.String</method-param>
20:                         <method-param>java.lang.String[]</method-param>
21:                     </method-params>
22:                 </method>
23:             <trans-attribute>Required</trans-attribute>
24:         </container-transaction>
25:
26:     </assembly-descriptor>
27: </ejb-jar>

As you have seen over the last three days, the enterprise-beans element consists of session or entity elements. The session element has a transaction-type element which, under CMTD, should have the value of Container. For entity elements, the transaction-type is not specified because entity beans must always be deployed using CMTD, so it is implicit.

Each method of the remote interface must be present in a container-transaction element. The same is true of the methods in the home interface. The relevant DTD definitions that govern the structure of the deployment descriptor are as follows:

<!ELEMENT ejb-jar (description?, display-name?, small-icon?, large-icon?,
enterprise-beans, relationships?, assembly-descriptor?, ejb-client-jar?)>

The assembly-descriptor element is defined as follows:

<!ELEMENT assembly-descriptor (security-role*, method-permission*, container-transaction*,
 exclude-list?)>

You can see here that assembly-descriptor element is all about providing the information used to create the EJB proxy objects. The security-role, method-permission, and exclude-list elements are security related, and the container-transaction element obviously defines transaction-related information.

The security-related elements of the assembly-descriptor element are not considered further here. However, the container-transaction element is relevant to the discussion. It is defined in the DTD as follows:

<!ELEMENT container-transaction (description?, method+, trans-attribute)>

and the method element is defined as

<!ELEMENT method (description?, ejb-name, method-intf?, method-name, method-params?)>

So, a container-transaction element identifies one or more methods. The method element identifies a method in the home or remote interface; the method-intf element is only needed in those rare occasions when there happens to be a method of the same name in both the home and remote interfaces. The method-name must be specified, although the value of * can be used as a convenient shortcut to indicate all methods. The method-params element is optional and is used to distinguish between overloaded versions of the same method name. If not specified, the method element identifies all overloaded versions of the method with the specified name.

Finally, the bit that really matters. The trans-attribute element indicates the transactional characteristics to be enforced when the specified method is invoked. A transaction may or may not be in progress; in the terminology of the EJB specification, there may or may not be a current valid transactional context. When a method is invoked, the EJB container needs to know what should occur. For example, if there is no transaction in progress, is one needed to execute the method? Should a transaction be started automatically if there isn't one? Perhaps a transaction can be started even if another one is in progress? And so on. There are six possible values; their semantics are shown in Table 8.1.

Table 8.1. Different CMTD Semantics Are Indicated by the trans-attribute Element
trans- attribute Meaning Notes
NotSupported Method accesses a resource manager that does not support an external transaction coordinator. Any current transaction context will be suspended for the duration of the method. The EJB architecture does not specify the transactional semantics of the method.
Required A transaction context is guaranteed. The current transaction context will be used if present; otherwise, one will be created. Commonly used.
Supports Use valid transaction context if available (acts like Required). Otherwise, use unspecified transaction context (acts like NotSupported). Acts as either Required or NotSupported. This makes the Supports a highly dubious choice. The method must guarantee to work in the same way whether or not there is a transaction context available.
RequiresNew A new transaction context will be created. Any existing valid transaction context will be suspended for the duration of the method. Can reduce contention (for example, for a bean that generates unique IDs or for a bean that writes to a log).
Mandatory A valid transaction context must exist; an exception will be thrown by the EJB container otherwise. The transaction context will be used. Useful for helper beans' methods, designed to be called only from another bean.
Never There must be no current transaction context. An exception will be thrown by the EJB container otherwise. The method invokes with an unspecified transaction context. Acts as NotSupported.

For Entity beans, only the Required, RequiresNew, and Mandatory trans-attribute values are recommended. The problem with NotSupported, Never, and (if invoked with no current transaction context) Supports is that, in addition to performing the business method, the EJB container must also perform the ejbLoad() and ejbStore() methods. These will be performed with the same transactional context as the business method, which is to say, with no transactional context. What might happen then is somewhat undefined, as the EJB specification is at pains to point out. Indeed, it goes so far as to list (in section 17.6.5) four or five different ways in which the EJB container might decide to act.

Caution

Never use NotSupported, Never, or Supports as trans-attribute values with Entity beans.


As usual, the deploytool GUI can also be used to configure the information within the deployment descriptor, as shown in Figure 8.2.

Figure 8.2. deploytool lets CMT characteristics be defined on a per-method basis.


You are likely to find that the vast majority of your beans' methods will use the Required trans-attribute value. Indeed, this is the value that has been used in the case study over previous days.

Although CMTD means that the EJB container automatically starts, suspends, and completes transactions, this is not to say that the beans themselves cannot influence the transactions. After all, if an Entity bean hits an error condition that means that the transaction should be aborted, it needs some way to indicate this to the EJB container. As an example, consider the hackneyed example of withdrawing money from a bank account. If the balance would go into the red, (or perhaps more likely, beyond an overdraft limit), the Entity bean that represents the account would want to indicate that the transaction should be aborted.

Note

It's interesting to compare the XML deployment descriptor approach to using deploytool. The deployment descriptor places the security- and transaction-related information in the assembly-descriptor element, away from the definition of the beans themselves (which reside under the enterprise-beans element). This is interesting in its own right, because it ties back to the different EJB roles you learned about back on Day 2, “The J2EE Platform and Roles.” The intention is that the bean provider completes just the information in the enterprise-beans element, while the application assembler completes the information under the assembly-descriptor. This allows an EJB component to be used in different applications, with different transaction and security requirements.

In contrast, the deploytool does not differentiate between the two roles; the transaction (and security) information are just two of the seven tabs on the right side of the GUI, providing information about the selected EJB; the other five tabs pertain to information found under the enterprise-beans element.


To do this, the bean can use two transaction-related methods provided by its EJBContext. In the case of a Session bean, this will be the javax.ejb.SessionContext passed in through the setSessionContext() method, and for an Entity bean, this will be the javax.ejb.EntityContext passed in through setEntityContext(). To remind you, Figure 8.3 shows a UML class diagram illustrating the methods provided by these interfaces.

Figure 8.3. The EJBContext provides access to the current transaction.


To cause the transaction to be aborted, the CMTD bean can call setRollbackOnly(). This instructs the EJB container to prevent the transaction from being committed. The bean cannot rollback the transaction directly, because the transaction itself is “owned” by the EJB container, not the bean. The getRollbackOnly() method obviously just indicates whether the transaction has been marked for rollback.

There is one other transaction-related method in EJBContext, namely getUserTransaction(). However, this cannot be called by a CMTD bean, and any attempt to do so will result in the EJB container throwing a java.lang.IllegalStateException.

Note

The remaining methods in EJBContext provide access to the home interface(s) of the bean (getEJBHome() and getEJBLocalHome()) and to the security context (getCallerPrincipal(), isCallerInRole(String)). The other methods have been deprecated.


One last point relating to CMTD beans—they must not make use of any resource manager-specific transaction management methods that would interfere with the EJB container's own management of the transaction context. Consequently, a BMP Entity bean cannot call commit(), setAutoCommit(), and so on a java.sql.Connection object.

If your bean does need more fine-grained control over transactions, the bean must be deployed using bean-managed transaction demarcation. This is discussed next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.184.102