关于 glassfish:CMT 的 JTA 交易划界究竟在哪里得到尊重?

Where exactly is the JTA Transaction demarcation for CMT respected?

我正在尝试完全理解 JTA 与 CMT 的划分。我遇到的行为是,在 EJB 上仅尊重该方法的第一个 @TransactionAttribute,而对具有不同 @TransactionAttribute 注释的同一 bean 的后续方法调用则没有。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Foo implements IFoo {

   @EJB
   private IBar barBean;

   // inherits class transaction annotation of NOT_SUPPORTED
   public void doSomething() {
        barBean.doAction();
   }
}

@Stateless
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class Bar implements IBar {

    public void doAction() {
        Entity entity = bar.find();
        entity.setName("new name");
        // fails with EJBException with TransactionRequiredException as cause
        save(entity);
    }

    public Entity find() {
        // return some persisted entity.
        return em.findById(1);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Entity save(entity) {
        em.persist(em.merge(entity));
        em.flush();
    }
}

我看到的行为是 Bar.save() 抛出了 TransactionRequiredException。所以这告诉我在 save() 上设置的 REQUIRED 注释不会创建事务。 REQUIRES_NEW 也不起作用。如果我将 save() 移动到另一个 EJB,它会按预期工作。

这是否意味着只有第一个 TransactionAttribute 注释被尊重,而不管后续方法调用是否具有不同的注释值?这是一个错误还是预期的行为?我似乎找不到任何具体解释这一点的文档。我很感激对此的任何见解。

我的堆栈:
EJB 3.0,
顶联要点,
GF V2UR2


我对 EJB 3 规范的解读是,单个方法的事务规范会覆盖整个 EJB 的事务规范。因此,您对 REQUIRED 应该适用的期望似乎是合理的,但是 ...

仅当您将 bean 方法用作 EJB 时。当您从一个业务方法 doAction() 直接调用另一个业务方法 save() 时,您没有使用 EJB 引用,因此这只是普通的旧 Java - 不涉及容器,因此容器没有机会进行干预.

如果您将所需的选项应用于您的 doAction() 方法,我希望它可以工作。

这个理论与你对重构到另一个 EJB 的影响的发现是一致的。