selecting implementations with WebBeans
The previous WebBeans injection tutorial relied on a single implementation of the ATMTransport to work, but a full implementation would need need to select an implementation. In Rick Hightower’s dependency injection introduction, the ATMTransport was selected from one of three implementations: StandardATMTransport, SoamATMTransport, and SimulationATMTransport. Today I’ll show how to do this using WebBeans.
WebBeans enables beans based on a @DeploymentType, where the default bean is enabled as a @Production deployment type. In the previous example, the StandardATMTransport automatically used the @Production deployment type and was automatically enabled and injected. Now, though, I want the transport implementations to be disabled by default and only enabled when they’re configured.
In the example, I have an ATM implementation that needs an ATMTransport. Because my design expects a single, unique ATMTransport configured in the system, I use the @Current binding annotation to inject the transport. So the @Current binding does more than marking an injection point, it documents my design intent for the whole system. (This self-documenting philosophy is important throughout WebBeans, because improving our code organization and clarifying its intent is key to designing and maintaining any significant application. Our code needs to be meaningful, not just functional.)
public class AutomatedTellerMachineImpl implements AutomatedTellerMachine {
@Current
private ATMTransport transport;
...
}
To disable by default, I’ve created create a custom @Disabled deployment type annotation and marked the disabled implementations. The @Disabled annotation conveys my intent: this bean is disabled by default and must be configured to be enabled. In the XML configuration, I can override the deployment type to enable it. This custom annotation lets me document in code the intended purpose of the bean and even express it automatically in the JavaDoc. For example, I can also create a @Mock deployment type for testing, which will document my testing beans.
I can select an implementation by overriding the deployment type in the web-beans.xml, choosing an enabled deployment type, like the standard @Production type. In the configuration below,
the <example:StandardATMTransport> configures the StandardATMTransport bean, and the
<Production> tag overrides the @Disabled deployment type annotation.
<WebBeans xmlns="urn:java:javax.webbeans"
xmlns:example="urn:java:example">
<example:StandardATMTransport>
<Production>
</example:StandardATMTransport>
</WebBeans>
In the configuration, it’s important that <Production> selects the @javax.webbeans.Production annotation because the WebBeans configuration mirrors the class and annotation definitions, avoiding keywords and special cases when possible. In other words, since the JavaDoc for javax.webbeans and my example package documents the XML configuration, I have self-documenting XML configuration.
For the code, I’ll mark the StandardATMTransport and SoapATMTransport as @Disabled, and mark the SimulationATMTransport as @Mock, since it’s a testing interface. Since neither @Disabled or @Mock are enabled by default, the only active bean will be the one I select in the web-beans.xml.
@Disabled
public class StandardATMTransport implements ATMTransport {
...
}
@Disabled
public class SoapATMTransport implements ATMTransport {
...
}
I’ve marked the SimulationATMTransport as @Mock, since it’s intended as a testing implementation. Both @Disabled and @Mock will disable the bean, but @Mock shows the intended use more clearly. This self-documenting approach is key to the WebBeans philosophy.
@Mock
public class SimulationATMTransport implements ATMTransport {
...
}
package example;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
import javax.webbeans.DeploymentType;
@DeploymentType
@Documented
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface Disabled {
}
Now I’ve created and configured the ATMTransport out of a selection of disabled drivers, and more importantly, I’ve communicated my design intent for my driver classes.
Conclusion
Some things to note about the WebBeans example:
- Annotations are used to convey intent: they are semantically meaningful.
- XML is only needed to override defaults. Since WebBeans automatically scans and enables simple beans by default, only changes to the defaults need to be configured.
- Since the configuration XML is a direct reflection of the annotations and beans, including the WebBeans annotations themselves, the JavaDoc serves as XML documentation.

November 22nd, 2008 at 3:13 pm
Great example using WebBeans… With Spring you can also use user-defined annotations…. Thanks for writing this. And thanks for using my example as a guide. It makes it easier to follow this one.
Have you checked out the Crank framework? http://code.google.com/p/krank/
It is what I do when I am not consulting, training or writing… Let me know what you think.
November 22nd, 2008 at 3:14 pm
WRT: It makes it easier to follow this one.
What I meant was it makes it easier for me to follow….. Without the “for me”, I just sound like an ego maniac…
November 24th, 2008 at 11:37 am
Nothing wrong with being an ego maniac :). And thanks for writing the tutorial, it made these notes much easier to write.
I haven’t looked at crank yet, but scanning it looks very interesting.
I’ve been putting off the direct comparison with Spring because it’s becoming increasingly difficult to pick a fair flavor to talk about. If I talk about the old-style <bean>, or <property>, then I’m skipping the annotations or p:foo variation or the custom syntax. And yet the old-style <bean> is still the most common. For exaimple, if you look at the Spring/OSGi proposal in OSGi 4.2, they still use old-style Spring syntax, so it’s certainly not deprecated. I might cheat and write two separate comparisons.