domenica 31 maggio 2009

Web Beans - Part I: Redefining Dependency Injection

Dependency Injection has been around for quite a while, initially spread by the popular Spring Framework, but recently has been revamped with new ideas coming from the open-source community, especially JBoss Seam and Google Guice.

In the last year the various contenders (or at least some of them =) have joined their efforts to produce a java specification, JSR-299, named Web Beans.

Let's see why Web Beans (or simply WB) promises to be the new java revolution.

WB expands the Dependency Injection pattern offering a DI that is:
  • strongly typed
  • deployment targeted
  • contextual

The purpose of DI is to enhance loose coupling of client (the one that gets the bean injected) and server (the injected bean).

With Classic Dependency Injection, the client is not required to manage the construction and wiring of the client.

With Web Beans Dipendency Injection, the client is not required to manage the lifecycle of the server object, and to take care of the actual deployment environment.

Or, quoting WB manual, "This approach lets stateful objects interact as if they were services".

Let' see WB in action.

STRONGLY TYPED
WB enforces strong typing using binding annotation.

To inject a generic PaymentProcessor we use @Current:
@Current
PaymentProcessor paymentProcessor;
If we need to pay by check or credit card, we exploit a user defined annotation (called binding annotation):
@PayByCheck
PaymentProcessor chequePaymentProcessor;

@PayByCreditCard
PaymentProcessor creditCardPaymentProcessor;
The feature is the same as Guice binding annotations, or Spring custom qualifier.
What is different from Spring, is that no dependency resolution by name is allowed, since using a string would sacrifice the benefits of typing (compiler check, IDE refactoring, etc.).

But the most powerful feature here is the ability to combine Binding Annotations to produce elegant results:
@Asynchronous
@PayByCheque
PaymentProcessor processor
Can't you see how nice? No more stupid bean names like asyncByCheckPaymentProcessor !!
And it enforces the correct semantic too: in this case we are sure that we will pay by check and asynchronously.

DEPLOYMENT TARGETED
What if our web beans should be deployed differently in certain environments?

For example we would like to mock our payment processor in an integration testing environment.
We can specify this through a user defined annotation (called deployment type):
@Integration
public class MockPaymentProcessor implements PaymentProcessor {
...
}
Then through the web-beans.xml we say we are in the integration environment (i.e. we enable the deployment type):
<webbeans>
<deploy>
...
<integration />
</deploy>
</webbeans>
And magically every time a client asks for a PaymentProcessor, he will receive a mocked instance !

CONTEXTUAL
This is probably the most innovative feature, directly inspired by JBoss Seam.

More to come...

Nessun commento: