Contexts & Dependency Injection for Java

CDI 2.0 Early Draft Review 1 released

Posted by Antoine Sabot-Durand on Jul 03, 2015 | Comments

After eight months of work, the CDI 2.0 expert group is pleased to release this first draft of CDI 2.0 specification for community review. This draft contains important and long awaited features that will change CDI as we know it.

But these features are still proposals and we really need your feedback to know if the way we specified them fits your needs. Let’s check what’s on the menu.

CDI runs now in Java SE

One of the oldest request was the support of Java SE in CDI. Since the beginning the two main implementations (JBoss Weld and Apache OpenWebBeans) proposed proprietary solutions to use CDI in Java SE.

Then, Apache DeltaSpike came in and provided an absract solution to boot either implementations, but this wasn’t never standardized at spec level, until now…​

Why this important?

So, if implementation and a third party project already provide this Java SE support, what’s the big deal to have it at spec level? The answer is "increase adoption by other specifications".

A lot of Java EE specification provide a Java SE support (like JPA or JAX-RS). Since CDI doesn’t provide this support as well, they can’t rely totally on it since it is not available in Java SE. So, the side effect of this new Java SE support will be a better CDI integration in Java EE. If we add to this a broader adoption by third parties framework, we see that the benefits for CDI and its users goes far beyond the simple feature.

Preparing Java SE support (API split)

Adding such a straight forward feature to CDI seems quite easy on paper but, trust me, it wasn’t.

If you check the current 1.2 specification, you’ll see that EJB is everywhere in the spec. You also have reference to JSF, servlet or Expression Language all accross the document.

So the first work was to split the spec to put he Java EE specific feature in a dedicated part to have all CDI core feature (no tie to other spec) in its own part. This specification has now 3 parts plus an introduction as explain in the foreword section.

This work was done as carefully as possible to avoid destroying, duplicating or modifying rules, yet, your double check here is most welcome to be sure that we didn’t forget something in the rewriting.

Yes it’s rather long work to read (or re-read) the whole specification but it’s also the ocasion to see it with a fresh eye with this new organisation. You migh want grab the pdf version (whose look has been updated) of the spec to go through it.

Booting CDI in Java SE

After all this work (invisible for end users), we introduced the Java SE support by adding a bootstrap API for Java SE. The solution make use of already existing CDIProvider interface and CDI class.

Code for booting CDI in Java SE looks like this:

public static void main(String... args) {
    try(CDI<Object> cdi = CDI.getCDIProvider().initialize()) {
        // start the container, retrieve a bean and do work with it
        MyBean myBean = cdi.select(MyBean.class).get();
        myBean.doWork();
    }
    // shuts down automatically after the try with resources block.
}

Go check the Bootstrapping a CDI container in Java SE chapter in the specification and tell us what do you think.

Still work to do

Java SE support needs more work and we are still working on the feature. The two main aspect are:

Again, your feedback and ideas are most welcome to help us for these part specification.

Ordering event observers

One of the oldest requested feature for CDI was resolved in this EDR : observer ordering.

The feature was simply design by using @Priority annotation (from commons annotation) and will be used like this:

void afterLogin(@Observes @Priority(APPLICATION) LoggedInEvent event) { ... }

The use of @Priority was rather obvious since we already use this annotaion for interceptor, decorator or alternatives activation and ordering. The only issue here is that the annotation only targets types right now. We asked for a review of JSR-250 to add parameter as accepted target for @Priority.

Check the section dealing with observer ordering to have all the details.

Asynchronous events

Another important feature requested by many of you. Introducing Asynchronous event wasn’t an easy thing, because we needed to keep backward compatibilty with existing events. We also wanted to leverage new asynchronous API in Java 8 to provide the most up to date approach in the spec.

The solution we choose was to introduce @ObservesAsync and add methods fireAsync() in the Event interface. So the exisitng observer (defined with @Observes) will stay synhcronous and new observer defined by @ObservesAsync will be called asynchronously if the event was triggered with fireAsync() (and won’t be called from a classical fire()).

So asynchronous event usage will look like this:

@Inject Event<LoggedInEvent> loggedInEvent;

public void login() {
    ...
    loggedInEvent.fireAsync( new LoggedInEvent(user) );
}

...

public void asyncAfterLogin(@ObservesAsync LoggedInEvent event) { ... }

The best is to re-read all the event chapter in the spec to get the details.

Why this double activation is needed?

For the producer (fire()) side it’s rather obvious : we cannot magically change all synchronous event call to async. We need an handle on the work in progress (so a new method signature with CompletionStage), the payload mutation mechanism would break as all transactional events. So there’s no debate on fireAsync().

On the observer side, the reason is for backward compatibility. CDI events are a great way to cross boundaries of our own code and activate unknown code at runtime in another module of the app (i.e. another jar) that we don’t own. This other code can be a framework, a code developed by an other team in a big project or a legacy jar that we don’t want to touch.

Imagine the following use cases (all code running on CDI 2)

  • I’m compiling in CDI 1.x and one of the Jar (framework for instance) already migrated to CDI 2.0 firing async event where it use to fire sync events. Without activation on the observer side, I have all the chance to see my observer break. And if I decide to upgrade to CDI 2.0 I must have a way to activate / deactivate async call on given observers

  • I’m compiling in CDI 2.0 but use jar1 in CDI 1.0 and jar2 in CDI 2.0 coming from other teams. jar2 and jar1 are old related pieces of code communicating the event. The guys in jar2 had time to migrate to CDI 2.0 and switch most fire() to fireAsync(). Observer in jar1 will be called asynchronously if the default is to have async activated for all observers.

