A quote from the EJB 3.1 specification:
13.6.1 Bean-Managed Transaction Demarcation
The container must manage client invocations to an enterprise bean instance with bean-managed transaction demarcation as follows. When a client invokes a business method via one of the enterprise bean’s client views, the container suspends any transaction that may be associated with the client request.
On the other hand, a transaction from a stand-alone client or another EJB is propagated into a bean using container-managed transactions. Looking at it from the CMT perspective, it seems that beans using CMT have an additional important feature (transaction propagation).
What is the reason for this restriction ("transaction barrier") being imposed on beans using BMT?
Related questions:
In a bean-managed transaction, the code in the session or message-driven bean explicitly marks the boundaries of the transaction. An entity bean cannot have bean-managed transactions; it must use container-managed transactions instead.
The EJB specification allows for distributed transactions that span multiple resources (such as databases) and supports the two-phase commit protocol for both EJB CMP 2.0 and EJB CMP 1.1. WebLogic Server supports any JTA-compliant XA resource.
You probably know that if you use BMT (Bean Managed Transactions) you can get information about current transaction status by using UserTransaction interface (which implementation can be fetched either by JNDI or using dependency injection) and executing it's getStatus() method.
If the client is running within a transaction and invokes the enterprise bean's method, the container throws a RemoteException. If the client is not associated with a transaction, the container does not start a new transaction before running the method.
My "guess" would be this
container "sees" that you have marked the bean as BMT
so at some point you would presumably use UserTransaction object and its begin/commit/rollback etc methods
And since truely nested transactions are not supported by weblogic/oracle etc .. Container has no choice but to suspend current transaction to be able to support the new one
In case of CMT - since you use Requires, or RequiredNew - container "knows" your intent and choses to continue same transaction, or suspend and start a new one accordingly
I do agree with answer by Kalpesh Soni
just I would like to add bit more.
Container uses the same thread for running of one to other EJB calls. A thread could be bound with only one global transaction managed by TM.
That's why @Asynchronous
bean call does not propagate transaction (EJB 3.2 spec, 4.5.3 Transactions). Transaction can't be split over more threads and it's bound to the caller one.
If bean is marked as CMT then container manages transaction creations based on the annotation or info taken from ejb-jar.xml
descriptor. Container is then able to decide if the bean method call will be part of the currently running transaction or a new one needs to be created. As mentioned nested transaction is not supported in most of the Java EE containers. By my understanding the main reason is that XAResource does not support nested transactions (see JTA spec).
BMT bean uses UserTransaction
to drive transaction management on its own. How propagation existing transaction to BMT should work or better what you could with it then? If you would like start a new transaction with UserTransaction.begin()
then the currently running one would be suspended. That's how now propagation works now. I mean transaction is not propagated but suspended at BMT bean call.
The other thing that you could do is drive transaction. It means use UserTransaction.commit()
or UserTransaction.rollback()
on incoming transaction. If you do so then caller on return would be working with no active transaction in its context. Which means a call to a different bean could work with your transaction without you as caller knows and being notified about it. I think that you don't want this being possible. That's my understanding about reasons behind.
There is another funny thing about BMT. If you use a SLSB (Stateless Session Bean) then you are not permitted to exit the called method without finishing transaction (see EJB 3.2: 8.3.3 Enterprise Beans Using Bean-Managed Transaction Demarcation). On the other hand SFSB (Stateful Session Bean) can exit a method without finishing the transaction and that could be finished in other call. If such call happens e.g. in different HTTP session than transaction is suspended and taken from the current thread and later on activated and pinned to new thread.
javax/transaction/xa/XAResource.html "XAResource Java EE 7 API"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With