2014年4月14日 星期一

Bean Managed Transaction Demarcation

If an EJB is deployed using bean managed transaction demarcation (here referred to as
BMTD, though this abbreviation isn’t used in the EJB specification itself), the EJB con-
tainer allows the bean to obtain a reference to a javax.transaction.UserTransaction
object using the EJBContext. You can see this in Figure 8.3.

Motivation and Restrictions

An EJB might need to be deployed under BMTD if the conditions on which a transaction
is started depend on some programmatic condition. It could be that one method starts the
transaction and another method completes the transaction.
However, the cases where BMTD is needed are few and far between. Indeed, they are so
rare that the EJB specification limits BMTD to Session beans. Entity beans can only be
deployed with CMTD. This makes sense because Entity beans represent persistent trans-
actional data; the transaction context should be as deterministic as possible.
Moreover, if a stateless Session bean starts a transaction, it must also commit that trans-
action before the method completes. After all, the stateless Session bean will have no
memory of the client that just invoked its method after that method completes, so one
cannot expect that the transaction context is somehow miraculously preserved. If you
write a BMTD stateless Session bean that does not commit its own transaction, the EJB
container will rollback the transaction and throw an exception back to the client
(java.rmi.RemoteException for remote clients, or javax.ejb.EJBException for local).
Indeed, even with stateful Session beans, there is a restriction. Any current transaction in
progress when the BMTD Session bean is called will be suspended by the EJB container,
not propagated to the BMTD bean. It is possible that, from the bean’s perspective, there
is a current transaction, but that would refer to any transaction not committed when a
method on that bean was last called.

Using the Java Transaction API
When a Session bean is deployed under BMTD, there is an implementation choice as to
how it should manage its transactions. If interacting solely with an RDBMS, the Session
bean can manage the transactions directly through the JDBC API. Alternatively, it can
use the Java Transaction API, defined by the classes and interfaces in the javax.trans-
action and the javax.transaction.xa packages. The latter is to be preferred, if only
because transactional access to Java Messaging Service resources (you’ll be learning
more about these tomorrow and the day after) can only be performed through the JTA
API. Equally, servlets can also use the JTA API.

For a Session bean to start a transaction, it should first call the getUserTransaction()
method of its SessionContext. You’ll recall that this was the method that throws an
exception under CMTD, but it is the centerpiece of transaction control under BMTD.
Obtaining a UserTransaction does not mean that a transaction has been started. Rather,
it must be started using the begin() method. The transaction can then be completed
using either the commit() or the rollback() method. The current status can also be
obtained using getStatus(). This returns an int whose meaning is defined by the
constants in the javax.transaction.Status interface. Some of the most common status
values are shown in Table 8.2.

沒有留言:

張貼留言