问题描述
Java EE7由一堆bean定义组成:- Managed Bean 1.0(JSR-316 / JSR-250)
- Java 1.0的依赖注入(JSR-330)
- CDI 1.1(JSR-346)
- JSF管理Bean 2.2(JSR-344)
- EJB 3.2(JSR-345)
为了摆脱我心中的混乱,我研究了几篇文章何时使用哪种豆类。 EJB 的优点之一似乎是,它们独自支持声明性容器管理的事务(着名的事务注释)。我不知道,如果这是正确的。有人可以批准吗?
同时,我想出了一个简单的演示应用程序来检查这是否真的是真的。我刚刚定义了一个CDI bean( 不是 一个EJB - 它没有类级别的注释)如下,基于片段:
public class CdiBean {
@Resource
TransactionSynchronizationRegistry tsr;
@Transactional(Transactional.TxType.REQUIRED)
public boolean isTransactional(){
return tsr.getTransactionStatus()== Status.STATUS_ACTIVE;
}
}
现在,GlassFish 4.0的结果是这种方法实际上返回true,根据我的查询, 不按预期工作 。我确实期望容器忽略CDI bean方法上的@Transactional注释,甚至抛出异常。我使用新安装的GlassFish 4服务器,所以没有干扰。
所以我的问题是真的:
- 哪些bean类型实际上支持容器管理的事务?
- 只是为了好奇,我如何使用一个简单的演示应用程序来测试它,上面的代码是错误的?
(BTW:有人描述了类似的问题,但其解决方案不适用于我的情况。
由于Java EE 7只有EJB是事务性的,而 @Transactional
注释不存在。 Java EE 7和JTA 1.2可以在CDI中使用事务拦截器,使用 @Transactional
注释。
回答您的问题关于最好的bean类型,默认情况下是CDI。
CDI bean更轻并且支持许多功能(包括作为EJB),并且默认情况下激活(当您将 beans.xml
文件添加到您的应用程序时)。
由于Java EE 6 @Inject
supersede @EJB
。即使您使用远程EJB(CDI中不存在功能),最佳做法表明您一次注入远程EJB和CDI生产者将其显示为CDI bean
public class Resources {
@EJB
@Produces
MyRemoteEJB ejb ;
}
同样的建议用于Java EE资源
public class Resources2 {
@PersistenceContext
@Produces
EntityManager em;
}
这些生产者将在稍后使用
public class MyBean {
@Inject
MyRemoteEJB bean;
@Inject
EntityManager em;
}
EJB对于JMS中包含的某些服务继续有意义或异步处理,但您将使用它们作为CDI bean。
Java EE7 consists of a bunch of "bean" definitions:
- Managed Beans 1.0 (JSR-316 / JSR-250)
- Dependency Injection for Java 1.0 (JSR-330)
- CDI 1.1 (JSR-346)
- JSF Managed Beans 2.2 (JSR-344)
- 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). 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:
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. I did expect the container to ignore the @Transactional annotation on a CDI bean method, or to even throw an exception. I use a freshly-installed GlassFish 4 server, so there are no interferences.
So my question is really:
- Which bean types do actually support container-managed transactions?
- 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.
Since Java EE 7 and JTA 1.2 you can use transactional interceptor in CDI with @Transactional
annotation.
To answer your question about the best type of bean to use, the answer is CDI by default.
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).Since Java EE 6 @Inject
supersede @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
public class Resources {
@EJB
@Produces
MyRemoteEJB ejb;
}
The same is suggested for Java EE resources
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.
这篇关于JEE7:EJB和CDI bean是否支持容器管理的事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!