简体   繁体   English

JEE7:EJB和CDI bean是否支持容器管理的事务?

[英]JEE7: Do EJB and CDI beans support container-managed transactions?

Java EE7 consists of a bunch of "bean" definitions: Java EE7由一堆“bean”定义组成:

  • Managed Beans 1.0 (JSR-316 / JSR-250) Managed Beans 1.0(JSR-316 / JSR-250)
  • Dependency Injection for Java 1.0 (JSR-330) Java 1.0的依赖注入(JSR-330)
  • CDI 1.1 (JSR-346) CDI 1.1(JSR-346)
  • JSF Managed Beans 2.2 (JSR-344) JSF Managed Beans 2.2(JSR-344)
  • EJB 3.2 (JSR-345) EJB 3.2(JSR-345)

In order to get rid of the chaos in my mind, I studies several articles of "when to use which bean type". 为了摆脱我心中的混乱,我研究了几篇“何时使用哪种豆类”的文章。 One of the pros for EJB seems to be that they alone support declarative container-managed transactions (the famous transaction annotations). EJB的一个优点似乎是它们单独支持声明性容器管理事务 (着名的事务注释)。 I'm not sure, though, if this is correct. 不过,我不确定这是否正确。 Can anyone approve this? 任何人都可以批准这个吗?

Meanwhile, I came up with a simple demo application to check if this was actually true. 同时,我想出了一个简单的演示应用程序来检查这是否真的如此。 I just defined a CDI bean ( not an EJB - it has no class level annotations) as follows, based on this snippet: 我刚刚根据这个片段定义了一个CDI bean( 不是 EJB - 它没有类级别注释),如下所示:

public class CdiBean {
    @Resource
    TransactionSynchronizationRegistry tsr;

    @Transactional(Transactional.TxType.REQUIRED)
    public boolean isTransactional() {
        return tsr.getTransactionStatus() == Status.STATUS_ACTIVE;
    }
}

Now, the outcome on GlassFish 4.0 is that this method actually returns true, which, according to my inquiries, is not working as expected . 现在,GlassFish 4.0的结果是这个方法实际上返回true,根据我的询问,它没有按预期工作 I did expect the container to ignore the @Transactional annotation on a CDI bean method, or to even throw an exception. 我确实希望容器忽略CDI bean方法上的@Transactional注释,或者甚至抛出异常。 I use a freshly-installed GlassFish 4 server, so there are no interferences. 我使用新安装的GlassFish 4服务器,因此没有干扰。

So my question is really: 所以我的问题是:

  • Which bean types do actually support container-managed transactions? 哪些bean类型实际上支持容器管理的事务?
  • Just for the sake of curiosity, how could I test it with a simple demo application if the code above is wrong? 只是为了好奇,如果上面的代码错误,我怎么能用一个简单的演示应用程序来测试呢?

(BTW: Someone described a similar problem here , but its solution does not apply to my case. (顺便说一句:有人在这里描述了类似的问题,但其解决方案并不适用于我的情况。

Until Java EE 7 only EJB was transactional and the @Transactional annotation didn't exist. 在Java EE 7之前,只有EJB是事务性的,并且@Transactional注释不存在。

Since Java EE 7 and JTA 1.2 you can use transactional interceptor in CDI with @Transactional annotation. 从Java EE 7和JTA 1.2开始,您可以在CDI中使用事务拦截器和@Transactional注释。

To answer your question about the best type of bean to use, the answer is CDI by default. 要回答有关要使用的最佳bean类型的问题,默认情况下答案是CDI。

CDI beans are lighter than EJB and support a lot of feature (including being an EJB) and is activated by default (when you add beans.xml file to your app). CDI bean比EJB轻,支持很多功能(包括作为EJB),默认情况下会激活(当你将beans.xml文件添加到你的应用程序时)。 Since Java EE 6 @Inject supersede @EJB . 由于Java EE 6 @Inject取代了@EJB Even if you use remote EJBs (feature not existing in CDI) the best practice suggest that you @EJB once to inject remote EJB and a CDI producer to expose it as a CDI bean 即使您使用远程EJB(CDI中不存在的功能),最佳做法建议您@EJB一次注入远程EJB和CDI生成器以将其公开为CDI bean

public class Resources {

    @EJB
    @Produces
    MyRemoteEJB ejb;

}

The same is suggested for Java EE resources 对于Java EE资源也建议使用相同的方法

public class Resources2 {

    @PersistenceContext
    @Produces
    EntityManager em;

}

These producers will be used later 这些生产者将在以后使用

public class MyBean {

    @Inject
    MyRemoteEJB bean;

    @Inject
    EntityManager em;

}

EJB continue to make sense for certain services they include like JMS or Asynchronous treatment, but you'll use them as CDI bean. EJB继续对它们包含的某些服务(如JMS或异步处理)有意义,但您将它们用作CDI bean。

The javadoc of Transactional says: Transactionaljavadoc说:

The javax.transaction.Transactional annotation provides the application the ability to declaratively control transaction boundaries on CDI managed beans, as well as classes defined as managed beans by the Java EE specification, at both the class and method level where method level annotations override those at the class level. javax.transaction.Transactional注释为应用程序提供了声明性地控制CDI托管bean上的事务边界的能力,以及Java EE规范定义为托管bean的类,在类和方法级别,方法级别注释覆盖了班级。

So, your assumptions are wrong. 所以,你的假设是错误的。 EJBs, until Java EE 6, were the only kinds of components to support declarative transactions. 直到Java EE 6,EJB才是支持声明式事务的唯一组件。 The Transactional annotation has precisely been introduced in Java EE 7 to make non-EJB, managed CDI beans transactional. 事务性注释已经在Java EE 7中引入,以使非EJB,托管CDI bean具有事务性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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