【问题标题】:Calling non-transactional method after transaction is rolled back事务回滚后调用非事务方法
【发布时间】:2018-03-16 17:34:19
【问题描述】:

我刚刚发现了一些让我很吃惊的 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”的执行。只有超时标志。

【问题讨论】:

    标签: java jakarta-ee transactions ejb websphere


    【解决方案1】:

    EJB 规范并没有专门解决这种情况,只是指出一旦事务被标记为回滚,那么“继续事务是没有结果的”,并用于处理NOT_SUPPORTED ,规范表明它“没有规定容器应如何管理具有未指定事务上下文的方法的执行”。

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

    【讨论】:

    • 关心资源是有道理的,但实际上这种方法会带来严重的设计限制。您是否有任何信息或只是猜测其他容器在那里的行为?其他供应商(Oracle 等)提供的那些
    • 大多数容器,甚至 Wildfly 都是这样运行的。在将事务方法标记为回滚后,您不能在该方法中执行任何其他操作。我认为即使是 wildfly 或 glassfish 也不允许您在事务方法中捕获异常,并且会自动结束到最后一个非事务性方法调用。
    • @Tracy 实际上这种行为看起来是特定于超时的。 “rollbackOnly”标志不会阻止后续方法的执行,至少是非事务性方法。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2013-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-04
      • 2012-09-19
      • 2016-07-26
      • 2023-03-20
      • 2015-09-01
      相关资源
      最近更新 更多