JEE7: Do EJB and CDI beans support container-managed transactions?
cdi, ejb, jakarta-ee, java, jta
Solution
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.
Problem
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.