EJB 3.0 - Is it going to solve our problems?
UPDATE: Brazilian Portuguese translation / tradução para o português do Brasil no JavaFree
To begin with, I must congratulate the JSR-220 EG for their braveness. I can't think of any spec in the JCP that has been changed in such a dramatic way as this one. Linda said during the last JavaOne she intended to kill deployment descriptors and to simplify the programming model as much as possible. However, I never thought the EG would take that words so seriously and would drop the current model - ok, "drop" may sound too strong, but, even though they are going to support it, anyone writing code will prefer the new API unless there is some political/business objection for not doing so - for a POJO-based one.
So, now it's time to explain why I think we can simplify EJB 3.0 even more and give tremendous flexibility for the hardcore developer without making any EJB look cluttered or ugly (some people said Linda stated it still will be necessary to use the "old model" for some hard stuff; this sounds extremely unpleasant to me, I must say). The new programming model for EJB 3.0 seems to rely heavily on annotations. This certainly is a good thing compared to the deployment descriptor hell, but there are two things missing that would make turn this idea into something really powerful:
- Annotation processors: what do you do when the security capabilities of your app server are insufficient or inadequate for your needs? Change vendors? But what if the first vendor has a feature you need, but that the second one doesn't offer something similar? That's one of the flaws we're still keeping: vendors will implement the spec in some way that may not be what you need/want. And what can you do about it? Almost nothing, besides throwing your app server away or relying on a non-standard solution - sometimes, it means not using EJBs for a part of your project they'd be the perfect fit if only that feature had been implemented in a better way by your app server vendor. What if you could write implementations for the services an EJB container should offer? You may now say: "hey, but that's exactly what I've paid for", but it's often needed. Vendors are not capable of foreseeing every need you'll have. It'd be even better if we had a standard spi for all the services an EJB container is supposed to provide. In that way, you could swap small components or, even better, write a decorator around a app server specific implementation so that you could only provide the one missing functionality you need - instance-based security for entity beans, for example - and delegating the other features to your app server default implementation. Imagine how many problems you would be able to solve if you could change or augment the functionality provided by an application server in a standard way! I can tell you it would solve around 80% of my issues with EJB. The other 20% would be solved as shown below:
- Support for custom, user-defined annotations: frequently, we need to add services to our components that are not part of the EJB spec. If this feature is not so domain-specific, chances are some vendor has provided support for it. And then, welcome to vendor lock-in! You are left with two choices: go for vendor lock-in or write terrible code just in order to have a portable application. Wouldn't it be nice if you could solve it in a elegant, portable way? Custom annotations and custom annotation processors could be the answer. Imagine if you could write an small session in an deployment descriptor declaring a custom annotation and an implementation of an interface, AnnotationProcessor, that's capable of handling it. You could define your own implementation or simply delegate the processing of your custom annotation to a class provided by your container of choice. You could get portability and still benefit from non-standard features your vendor offers you. Annotations without properly-configured processors would be simply logged at deployment time, since they could be there for a nice reason - for example, you might want to "tag" your methods for some functionality first and implement it after; or maybe that annotations are meant to provide enhancements during runtime and don't represent essential services, like caching, for example.
I am pretty sure some people will say: "Spring (put your favourite lightweight? container here) can do that" or "this is a case for an AOP-based container". I totally agree with the first and I think an AOP-based container would be a good implementation, but the real point is: these are not standards. There is only one Spring - some people might be writing a few implementations for its interfaces, but they are just some people, not major vendors with hundreds or thousands of experienced employees working full-time on that - and AOP frameworks I know are completely different from each other. If we could come to agreement on what basic services an EJB container should provide, a SPI for them and a way to plug custom annotations and to process them, we could get ease of use with maximum flexibility and ability to choose without limiting you to rely on a single vendor for the rest of your life. Vendors would have to provide amazing implementations for each EJB container service and offer a lot of high-quality custom services if they wanted to keep up. A new market of service providers would arise and we'd see a constant increase in the quality of each comercial container out there.
Besides that, there's another idea that annoys me: who said an interface is always a good thing? Even if the container generates it, I am sure I'd be glad to write:
OrderService os = new OrderService();
instead of using a container-generated interface for my sesion bean. Plain Java code is great! If I don't need to use some
javax.ejb.SessionBeanFactory or to have use a DI container in order to provide interface implementations to my client components, I can hire almost any person who knows basic Java to work with me in my enterprise projects and knowing I won't have to teach them a thing! That is easy of use. Interfaces are needed for a lot of reasons but, as I stated above, they are not always wanted.
Several techniques would be necessary to make these ideas work inside the container - a post-compiling phase, CGLIBed classes, etc. - but that's not my concern at the moment. If I am able to have a similar architecture right now using AspectWerkz - one of the greatest pieces of software I've ever came accross, with incredible support -, why can't enterprise vendors provide something similar?
I am sure that some people would still object saying this would be best addressed by an AOP JSR and a lightweight container JSR, but let's face it: EJB 3.0 started one year ago and it's expected to be finished next year; if we start these other JSRs now, when are we going to see a compliant implementation of them? Besides that, I am not asking for full AOP support; I just want annotation processors and maybe vendors would need to use AOP, CGLIB and/or custom class loaders for achieving my plain Java model. It may not be perfect, but it's better than what we have now in my opinion. What vendors would have to do to support the features doesn't concern me; all I want is a standard solution, with competing implementations, that offers me simplicity, total flexibility and portability.
I do hope someone from the JSR-220 EG reads this blog and post some comments about these ideas.
PS: I really think the JSR-220 EG members are doing great things and think their work must be acknowlegded and praised. They are doing the right thing, although it's hard to do. I just want more :-D. Don't get me wrong: Spring rocks, as well as Pico/NanoContainer. And AspectWerkz will be part of all my future projects unless my client objects, you can be sure. :-D
PS2: This post is inspired by the fact that, several months ago, I posted here some suggestions on how to improve the spec. They were not as drastic as the ideas presented during the last TSSS, but they addressed the most annoying issues I had to face with EJB at that time. Ease of use was, at that time, in my mind, very important for wide adoption, but my post reflected things that even XDoclet and my own frameworks couldn't solve in a decent, clean, non-application-server-dependant way. What amazes me now is that apparently most of those issues aren't going to be addressed by the new spec. Since I wrote that entry, I've been involved in lots of projects and got to know the now popular lightweight frameworks, besides getting my hands dirty with AOP. And I must say that, after playing with these ideas for a while, I got to understand things really must be simpler for the regular work - 95% of it -, but that I still do need a lot of flexibility. And I don't want this flexibility to make my code look harder when I use fancy, obscure, powerful features; I want my business code to always look as simple as the rest of my codebase. The only complexity I want to face is the inherent complexity of my business problem.