We have an annotation for this!
When once annotations has been introduced, they used to be just a metadata storage for the real code developers would write. Java EE Contexts and Dependency Injection mechanism it not well-known yet, but allows quite easy and exciting annotation-driven injections of POJOs in managed beans. No more constructor based injections, no ladder-styled signatures and dependency hell, CDI will handle everything in a simple declarative manner.
For example, assume we want to inject two clock components: UTC clock and local timezone clock. In plain Java it will look like:
@Stateful
class Component {
private Clock utc;
private Clock local;
public void setUtc(Clock utc) {
this.utc = utc;
}
public void setLocal(Clock local) {
this.local = local;
}
}
component.setUtc(Clock.systemUTC());
component.setLocal(Clock.systemDefaultZone());</code>
Java CDI allows us to extract dependency declaration on per-project basis and inject those clocks based on annotation contexts. First of all, we declare contextual annotations for UTC and local timezones:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
public @interface UTC {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
public @interface LocalTime {
}</code>
@Qualifier
annotation tells CDI that @UTC
and @LocalTime
are contextual annotations capable of injected interfaces implementations separation.
Then we declare injections provider capable of supplying Clock implementation based on context qualifier:
@Singleton
public class Producers {
@Produces
@UTC
public static final Clock UTC_CLOCK = Clock.systemUTC();
@Produces
@LocalTime
public static final Clock LOCAL_CLOCK = Clock.systemDefaultZone();
}
From now on, CDI will get Producers.UTC_CLOCK
and Producers.LOCAL_CLOCK
on every injection marked with @UTC
or @LocalTime
qualifier respectively, allowing us to focus on application logic, not dependency injection infrastructure. For example, let's rewrite our Component to use CDI mechanisms:
@Stateful
class Component {
@Inject
@UTC
Clock utc;
@Inject
@LocalTime
Clock local;
}
Once Component bean instance is created, both utc and local fields will be filled with Producers.UTC_CLOCK
and Producers.LOCAL_CLOCK
respectively. No other actions required, CDI will make all the magic to make this work.