17.3 Bean-Managed Transactions
Bean-managed transactions offer the stateless
session bean developer additional flexibility, but at the cost of
additional complexity.
There are two alternate techniques for demarcating transaction
boundaries in your bean code: use the server's
javax.transaction.UserTransaction
or use the PersistenceManager's
javax.jdo.Transaction. If you use
UserTransaction, you can begin and complete
distributed transactions managed by the server's
TransactionManager. If you use
JDO's Transaction, you begin and
complete local transactions that are managed completely by the JDO
implementation, without any help (or interference) from the
container.
17.3.1 javax.transaction.UserTransaction
To use
UserTransaction,
you obtain it via
getUserTransaction(
) from the SessionContext instance,
begin the transaction, and then obtain the
PersistenceManager from the
PersistenceManagerFactory. During
getPersistenceManager( ), the
PersistenceManagerFactory will automatically
associate the PersistenceManager with the active
UserTransaction.
When your bean invokes methods of beans that use
container-managed transactions, the
container automatically associates transactional resources used by
the other beans in the current UserTransaction.
The transactional resources can be JDO
PersistenceManagers,
JDBC
Connections, or
connector
resources.
If you require nontransactional access to JDO, you must obtain the
PersistenceManager when the
UserTransaction is not active. After beginning a
UserTransaction, if your application needs a
PersistenceManager for transactional access, a
different PersistenceManager must be obtained for
this purpose. Your application must keep track of which
PersistenceManager is being used for which
purpose. Once you complete the UserTransaction by
calling commit( ) or rollback(
), the PersistenceManager associated
with that transaction can no longer be used.
Consider the following code fragment, in which ctx
is the SessionContext instance:
UserTransaction utx = ctx.getUserTransaction( );
PersistenceManager pm1 = pmf.getPersistenceManager( );
utx.begin( );
PersistenceManager pm2 = pmf.getPersistenceManager( );
PersistenceManager pm3 = pmf.getPersistenceManager( );
utx.commit( );
PersistenceManager pm4 = pmf.getPersistenceManager( );
PersistenceManager pm5 = pmf.getPersistenceManager( );
utx.begin( );
PersistenceManager pm6 = pmf.getPersistenceManager( );
PersistenceManager pm7 = pmf.getPersistenceManager( );
utx.commit( );
In this example, pm1, pm4, and
pm5 are references to unique instances of
PersistenceManager, and transaction completion is
managed independently by each of the associated
Transaction instances. pm2 and
pm3 are references to the same instance, and
transaction completion is controlled by the utx
instance. pm6 and pm7 are
references to the same instance, and transaction completion is
controlled by the utx instance.
17.3.2 javax.jdo.Transaction
As the bean developer, if you choose to use the same
PersistenceManager for multiple serial
transactions, you must demarcate transaction boundaries by using the
javax.jdo.Transaction instance associated with the
PersistenceManager. Obtaining a
PersistenceManager without having an active
UserTransaction results in your being able to
manage transaction boundaries via begin( ),
commit( ), and rollback( ) of
javax.jdo.Transaction. In this mode, the JDO
implementation does not access UserTransaction.
Your bean can invoke methods of beans that use container-managed
transactions, but since the container doesn't know
about JDO transactions, it cannot automatically associate
transactional resources used by the other beans in the transaction.
17.3.3 Stateless Session Beans with Bean-Managed Transactions
You establish transaction boundaries using one of the techniques
detailed in the previous section, but the bean's
state (including the PersistenceManager) cannot be
retained across business-method boundaries. Therefore, each business
method must obtain a PersistenceManager and close
it before it returns.
17.3.4 Stateful Session Beans with Bean-Managed Transactions
The major difference between stateful and stateless session beans
with bean-managed transactions is that with stateful session beans
you can save states between method invocations, including
PersistenceManager, and you can even keep
transactions active. However, we recommend that you do not keep
transactions open between business methods.
If you use UserTransaction, the server knows that
the transaction is open at the end of the business method and it will
leave the bean in a state that cannot be passivated. Since the bean
can't be passivated, it will continue to tie up
server resources until the timeout period elapses. If the server does
time out the bean, the server automatically rolls back the
transaction and you lose everything in the current transaction.
If you use JDO Transaction instead, the server
might not even be aware of your transaction and might passivate the
bean. In this case, you have to close the
PersistenceManager in ejbPassivate(
), since the
PersistenceManager cannot be serialized. Again,
you lose the current transaction.
|