CDI 中 @Transactional 的局限性是什么?

What are the limitations of @Transactional in CDI?

我正在尝试在 CDI class 中使用 @Transactional 方法,而不是 EJB:

@javax.inject.Named
// fails @javax.enterprise.context.ApplicationScoped
// fails @javax.enterprise.context.SessionScoped
// works @javax.ejb.Singleton
// works @javax.ejb.Stateless
public class SomeClass {
    @javax.persistence.PersistenceContext
    private EntityManager em;

    @javax.annotation.PostConstruct    
    @javax.transaction.Transactional
    public void someMethod() {
        em.persist(someEntity);
    }
}

当我用 @Singleton@Stateless 注释 SomeClass 时,一切正常。

当我用 @ApplicationScoped@SessionScoped 注释 SomeClass 时,WildFly 13 显示以下错误消息:

Transaction is required to perform this operation (either use a transaction or extended persistence context)

我的印象是 @Transactional 从 Java EE 7 开始就与 CDI 一起工作。我错了吗?或者我只是缺少一些额外的配置?

我将尝试给出一个简短的清单,列出在尝试使 @Transactional 与 CDI 一起工作时要查看的内容,以便给出比评论更有价值的答案:

  1. 我们正在讨论 javax.transaction.Transactional,而不是 javax.ejb.TransactionAttribute,它适用于 EJB!
  2. 它不能在非 JEE 应用程序中开箱即用!
  3. 我们所说的 JEE 应用程序是指 运行 完整的 JEE 应用程序服务器; Tomcat 开箱即用不支持!
  4. 注意类路径问题,特别要确保不存在包含注释 javax.transaction.Transactional 的 jar,例如在 WEB-INF/lib 中,当 运行 在完整的 JEE 应用程序服务器中。如果你想在非完整的 JEE 环境中使用它,你需要将它放在类路径中。
  5. @Transactional被最新的JTA规范实现为CDI拦截器。像这样:
    • JEE < 7 中没有!
    • 它具有与任何拦截器相同的限制。例如。它不能被初始化方法调用 - @PostConstruct [这是这个问题中的问题],并且在调用 this 对象的方法时它是 NOT 激活,当心!!!
  6. 我很有信心可能存在更多错误!!!