Introduction to CDI 2.0 API

User Rating: 0 / 5

Star InactiveStar InactiveStar InactiveStar InactiveStar Inactive
 

CDI 2.0 is the new version of Context and Dependency Injection for the Java EE Platform and it's now in public review status. While you can now grab the specification at: https://jcp.org/aboutJava/communityprocess/pr/jsr365/index.html in this tutorial we will have a first look on running some of its features on the last version of WildFly 10

CDI brings several additions to the existing 1.1 version. The most relevant are:

  • Providing Asynchronous event execution and Observer ordering
  • Possibility to configure or veto observer methods
  • Alignment on Java 8 features (streams, lambdas, repeating qualifiers)
  • A standard API to boot CDI in a standard Java SE application
  • Ability to apply interceptors on @Producers through a InterceptionFactory
  • Built-in annotation literals addition

We will see at first how to install WildFly Patch for CDI 2.0 and then modify an example Java EE application to run some of CDI 2.0 features.

Start by downloading the WildFly patch from: http://download.jboss.org/weld/3.0.0.CR1/

Once done, apply the patch as usual:

patch apply /home/jboss/Downloads/wildfly-10.1.0.Final-weld-3.0.0.CR1-patch.zip
{
    "outcome" : "success",
    "result" : {}
}

Great. Let's move on. In this example we will be updating an application used widely in this site: https://github.com/fmarchioni/mastertheboss/tree/master/javaee/javaee7example

The first thing you will need to do is updating the cdi-api dependency in the pom.xml file, otherwise you will fail to compile your project:

<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>2.0-PFD</version>
</dependency>

Now let's introduce in the application Asynchronous Events which were not available until now:

public class  ServiceBean   {

	@Inject
	private Event<SimpleProperty> propEventSrc;

	@Inject
	private Event<Tracer> tracerEventSrc;

	@Inject
	private EntityManager em;

	
	public void put(SimpleProperty p){
		 
	      em.persist(p);
	      propEventSrc.fire(p);
	      tracerEventSrc.fireAsync(new Tracer("Added property "+p.getKey()));
	}
	 
	public void delete(SimpleProperty p){

		Query query = em.createQuery("delete FROM SimpleProperty p where p.key='"+p.getKey()+"'");

		query.executeUpdate();
		propEventSrc.fire(p);
		tracerEventSrc.fireAsync(new Tracer("Removed property "+p.getKey()));
		 	      
	}
}

As you can see ServiceBean class has been updated to include an Asynchronous event in every business operation. The event itself is trivial as all it does is tracing some data with the Tracer class:

public class Tracer {
   private String evt;
	
   public Tracer(String evt)  {
	this.evt = evt;  
  }
   public String toString() {
	   return "Tracing an event "+evt;
   }
}

As for synchronous events, we need an Observer method also for asynchronous events. The logger method, will be included for this purpose:

@RequestScoped
public class Producer {
	@Inject RepositoryManager db;

	private List<SimpleProperty> propertyList;

	 
	public void onMemberListChanged(@Observes final SimpleProperty member) {
		retrieveAllSeatsOrderedByName();
	}
	
	public void logger(@ObservesAsync Tracer tracer) {
		     System.out.println("TRACE: "+tracer);
	}
	
	@Produces
	@Named
	public List<SimpleProperty> getPropertyList() {
		return propertyList;
	}
  • . . . .

That's all. Build the project and check that your asynchronous event are logged in the Console.

Another addition in CDI 2.0 is Observer ordering. As a matter of fact, before the actual observer notification, the container determines an order in which the observer methods for a certain event are invoked. The priority of an observer method can be declared by annotating the event parameter with @Priority annotation. Observers with smaller priority values are called first.

So, for example:

public void onMemberListChangedEarly(@Observes @Priority(500) final SimpleProperty member) {
	firstAction();
}
public void onMemberListChangedLate(@Observes @Priority(600) final SimpleProperty member) {
	secondAction();
}

Finally, it's worth mentioning that CDI 2.0 will enable also the usage of Java 8 features such ash the CompletionStage API. The CompletionStage is an interface which abstracts units or blocks of computation which may or may not be asynchronous. In our example, callers of Event.fireAsync (...) will receive a Java 8 CompletionStage which allows you to react to errors and concatenate multiple calls (future chaining).

Here's an except of it:

tracerEventSrc.fireAsync(new Tracer("Added property "+p.getKey())).
.whenComplete((event, err) -> {
    if (err != null) {
        System.out.println("Received error! "+err.getMessage());
    } else {
        System.out.println("Processed event correclty");
    }
});

If an Exception is raised during event processing, it will be intercepted in the .whenComplete block.

In the next tutorial we will see how you can bootstrap the Weld container from a J2SE application using the standard libraries described by CDI 2.0 specifications. Stay tuned!

Follow us on Twitter