CDI With Or Without EJB 3.1
Java EE 6 comes with EJB 3.1 and CDI. You could work exclusively with EJB 3.1 or CDI, but you will not end up with the simplest possible solution. CDI comes with typesafe and scalable (=start easy, but sky is the limit) DI, events, decorators and "glue" logic.CDI, however, is missing some EJB 3.1 features:
- Asynchronous, transactional execution with Future support
- Pooling: important for throttling and prevention of denial of service attacks
- Monitoring - all EJBs are exposed via JMX and can be so monitored with JConsole
- Declarative, "Convention Over Configuration" transactions. Without EJB 3 you will end up in a considerable bloat
With CDI and its integration of the JavaEE Interceptors (via the JavEE6 InterceptorBinding) something like @Transactional, known from the Spring Framework can be created in an esay manner.
A full-blown version of such a Transaction-Interceptor will be part of the MyFAces CDI extension project, called "CODI".
In the meantime, a very simple version of such an artifact is located here:
(taken from the Apache OpenWebBeans project's reservation example)
Posted by Matthias Wessendorf on September 14, 2010 at 03:00 PM CEST #
yes - but why to implement or integrate a custom interceptor, if the transactional aspect is already a part of EJB and both are a part of Java EE 6 / even WebProfile?
Its cool stuff - but why you are doing that?
Btw. (I did it also several time in my leisure, but never for "real world") :-)
Posted by adam-bien.com on September 14, 2010 at 04:11 PM CEST #
That way I do not need to ship EJBlite with Tomcat/Jetty.
Posted by Matthias Wessendorf on September 14, 2010 at 04:38 PM CEST #
if you just have a CDI container and nothing else - a custom "Transactional" aspect is not only cool, but also useful :-),
Posted by adam-bien.com on September 14, 2010 at 05:57 PM CEST #
The problem with CDI + EJB is the lifecycle mismatch as explained in this post: http://www.germanescobar.net/2010/03/whats-so-wrong-with-ejbs.html.
That's why people are trying to stay away of EJB's. They make the learning curve steeper. I'd go with CDI + POJO's + Interceptors instead.
Posted by German Escobar on September 14, 2010 at 06:20 PM CEST #
Hello Adam, i want to know it will be a second edition of your book
in Real World Java EE Patterns - Rethinking Best Practice where explain the JEE 6 Best Practices ?.
Posted by Eudris Cabrera on September 14, 2010 at 06:42 PM CEST #
stay tuned :-)
Posted by adam-bien.com on September 14, 2010 at 07:04 PM CEST #
You can inject a @Stateless into @RequestScope @SessionScoped or @Singleton without any problem. You can even declare a @Stateful beans as @SessionScoped And you can inject CDI beans into EJBs. The integration between EJBs and managed beans is clearly defined.
I didn't had any problems so far in real world (also not in stress tests, synchronization problems etc.).
What problems do you encountered more specifically?
Posted by adam-bien.com on September 14, 2010 at 07:10 PM CEST #
I've seen people, for example, declaring @Stateless within a @SessionScoped bean, which is, a lifecycle mismatch. I know this is trivial for JEE experts but this is a problem for newbies, believe me. And it is something that can be avoided. Why do they have to learn two lifecycles and their valid combinations?
What we really want are the features of EJB's without introducing a new lifecycles (let others manage it, in this case, CDI). So, we want to say that a POJO is @Synchronized, @Transactional, etc., which is much more cleaner/clear. What do you think?
Posted by German Escobar on September 15, 2010 at 04:47 AM CEST #
and I've seen people declaring @Stateless @Singleton or even better: @ConcurrencyManagement(Bean) @Stateful. You just cannot prevent this. If you have problems to understand that a Stateless Bean is not stateful :-), you will also have a hard time to understand qualifiers, stereotypes and especially implement transactional aspects (you have to implement them without EJBs)
What I do in projects: just provide a small working example as a blueprint with short documentation in the wiki. It works really well.
In the future CDI should come with aspects currently available with EJB 3.1. The EJB 3.1 spec could be replaced with few stereotypes then and the EJB "component model" entirely removed.
But now: the easiest possible solution is using an EJB 3.1 as a boundary and inject CDI beans into it. You could also use entirely EJB 3.1 if you prefer (=don't need the sophisticated DI, events and stereotypes).
thanks for your comment - really appreciate it!,
Posted by adam-bien.com on September 15, 2010 at 05:28 PM CEST #
Definitely. That's the easiest way right now ;-)
> In the future CDI should come with aspects currently available with EJB 3.1. The EJB 3.1 spec could be replaced with few stereotypes then and the EJB "component model" entirely removed.
Agree. Maybe not included in the CDI spec but a separate spec would be better; just to leave CDI as simple as it is right now.
Posted by German Escobar on September 15, 2010 at 09:42 PM CEST #
its a pity - now we have full agreement and the discussion probably ends here :-).
Thanks for your interesting input!,
Posted by adam-bien.com on September 15, 2010 at 10:24 PM CEST #
Pity it doesn't work worth a damn in Glassfish 3.1b19 and later. See, for example, https://glassfish.dev.java.net/issues/show_bug.cgi?id=11888, which is just sitting there, unmaintained, in violation of the Java EE specification. One of many reasons I made sure to rip all vestiges of CDI out of my Java EE application. Can't wait till it works properly, but I'm not holding my breath.
Posted by Laird Nelson on September 17, 2010 at 10:20 AM CEST #
didn't tested 3.1b19 yet. I'm working with 3.0.1 - it works really good. I will actually show EJB 3.1 - CDI integration on stage: http://www.adam-bien.com/roller/abien/entry/my_javaone_sessions_and_interactive
Will ping the glassfish guys at JavaOne :-),
Posted by adam-bien.com on September 17, 2010 at 12:36 PM CEST #
I don't often do this but can you tell me why when you inject @Stateful SB's into @RequestScoped beans that a new instance of the Stateful SB is created every request ? This never happens with Stateless or Singleton's and I cannot find an answer anywhere and it appears very confusing when you are trying to pickup the new spec.
Posted by Chris on October 21, 2010 at 05:06 AM CEST #
Probably because your stateful bean is considered as @Dependent bean.
Posted by Den on April 24, 2012 at 03:20 PM CEST #
I am new to CDI and EJB 3.1.
Can you please post an article regarding Integration between "CDI & EJB" and how this example could be run in Application Client Container(ACC),weld-se Contailner and in java EE-6 container ?
Posted by Dhruba on May 29, 2012 at 02:55 AM CEST #
CDI seems to be a glue between JSF and EJB. We shall
look at CDI in its entirety, i.e. like this:
Especially the uploaded EJB+CDI test application.
The absence of blog-entries or articles around
EJB and CDI shows, that there is something
Posted by GroovieMan on January 29, 2013 at 08:12 PM CET #
"CDI seems to be a glue between JSF and EJB"
I'm absolutely with you!,
Posted by 192.168.0.100 on January 30, 2013 at 05:51 PM CET #
Today I saw some code were a @SessionScoped bean was injected into a @Stateless EJB.
Up-to-now my understanding was that such a constallation will lead to unpredictable behaviour, since the stateless EJB is not stateless anymore.
After googling that topic I figured out that may people stating, such a constallation is absolutly valid.
I can't belive that's true. How is this working?
Do you have an advice for me?
Thanks and best regards. Juergen
Posted by juergen on December 23, 2014 at 03:27 PM CET #
a good question, I'm going to cover it at the next: http://airhacks.tv,
thanks for asking and commenting!
Posted by Adam Bien on January 11, 2015 at 08:15 AM CET #
@Juergen: As CDI creates a proxy for scoped beans, @Stateless beans do not hold direct reference to a CDI bean and therefore they do not hold the state. A correct instance of @SessionScoped bean is always injected according to the current context.
In the CDI world, you may treat @Stateless EJBs as dependent beans, which may be reused (shared) for multiple beans if EJBs are pooled. This sharing may cause conflicts only when CDI bean with dependent scope is injected. Beware that also all predefined CDI beans are dependent, including Principal (http://docs.oracle.com/javaee/6/tutorial/doc/gmgli.html). You should always put such beans into a bean with some scope other than dependent.
When pooling is disabled and EJBs are always recreated, they behave exactly like dependent scoped beans. This is the default behavior for example for Wildfly 9 server, but I would not count on it as it is not portable.
Posted by ondrom on September 19, 2015 at 10:50 AM CEST #