REQUIRED may be evil
I personally do not like the REQUIRED transaction attribute and will greatly impede its use.
Lazy creation of transactions (this is what is REQUIRED) leads to the fact that he does not know when and where the transaction was actually launched and when it will be completed. This is not good. People must explicitly create transactional boundaries.
MANDATORY and UserTransaction - soul mates
Your desire to use UserTransaction very good and works with CMT - there is no difference between a JTA transaction launched through a UserTransaction provided by a container or a JTA transaction launched by a container for you.
The approach I would recommend is to switch all the REQUIRED USE to MANDATORY . WITH RESPONSIBILITY the container will not trigger transactions for you. Instead, it will protect your bean, ensuring that it cannot be called if the transaction is not running. This is an amazing and underutilized feature. MANDATORY is the best friend of anyone who wants to create a truly deterministic transactional application and enforce it. With this setting, you can fall in love with CMT.
In this scenario, you start a transaction with UserTransactions , and then the container looks like your big bodyguard, kicking people on the curb, unless they started the proper transaction before trying to call your code.
Questions
- A servlet or BMT EJB can use UserTransaction.
- CMT beans cannot use UserTransaction, but they can participate in a transaction launched by UserTransaction (as indicated above, a JTA transaction is a JTA transaction).
- BMT beans cannot participate in an existing transaction. If you call the BMT bean while the transaction is already in progress, the transaction will be suspended by the container before the BMT bean is called and resumed after this method completes.
@Resource UserTransaction you will get user transaction through injectionjava:comp/UserTransaction you will get user transaction through search@TransactionAttribute(MANDATORY) used at the class level will affect the methods of this exact class (i.e. the fooClass.getDecaredMethods() methods). Methods of superclasses and subclasses will default to @TransactionAttribute(REQUIRED) if these classes are also not explicitly annotated @TransactionAttribute(MANDATORY)- If you are unable to call
userTransaction.begin() and userTransaction.commit() and do the appropriate exception handling, consider @TransactionAttribute(REQUIRES_NEW) . Your transaction boundaries will continue to be documented and clear. RuntimeException from the CMT bean method will cause the transaction to be marked for rollback, even if you catch and handle the exception in the calling code. Use @ApplicationException to disable this on a case by case basis for custom exception classes at runtime.
Loss of transaction context
A couple of things can lead to the fact that your transaction during the continuation, suspension or otherwise will not be transferred to the called bean.
- BMT beans terminate the distribution of the transaction. If the current transaction calls the BMT bean, this transaction will be paused until the BMT bean is called and will resume after the bean returns. BMT beans can be a source of transactions, but cannot participate in existing transactions. If the distribution mysteriously doesn't work, make sure there are no inadvertent calls to BMT beans in the middle of the transaction.
- Do not use anything other than the container-supplied UserTransaction or container that provides methods such as SessionContext.setRollbackOnly to manage transactions. Using a "resource-specific transaction demarcation API", such as JPA
EntityTransaction or EntityTransaction java.sql.Connection.commit() , will bypass transaction management. - Do not start your own threads. Transactional propagation occurs separately. Java EE has standard no standard APIs that support a transaction that spans multiple threads. If you leave the thread either from starting your own thread, or using @Asynchronous, you will leave your existing transaction.
David Blevins
source share