[jsr-314-open] getting behind CDI

Jeremy Grelle Jeremy.Grelle at springsource.com
Fri Dec 18 21:08:54 EST 2009


Dan, I totally respect your desire to push CDI as an integral part of the "native Java EE" or rather the "Java EE 6 Web Profile Container" programming model, but I would like to offer a slightly contrasting point of view.  See my further points inline below.      

On Dec 17, 2009, at 8:23 AM, Dan Allen wrote:

> I feel strongly that, as a group, we should provide a consistent recommendation regarding the programming model of JSF by getting behind CDI. Now, I realize there are Spring developers and supporters on this EG. So, before going any further, I want to clarify that the point I am making relates specifically to the native Java EE 6 technology stack. Spring has always been a strong alternative to the native Java EE programming model and continues to be a great companion of JSF. The common rival that we want to downplay is JSF managed beans.

First off, I agree that the ultimate goal of pointing users away from the JSF-managed bean model is a good thing.  That said, we (myself and Keith along with the rest of the Spring team whom we represent) have our reservations about CDI.  So while I agree that the ultimate goal is a good one, I just want to be clear that I am slightly wary of this getting turned around and becoming a public statement of, "The JSF EG thinks you should use CDI."  If some of the members of the EG want to individually make that push, that's their right, just as it is ours to say we don't see a great benefit to choosing CDI over Spring. What I would really like to see is us figuring out the most possible common ground between CDI and Spring when showing examples that are alternative to the JSF managed bean facility. 

I really want to make it clear that we don't see it as an "us vs. them" thing when talking about Spring and Java EE on the whole.  Spring has always provided first-class integration with a wide range of the individual parts of EE, and we continue to do so with EE 6 beyond just JSF 2 as evidenced by our support of specs like JSR-330, JPA 2, Bean Validation, javax.annotationManagedBean, etc. in the recently finalized Spring 3.0.  The major difference being that we enable the use of these pieces in a completely modular and portable way that is just as powerful in a lightweight servlet container like Tomcat as it is in a full-blown commercial app server like WebSphere or WebLogic.  The benefits are evidenced by the fact that you can easily use many of these EE 6 pieces *today* with Spring 3.0 even in a container like WebSphere 6.1 that is still quite widely deployed and is only J2EE 1.4 compliant.      
I'm getting off-topic, but I just want to make the point that we are not anti-EE 6.

> When JSF was created, no other facility was available for defining contextual managed beans. As of Java EE 6, there is now a platform-wide definition of a managed bean.

I assume you mean javax.annotation.ManagedBean, right?  As I mentioned, we do support this in Spring 3.0.  I believe this, as well as the other shared annotations such as @Resource, @PersistenceContext, @Inject, etc. could be our best common ground to use when showing JSF 2 examples.

> With the services of CDI, there is a way to discover, produce, scope, inject, name and override beans. All of a sudden, the injection facility, and limited number of services in the JSF managed bean facility looks rudimentary in comparison. And the reality is, before CDI, most developers likely used an alternative bean container anyway (probably Spring) to define managed beans. So the JSF managed bean facility has been falling out of favor for a long time.

Right, but are you saying we should all tell developers to use CDI instead of Spring now even if they are already happily using Spring?  I just don't see CDI being a clearly better alternative to Spring (in fact, I see the opposite, but I freely admit to being biased in that regard), and I don't know that we should have an opinion either way collectively as an EG.  Again, individual opinions will vary as to which one to choose, but as a group it seems we should generally remain agnostic, especially if our overall goal is to get as many people as possible to be successful with JSF 2.  

> But there is a more serious problem with continuing to recommend the use of the JSF managed bean facility. The injections do not take the scope of the injected bean into consideration. That means, you cannot inject a request-scoped bean into a session-scoped bean without causing the request-scoped bean to become a session-scoped bean through attachment. This is a very typical occurance with having managed beans in a web application. CDI not only keeps beans in different scopes loosely coupled, it hides the scope at the injection point.

I'd just like to point out again for the sake of contrast that Spring 3.0 supports the same sort of approach quite well.  We of course supported this previously with our "scoped-proxy" feature since back in Spring 2.0, but it had to be configured per-bean and was thus only slightly less annoying than configuring JSF managed beans.  JSF was a major part of the use case for making it work "by default" with annotation-based configuration without having to do extra work.

> But I won't be able to use CDI in a Servlet Container, right?
> 
> Not true. The CDI reference implementation (Weld) provides a single extension JAR (weld-servlet.jar) that you drop into your web application archive and you get a full CDI environment (you just don't get EJBs, but that's to be expected).

And by proxy you also don't get declarative transaction support, correct?  To me, that's an immediate show-stopper for any non-trivial application vs. what you get with Spring in a servlet container.

> Isn't CDI just a Red Hat thing?
> 
> Of course not. We should all be behind CDI. As the spec lead, Red Hat worked very hard to define a set of services for Java EE managed beans that would make the development of enterprise applications simpler. That's exactly the type of effort we all put in for the JSF 2 specification. (JSF 2 was forged by all of us collectively. CDI has the same story). So CDI is your technology, one that you can use in Java EE 6 or even outside of it. There is no reason to back away from it.

With all due respect, I still fail to see why we should *all* be behind CDI.

> Perhaps a lot of the heated debating over dependency injection turned you off, but that heated debate really made the whole platform better because EG members, like us, talked and worked things out in the end. 

Actually, what turns me off is that what we ended up with seems to only be partially worked out and is still a bit of a mess, to be perfectly blunt.  I'll elaborate more on that in my discussion of the examples below.

> @ManagedBean
> @RequestScoped
> public class BlogEditor {
>    @ManagedProperty("#{blogDao}") BlogDao blogDao;
>    // getters and setters required
> }

First off, I assume these (including @ManagedBean) are all from the javax.faces.bean set of annotations.  Agreed, in this particular example, I would not recommend this approach.  What about @ViewScoped though?  That's one of the more useful pieces of JSF 2 in my opinion.  I don't believe there is an out-of-the-box CDI-equivalent, right?  I would assume it's not hard to implement a custom @ViewScoped that CDI would recognize?      

> We want to show them:
> 
> @Named
> @RequestScoped
> public class BlogEditor {
>    @Inject BlogDao blogDao;
> }

So first of all, I think it would be great if we'd ended up with something like the above that would "just work" in both CDI and Spring.  But we didn't.  We do actually support the use of @Named as a class-level annotation like this in Spring 3.0.  But I'm curious, why in CDI do you recommend using @Named vs. javax.annotation.ManagedBean?  It seems to me like @ManagedBean has more clearly defined semantics at the class-level.

Then we're back to the problem of the scopes.  We of course support various scope annotations in Spring, and support something equivalent to your above example, but don't specifically support the CDI scope annotations.  What really has me a bit confused is why the CDI scopes don't use @Scope from JSR-330 and instead use the JSR-299-specific @NormalScope.  The JSF scopes don't either, for that matter, but I assume that's because 330 was finalized well after.  See, this is what I mean by it being a bit of a mess.  We've got some JSF-specific scopes, we've got CDI-specific scopes, we've got Spring-specific scopes, etc.  Spring can and will ultimately support the equivalent of all of the useful ones (including @ConversationScoped in the near future...I really wish we could have just relied on JSF or CDI for that), but it sadly seems like we ended up with more fragmentation rather than less.  

So in the above example, we at least have @Named and @Inject as commonly supported things.  I really wish there were one common, complete and portable set of scope annotations we could support in Spring, but there isn't.
  
> I'm asking you to consider my request to get behind CDI. 

I'm perfectly fine with a world where CDI and Spring co-exist peacefully.  Despite my own misgivings about CDI, I acknowledge that it appeals to some.  The goal of moving away from the JSF managed bean is a good one.  But as the collective EG whose goal is to see as much adoption as possible of JSF 2, and given the corporate realities of how soon most people are going to be using an EE 6 container, I don't see how we can be asked to promote it as *the* choice of the EG.    

Cheers,

Jeremy



More information about the jsr-314-open-mirror mailing list