These example looks like corner cases but the side effect will be that no framework developers will switch to fireAsync() for the sake of defensive programming. So async event would have a serious adoption problem withotu this double activation. More than that, as we are designing a Java EE specification we must be committed to backward compatibility and cannot change behavior of old code, like it would do if we chose to not have activation on observer side.

Other change, corrections and clarifications

You can check the release notes of this early draft to discover the more minor changes we also introduced in the spec.

Implementation and TCK

TCK team and JBoss Weld team are currently working hard to provide a Reference Implementation for this draft. You’ll be notified as soon as there’ll be released.

We need you

To go on on this Early draft, we really need your feedback. The review period will be launch in the coming days by the JCP and will run for 90 days. You can give your feedback in many way:

Thank you for helping us making CDI one of the best programming model for Java and Java EE.

CDI 1.2 released

Posted by Antoine Sabot-Durand on Apr 14, 2014 | Comments

After one year of existence, the CDI 1.1 specification is updated by a maintenance release. This maintenance review known as CDI 1.2 was adopted by the JCP with 24 yes and one Expert Member forgetting to vote. The minor increment (from 1.1 to 1.2) instead of a 1.1-SP1 is due to the the fact that we changed the javadoc and the TCK but beyond that there are far less changes from 1.1 to 1.2 than from 1.0 to 1.1. That’s being said, CDI 1.2 brings a lot of clarifications and small behavior changes. Let’s check what’s on the menu.

Major changes

Some of these changes are only big clarifications but some other have an impact on the implementations (these last ones have an asterisk in their title below). In order to use them you’ll have to grab a CDI 1.2 implementation (more info at the end of this post).

Rethinking the default bean discovery mode *

The default bean discovery mode (annotated) that allows CDI to be activated by default in Java EE 7 without beans.xml, file was the root of a lot of issues with other frameworks implementing the AtInject specification (JSR-330) or with libraries thought to be used with such frameworks. To solve these issues we changed the set of Bean defining annotations (class annotations that make a class an implicit bean candidate) :

  • all pseudo scopes annotations except @Dependent were removed,

  • @Interceptor and @Decorator were added,

  • all stereotype annotations (annotations annotated with @Stereotype) were added.

Clarification of conversation resolution

Conversation resolution mechanism could bring conflicts with servlet spec as stated in CDI-411.

We clarified the fact that implementation should prevent these conflict during conversation resolution in conversation context lifecycle

Rework on event chapter

You think you know how event resolution works in CDI? If you gained this knowledge by a careful reading of chapter 10 of the specification, think again. This chapter had a lot of approximations and confusing mentions. It was reviewed and partly rewritten (and yes, @Any is totally useless for Event<> injection, event firing and observers resolution).

This chapter is worth the re-reading.

You can also check the diff, if you prefer.

BeanManager more permissive during initialization *

In CDI 1.1, some BeanManager methods couldn’t be called before the AfterDeploymentValidation was fired. A non portable behavior was tolerated to allow use of these in AfterBeanDiscovery observers. These brought confusing mention in specification and javadoc. We decided to standardized the non portable behavior (not a big deal since all implementations adopted it). So in CDI 1.2 the following BeanManager method can be called (with restrictions) in an AfterBeanDiscovery observer method:

  • getBeans(String),

  • getBeans(Type, Annotation…​),

  • getPassivationCapableBean(String)

  • resolve(Set),

  • resolveDecorators(Set, Annotation…​),

  • resolveInterceptors(InterceptionType, Annotation…​),

  • resolveObserverMethods(Object, Annotation…​),

  • validate(InjectionPoint).

more details on the diff

Clarification on container lifecycle event use

We clarified the fact these event should only be used during invocation of their observer methods. Check the diff of the whole 11.5 paragraph

Rework on the initialization phase parts

Description of initialization phase in chapter 11 & 12 was very messing. No chronological ordering of event fired by the container, missing events. For instance we forgot to speak with ProcessInjectionPoint and ProcessBeanAttributes and ProcessProducer was wrongly placed before ProcessBean in chapter 12. So if you’re planning to write portable extensions you should perhaps re-read chapter 12. Not yet a page turner but far more accurate than it use to be.

CDI API now officially supporting OSGi

We integrated all OSGi bundle information in CDI 1.2 api jar. So now it’ll be easier to use CDI in OSGi environment. Before that you had to grab a special OSGi release of CDI 1.1 to have the good bundle info in our META-INF/MANIFEST.MF.

More minor changes

You can check the change section of the spec to check the more minor changes we introduces in the spec. We also work on Javadoc to synchronize it with the specification by updating it or correcting the spec when api description were wrong.

Concrete stuff

You’ll find concrete raw and final data in the links below.

  • You’re interested by the release notes? it’s here.

  • You want to check the diff between CDI 1.1 spec and CDI 1.2 spec? You’ll find it there

  • You can’t wait to read this new spec, the Javadoc or use with the API or TCK? Go to our download page

  • You want to start coding in CDI 1.2? Good news reference implementation (Weld 2.2.0) is available and provide all that’s needed to be integrated to a Java EE 7 server. More information on Weld 2.2.0 announcement