Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

CDI Magic for Beginners

5.00/5 (2 votes)
8 Jul 2017CPOL1 min read 4.1K  
CDI magic for beginners

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:

Java
@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:

Java
@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:

Java
@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:

Java
@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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)