简体   繁体   中英

Calling non-transactional method after transaction is rolled back

I've just found some EJB behaviour which looks rather surprizing to me.

Here is the code sample (for sure MyBean, beanA, beanB are EJBs using CMT):

@Stateless
public class MyBean {
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void myMethod(){
         try {
             beanA.methodA(); /* annotated as REQUIRED */
         } catch (Exception e) {
             beanB.methodB(); /* annotated as NOT_SUPPORTED */
         }
    }
}

Lets's say methodA takes more than transaction timeout to execute, so once it returns myMethod receives TransactionRolledbackException, which is successfully caught then in "myMethod".

I would expect "methodB" be called so far, as accordingly with EJB spec it must be called without any transaction context. But actually, the "beanB" proxy simply returns another TransactionRolledbackException, the "methodB" is not executed.

Looking through EJB spec I do not see anything to prove that container should or even might behave that way.

Do I miss something? Any hint would be appreciated.

UPDATE

At least for Websphere, this behaviour appears to be timeout-specific. The "rollbackOnly" flag which for example is set when "methodA" throws a RuntimeException, does not prevent "methodB" from execution. Only timeout flag does.

The EJB specification does not specifically address this scenario, other than to indicate that once a transaction has been marked for rollback, then " Continuing transaction is fruitless ", and for the handling of NOT_SUPPORTED , the specification indicates it " does not prescribe how the container should manage the execution of a method with an unspecified transaction context ".

All versions of WebSphere Application Server have taken the approach that the best way to handle the scenario where an EJB method has been marked for rollback only is to prevent all further actions the container has control over, so that the transaction may be rolled back as quickly as possible, ensuring the timely release of resources (such as database locks). Allowing a call to a NOT_SUPPORTED EJB method would result in the marked for rollback transaction being suspended; and thus continue to hold onto resources that could block or already be blocking other transactions. For this reason, WebSphere prevents such activity.

Faced the similar issue a while back . When the container mark the transaction for rollback you will not be able to do any other EJB calls after that. You can think about a solution of annotating @RequiresNew for beanA.methodA() , so that it will not share the global transaction of myMethod() and will always use new transaction. Therefore anything happens to this new transaction will not affect the global transaction so that you can proceed with your further EJB calls.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM