Wednesday, December 2, 2009

CDI/JSR-299 preparing to marginalize EJB... again...

Whew, it's been a while since I've started looking at what's new in Java EE 6, partially because I've been fiddling with the newest addition to the Java EE portfolio -- JSR-299, aka CDI, f/k/a Web Beans, and this one could be big... Let's start with a bang -- CDI will eventually push EJB to obscurity... yeah, big statement, I know, but here's why I believe this will happen:
  • CDI has the potential, I believe, to provide all of the most commonly used services that the EJB spec provides, and let's face it, this mean transactions, timers, asynchronous process with MDB's, and now Singleton Startup beans. It does not mean remoting, instance pooling, and most certainly not any of the old CORBA crap :) -- also note that I'm not referring to JPA here at all, now that it has been removed from the EJB spec (as it should be!)
  • The CDI spec comes in at 98 pages.
  • The EJB 3.1 spec (PFD version), comes in at 618 pages -- yikes!
  • The CDI spec is far more flexible than the EJB spec, allows for more interesting and transparent customizations, and is built specifically to support extensions.
  • CDI's mechanisms for injection (which it inherits from JSR-330, thanks to Rod and Bob!), is more consistent, inclusive and unified than EJB's/JEE 5's.
  • CDI's inclusion of Stereotypes provides an awesome mechanism to create a lightweight framework, without directly exposing any CDI api to the end user.
  • CDI's context support is very extensive, and is far more complete and useful than EJB's Stateless and Stateful beans. Plus, it finally gives us a standard between Request and Session scoped.
  • CDI's integration with JSF is far better than EJB's (ever had a manually remove a Managed Bean from scope because its' Stateful bean has completed its' lifecycle? Come on!).
  • CDI's event mechanism provides for extensibility and easy, lightweight asynchronous processing.
  • There's no such thing as CDI Lite :)
That's not a short list, and admittedly, it's very early to make claims like this... after all, the spec has just finally been approved, we have yet to fully see the quality of the implementations (three that I know about, Weld, CanDI and OpenWebBeans -- hey, how come they got to keep the name!?), we have yet to see how the closed-source vendors will handle it, etc., but when it comes down to it, the CDI spec is simply better suited for POJO-style development, using Object Oriented core design principals, and it was designed specifically with this in mind... Contrast this with EJB, which has over a decade of cruft to carry along with it, and actually prevents the use of OO techniques altogether (historically more-so than today, but it's still an issue), and I think the future becomes fairly clear... All-in-all, I see it as great news for the Java EE platform...

One final caveat, though -- EJB has risen from the ashes before, specifically with the 3.0 version... if the vendors still feel the need to continue to push EJB, then who knows what we'll see :)



Anonymous said...

With this line you are wrong “CDI's mechanisms for injection (which it inherits from JSR-330, thanks to Rod and Bob!)” because the mechanisms for injection is not present in JSR 330 this is let to the Injection Provider. The JSR-330 is mostly developed by Bob with some contributions by Rod. Other point to take is that SpringSource has not voted the JSR 317 (JPA 2.0), JSR 318(EJB 3.1), JSR 299 (CDI SpringSource did not vote the other JSR for Dependency Injection Why ?) and JSR 316 (JEE 6.0).

Matt Corey said...

Ok, a clarification is in order, then... CDI is built around the new standard injection mechanism for injection targets -- you use the standard @Inject, @Named, and @Qualifier annotations that (theoretically) all DI frameworks can support...

You're correct that CDI is a service provider for JSR 330, just like upcoming versions of Guice and Spring, and will therefore be relatively easy to port from one platform to another in the same way that porting from one JPA provider to another is an easier task than porting from JDO to Hibernate... we all know that much of this is only theory, and it's not as easy as deleting a 'beans.xml' file and creating an 'applicationContext.xml' file, but it reduces the changes that are necessary to get the job done...

As for why SpringSource didn't vote for those JSR's, I have no idea... but they didn't vote 'no' either, they simply didn't vote, and made no comment -- for all I know, the absentee ballot is lost in the mail... besides, Apache votes 'no' on nearly every JSR, but it's never on the merits of the spec -- it's a protest vote on part of Sun's interpretation of the JSR process... SpringSource's actions here tell me more that they have no interest in the spec than that the spec itself is defective...


Anonymous said...

Yes you are right "that they have no interest in the spec than that the spec itself is defective...", so SpringSource does not have to be part of an expert group if it is not interested in the specifications.

if you see JPA is of the interest of SpringSource and it did not vote and EJB 3.1 comes in the next version of Spring 3.0. So, Why ?

Gavin said...

"You're correct that CDI is a service provider for JSR 330, just like upcoming versions of Guice and Spring, and will therefore be relatively easy to port from one platform to another in the same way that porting from one JPA provider to another is an easier task than porting from JDO to Hibernate..."

Matt, this is just not true. *Nobody* is claiming that porting an application between JSR-330 implementations will be as easy as switching JPA implementations. No way, not a chance.

JSR-330 does *not* standardize dependency injection. Not at all. It standardizes the annotations you use to define an injection point, and leaves everything else undefined. It's a deeply problematic specification.

Matt Corey said...

@Anonymous -- why do they include support for EJB 3.1 in Spring, if SpringSource didn't vote for the spec? That's easy -- so Spring can be used for integration of EJB 3.1 projects, and/or become a system replacement, which is one of the original goals of Spring in the first place...

@Gavin -- you're right, nobody is claiming portability between JSR-330 implementations, and either am I... nor am I claiming portability between JPA providers in my example... frankly, it's a pain in the ass to port from one JPA implementation to another if you don't plan to do it from the beginning, however using the platform to get your API usage mostly consistent means that most of the work will be done on the mapping side, and the API usage will involve mostly tweaks (in JPA 1, which standardizes the EntityManager and similar API, but left much of the complex mapping details out)...

JSR-330 appears to provide some of the same benefits on a much smaller scale, although for DI only -- for a simple CDI-to-Spring swap, for example, one would have to replace their Producers with an application context wiring, for example, but the injection points would remain mostly consistent... as I say, this would only apply to the DI support -- any usage of events, interceptors, or even complex producers would require a significant effort...

As for it being a deeply problematic spec -- it's too early for me to say... it seems Mostly Harmless to me at this point, but then again, I didn't have to change a framework to support it at the last second :)


Gavin said...

On the subject of JPA portability, I think there were just two things that held us back in JPA1:

* the OR mapping options were a carefully chosen subset of what most implementations provided, but users weren't happy to limit themselves to that subset, and
* there was no criteria query API.

Now, JPA2 solves both those issues. In the case of the criteria API, I think that's a step forward, which is why I put in so much work on that. In the case of all the new OR mapping stuff, I'm afraid to say I think it's a probably a step backward. I think your "complex mapping details" are what I would call bloat and bad practices.

The extra mapping constructs that have been added in JPA2 are stuff that I would personally never use, that make the model more difficult to maintain and understand. But people have been sold this "transparent persistence" nonsense, and think they don't need to learn anything about data modeling in the abstract. IMO, JPA1 standardized almost all of the mapping features that people should actually use in practice. Apparently that wasn't enough. Everyone wanted additional ways to shoot themselves in the foot, and so now we have a bunch of extra OR mapping shit that I wash my hands of. Hibernate had all that stuff for years, and I have never once seen any of it improve the quality of a domain model.

Hell, I would never even use @ManyToMany in a real app. Instead, I would have an object to represent the association. 'Cos I've never, in the real world, seen a many-to-many association that doesn't need to carry additional information about the association. I would certainly never use crap like collections of primitive values.

Unfortunately, I lost the battle to convince people to create clean, simple, self-documenting object models that map cleanly to the relational tables. Instead we have headed down the path of encouraging folks to run off with their totally Java-centric view of the world, persisting maps of dates keyed by strings, and lists of strings with a database column holding the list index, and other such nonsense. Like I said, I wash my hands of it. JPA1 was my take on the correct scope.

Gavin said...

"JSR-330 appears to provide some of the same benefits on a much smaller scale"

No, it really doesn't. It's nothing more than window dressing. Seriously.

"As for it being a deeply problematic spec -- it's too early for me to say... it seems Mostly Harmless to me at this point"

As I've explained elsewhere, I definitely don't think it's "Mostly Harmless" to drop Java's historical commitment to "write once run anywhere". That's kind of the whole point of the JCP.

Germán Escobar said...

I must say that all this abstraction over abstraction is just a pain in the ass! JSR-330 is an abstraction with multiple implementations (CDI, Guice, Spring, etc). While CDI could have had its own unified component model, it is now abstracted to Managed Beans and EJB's.

¿What is the JCP trying to achieve with this? As I stated in this post, while every other language out there is trying to make things easier, we are just making it harder for developers (specially for the new ones).

IMO, we need a unified component model inside CDI based on POJO's with all the benefits of EJB's. We really need to keep it that simple!

I know this was the goal of CDI at first ... but not anymore! It is now part of this abstraction over abstraction scheme.

Matt Corey said...

@Germán -- I completely agree that we are in danger of having too many 'Managed Bean-like' abstractions... I'm not actually sure where some of this landed in the final versions, but at one point there was the new Managed Bean spec, an option portion of the JSF 2 spec called 'Faces Managed Beans', EJB's, and the CDI spec, which encompasses EJB's, Managed Beans (not the JSF ones, or at least I don't think so :) )... yikes!

One thing I like about CDI is that it does take these separate component model, and enables them to work together -- unifying them, in a way... it's not realistic to expect the JCP to throw away EJB's, JSF Managed beans, etc., and replace them all with CDI -- it is primarily made up of independent committees, after all, each of which could be succeptable to self-preservation concerns (note that I have no idea if this occurs, and I have no specific JSR's or individuals in mind with this -- I simply see it as human nature in this type of organization)...

I do think it needs to be taken a step further, with some of the EJB capabilities pulled out into the CDI level -- transactions and security are two obvious ones (you can read about my thoughts on transactions here... over time, I expect to see that EJB's will become useful for distributed apps, and for wrapping services which actually require resource pooling, JSF will hopefully drop their version of Managed Beans -- CDI looks to be poised to coordinate some of these changes, but that is yet to be seen...

As for JSR 330, I think that may be a future post -- needs more thought (on my part, not necessarily the spec writers :) )


Gavin said...

German, I don't think the problem you're describing really exists. It doesn't really matter, from the user point of view, whether "managed beans" are defined in the CDI specification, or in a different document. Any actual CDI implementation is going to include a built-in implementation of the managed beans spec. As a user, you don't really need to be aware of the boundary between the two specs.

In the end, the actual definition of a "managed bean" has turned out much the same as what it was when it was part of the 299 specification, but now it can be more easily reused by all the different EE specifications.

Germán Escobar said...

I think the problem even goes further Gavin. In an ideal world, we would just have POJO's annotated like this for example:

public class ... {

It should be a problem of the Application Server to resolve these services without having a third party framework to resolve them. It doesn't matter how many specifications define it. But if I have to say: "Ok, we can do this but we will need ..., and add some interceptors bindings ... or we can use EJB's ...", it starts to make it confusing. I know that for your guys is trivial, but it is not.

I agree with Matt that we can't expect the JCP to throw away EJB's. We'll have to live with it right now as it is. However, I think it is important to raise our voices instead of waiting to see the same mistakes in JEE7.

Gavin said...

"But if I have to say: "Ok, we can do this but we will need ..., and add some interceptors bindings ... or we can use EJB's ...", it starts to make it confusing. I know that for your guys is trivial, but it is not."

Look, I don't disagree that "aspects" like transaction management and certain other things that have been traditionally part of the EJB spec should not be generalized. Indeed, I've been arguing that they should be.

All I'm saying is that the new managed beans spec is the vehicle that enables that generalization. We don't want to throw all of these annotations into the CDI spec. In fact, the CDI spec should do a little bit less than it does today (the interceptor binding stuff needs to move into the interceptors spec once there is a JSR for that).

There are a couple of places that the transaction management annotations could live today, none of them quite perfect:

* the managed beans spec
* the common annotations spec
* the interceptors spec
* the JTA spec

But I think it's probably better if someone submits a specific JSR for this problem.

Matt Corey said...

Gavin makes a good point in that perhaps the CDI spec itself isn't the place for Transactional, Security, Logging interceptors, etc -- it sets up the framework to make it possible, but should every implementation of CDI be forced to implement it? Could there be a spin-off JSR, similar to JSR-250, the Common Annotations JSR, that could define a few standard pieces of functionality?

On the other hand, I could see this as being similar to the JSF component model market -- if someone can come up with a sweet set of interceptors that go beyond the old-style EJB functionality, can figure out how to integrate it really well with a web framework or other front end, and come up with a fancy term like 'Ajax', 'Web Service', or 'Web 2.0' the opportunity might be there to make a few bucks :)...

@Germán -- A Stereotype to wrap around all those annotations would be pretty slick :)...


Anna said...

Great and Useful Article.

J2EE Training

Java EE course

Java EE training

J2EE training in chennai

Java J2EE Training Institutes in Chennai

Java J2EE Training in Chennai

Java EE training

Java Interview Questions