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

21,368

Solution 1

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.

Solution 2

The javadoc of Transactional says:

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.

So, your assumptions are wrong. EJBs, until Java EE 6, were the only kinds of components to support declarative transactions. The Transactional annotation has precisely been introduced in Java EE 7 to make non-EJB, managed CDI beans transactional.

Share:
21,368

Related videos on Youtube

SputNick
Author by

SputNick

Updated on July 09, 2022

Comments

  • SputNick
    SputNick almost 2 years

    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.

    • Mr_and_Mrs_D
      Mr_and_Mrs_D over 10 years
      "In order to get rid of the chaos in my mind", so true
  • SputNick
    SputNick almost 11 years
    Oh, now I see. I did actually confuse javax.ejb.TransactionAttribute from the EJB spec which is part of JEE5+ and javax.transaction.Transactional which was added in the new JTA 1.2 spec which is now part of JEE7. So, it's great news! If I got you right, this might then kill off the EJB layer for mid-size applications.
  • SputNick
    SputNick almost 11 years
    Yet another side note: Having transactional attributes from both JTA and EJB spec is then just another confusing DRY violation in the JEE ecosystem, right? Can javax.ejb.TransactionAttribute now be considered deprecated, even for EJBs?
  • Antoine Sabot-Durand
    Antoine Sabot-Durand almost 11 years
    No because EJB are Transactional by default (convention over configuration approach) so it's normal you get specific annotation. Plus you can do advanced transactions stuff with EJBs like a nested transactions or manage XA transactions. But remember when you need EJB it can (and should) always be a CDI bean. And yes CDI can replace EJB for a light application.
  • SputNick
    SputNick almost 11 years
    I see. However in my opinion, they should have centralized all transaction stuff in the JTA spec, and no more EJB-specific transaction handling. But let's stop discussion here. Thank you for your clarifications.
  • Martin Andersson
    Martin Andersson about 9 years
    I'd say use @Inject only if you want to let the container automatically deal with the "normally scoped" life cycle (all but @Dependent) of a @Stateful EJB and also let the container pass around the stateful reference for you. Otherwise, you might end up with illegally combined scopes (CDI 1.1, section 3.2) or try to lookup a @Remote EJB which will fail without the bloated hack posted in the answer above. Looking for an EJB? Use @EJB. Using @Inject makes sense only for @Stateful with a declared CDI scope.
  • Martin Andersson
    Martin Andersson about 9 years
    This source code comment might interest you. I'd like to emphasize that I think EJB:s should be pruned in the future and all the "services" they provide should be realized using meta programming, i.e. annotations. @Transactional is a good first step. Concurrency, pooling (?), role based security et cetera should all follow along. If so and if need be, each EJB session bean can be transformed into a @Stereotype.
  • Martin Andersson
    Martin Andersson about 9 years
    ..but of course. At that point, I bet the community will say "stop" in an effort to minimize complexity. More technologies will join Java EE in the future. JCache, data grids. NoSQL? And already, the learning curve is probably the most step of all frameworks available. "Invisible magic" add complexity and confusion. Even worse, it makes the developer unsure about his code. Who want to write code that "surely" works but "might not"? Things moving out from EJB into separate services are most welcome. I am competent enough to tie my own knots. But I need to know that they exist and how they work!