Sunday, October 28, 2007

Web Beans and Modules!

After some good work, the JSR-299 group released an early draft, first published on Gavin King's blog, and now on the JCP site.

The spirit of Web Beans is really good, and the way the annotations came out is very promising. I have nothing to say but compliment the Component Types, Component Bindings, Scopes, Injection, and Interceptors. The Event has the good approach (Event type filter), but looks young at the moment.

Web Beans is really the state of the art "Educational Framework". The technical base is already explored (Guice, Spring, Seam) and is not so complex, but the impact on the developer thinking is really significant. Like every good "Educational Framework" (Struts, Spring, Seam), it makes it harder to do the "bad thing" (hacking, ugly coupling) than the right one (framework driven injection and loose coupling).
I know that if developers start to use these Annotations their code will get cleaner, more readable and manageable.

But, reading through the specs and especially, "4.4.2 Interceptors bindings" and "8. Packaging and configuration", I felt like something was wrong: Where are my Web Beans modules?
I don't want to get into the argument of OSGi or JSR-277, but I was expecting a more modular approach of Web Beans Injection.
What I mean, is that I would like to see a Web Beans "core" defining all the above Annotations for a pure J2SE environment. This would be the specification of how to use Dependency Injection Annotations. On top of that, another specification on how to provide "Components Provider/Injectors" for JEE, JSF, EJB, MDB and so on.
For example, I want to be able to do:
@Log
private Logger log;


just by adding log4j-web-beans.jar in my classpath. In this jar Log4J will provide the Web Beans Component for my class and my environment.
So, with this approach all the EJB, JSF & JEE stuff that really don't have to be there, can be specified separately as: jee5-web-beans.jar, ejb-web-beans.jar, mdb-web-beans.jar, etc.
I think it will make the specifications easier to read and a lot more flexible for all the great future components ;-)

Since I don't like people that complain without proposing something of their own, I tried to see how to do this with the current specification. And, basically it's not missing much.
Today in EJB3 environment, the first thing I do is creating an Interceptor that can inject components from Spring or other sources in my Session Beans. The injection is based on my project level Annotations and it bridges Spring and EJB3 nicely.
So a first solution (not good but...) is to use javax.interceptor.InvocationContext. If the Web Beans container is adding some entry in getContextData(), I can find out the Component Type, the Scope, and other information and decide how to populate all the @Log fields.

A nicer solution will be to have Annotations specified by JSR-299, that will allow me to write something like:
@ComponentProvider
public class Jee5ComponentProvider {

@Provides(EJB.class)
public Object getEJB(WebBeansContext wbc) {
try {
return new InitialContext().lookup(
wbc.getDestinationField().getType().getName());
} catch (NamingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

Here I really did not investigate enough, but I know I'm missing @ComponentProvider and WebBeansContext in the current specification.
What do you think?

3 comments:

Gavin said...

The current internal draft of the spec has an interface called Component, which you can implement, and an API called Container, where you can call addComponent(Component).

Is that what you're looking for?

Frederic Simon said...

Yes, that will help for Log4J that can declare a "@Produces Logger" component.
But for example, with my client EJB stubs, I need to pre-load the Web Beans container before my clients Web Beans components are loaded.
I will like a more @Produces system.
But here is my problem, if @EJB is used for declaring EJB client fields, what is the equivalent of the EJB annotation in Web Beans terms.
IMHO it's close to a Component Binding. The problem is that my producer method (JNDI lookup) does not know "a-priori" the return type, and need the information for doing the lookup. I think it's a generic problem not only for EJB clients.
So, trying to be clear ;-), I'm missing a WebBeansContext interface that provide the injection context to a producer method.
Realy don't know if I'm clear ;-)

Frederic Simon said...

Actually for Logger you need to know the class it will be injected into. So same thing: A need for an injection context on producer methods.