回滚事务后调用非事务性方法

时间:2018-03-16 17:34:19

标签: java java-ee transactions ejb websphere

我刚刚发现了一些看起来令人惊讶的EJB行为。

以下是代码示例(确保MyBean,beanA,beanB是使用CMT的EJB):

@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 */
         }
    }
}

让我们说methodA需要超过事务超时来执行,所以一旦它返回myMethod就会收到TransactionRolledbackException,然后在“myMethod”中成功捕获。

我希望到目前为止可以调用“methodB”,因为必须在没有任何事务上下文的情况下调用EJB规范。 但实际上,“beanB”代理只返回另一个TransactionRolledbackException,“methodB”不会被执行。

通过EJB规范,我没有看到任何证明容器应该甚至可能以这种方式运行的东西。

我错过了什么吗?任何提示都将不胜感激。

更新

至少对于Websphere,此行为似乎是特定于超时的。例如,当“methodA”抛出RuntimeException时设置的“rollbackOnly”标志不会阻止执行“methodB”。只有超时标志。

2 个答案:

答案 0 :(得分:1)

EJB规范没有专门针对这种情况,除了表明一旦事务被标记为回滚,然后" 继续事务无效",并且NOT_SUPPORTED的处理,规范表明它" 没有规定容器应该如何管理具有未指定的事务上下文的方法的执行"。

所有版本的WebSphere Application Server都采用了这样一种方法,即处理EJB方法仅标记为回滚的方案的最佳方法是阻止容器控制的所有进一步操作,以便可以滚动事务尽快回来,确保及时释放资源(如数据库锁)。允许调用NOT_SUPPORTED EJB方法将导致标记为回滚事务被挂起;因此继续保留可能阻止或已经阻止其他交易的资源。出于这个原因,WebSphere阻止了这种活动。

答案 1 :(得分:0)

前一阵雨面对类似的问题。当容器标记事务以进行回滚时,您将无法在此之后执行任何其他EJB调用。您可以考虑为beanA.methodA()注释 @RequiresNew 的解决方案,以便它不会共享myMethod()的全局事务并始终使用新事务。因此,这个新事务发生的任何事情都不会影响全局事务,因此您可以继续进行进一步的EJB调用。