Next Presso (CDI, Java EE and friends)

The king components in CDI are the Beans (check this older post to all exisitng kind of beans).
In CDI a bean is managed from A to Z by the container, which controls lifecycle of its instance and add all CDI magic on it (injection, interception, etc..).

But sometimes you need to have more control on your components, because you need to create it or destroy it yourself or because it is provided by another container or framework, for instance.

Yet, you’d like to have access to some CDI features for your component like dependency injection or interception.
In that case you’ll need to use CDI "non-contextual instance" feature.

To achieve CDI integration, some Java EE spec use the non-contextual instance feature.
For instance, you can think about being able to perform CDI injection in servlets or in entity listeners.
These component are not managed by CDI container, but they are enhanced with some CDI features.

Two kind of non-contextual instances and two kind of classes

CDI Non-contextual instance may benefit the following services:

Call of @PostConstruct and @Predestroy lifecycle callbacks.

Dependency injection.

Destruction of dependent beans instances when the instance is destroyed.

Interceptors and Decorators.

We can distinguish 2 kinds of non-contextual instances.

The "official" (from the spec point of view) non-contextual instance which is created (i.e. instantiated) by the container and the one instantiated outside the CDI container.

This last kind has no official name in the spec (yet it is fully supported), in this post I’ll call them "user instantiated non-contextual instance"
This second kind of non-contextual instance may benefit the following CDI services:

call of @PostConstruct and @Predestroy callbacks.

CDI dependency injection

Destruction of dependent beans when the instance is destroyed

Interception thanks to the new InterceptionFactory SPI in CDI 2.0

Both kind of non-contextual instances are enhanced through the InjectionTargetFactory SPI.
The classic non-contextual instance is also created and destroyed with the same SPI, but CDI provides an helper class to perform this seamlessly if the class you want to use has already all required annotation (@Inject and qualifiers)

Three different use cases

Thus, when you need to use non-contextual instances, you should first answer to 2 questions

Can I Let the CDI container create the instance for me?

Does the class of the instance has already all annotations (@Inject, qualifiers, Interceptor bindings) at class level?

Your answers will make non-contextual instances more or less easy to use:

Class has all required annotations

Class lacks some annotations

Container can instantiate

You can use Unmanaged helper class

You’ll have to use InjectionTargetFactory and AnnotatedTypeConfigurator SPI

You provide the instance

You’ll have to use InjectionTargetFactory SPI

Use case 1: Non-contextual instance for a class having all required annotations

This is the simplest use case.

Since CDI 1.1, the API provide the Unmanaged helper class that hides all the work done with InjectionTargetFactory produce a non-contextual instance:

Request a new instance handler (providing all services and data for a given instance)

3

These invocation create the instance, perform dependency injection and call the @PostConstruct lifecycle call back

4

retrieving the effective instance

5

call the @Predestroy lifecycle callback

6

perform destruction of the instance context (i.e. release all @Dependent instances injected in the instance)

Keep in mind that letting the container producing the instance (produce() method) activate optional interceptors and decorators on the instance.

In this case, the class shouldn’t be unproxyable as detailed in the spec.

Unmanaged.UnmanagedInstance is an important handler that gives you access to all CDI services for the instance you want to obtain, but it should also be kept to perform the dispose() task, which release all dependent beans instances that were created with your instance.
Without this call you may face memory leaks in your application

Unfortunately, Unmanaged doesn’t provide access to the underlying AnnotatedType for the instance class.

So if you need to add annotations to the metadata model because they are missing on the original class, you’ll have to use the InjectionTargetFactory provided by the container.
Note that Unmanaged does the same under the hood.

To request an InjectionTargetFactory from the container, you’ll need first to access the BeanManager.

If you are in CDI programming model (i.e in a CDI bean) simply inject the BeanManager to access it

@Inject
BeanManager bm;

If are not CDI programming model, the easiest way to access the BeanManager is ot use the CDI class available since CDI 1.1 (note that it also works in CDI programming model even if direct injection is still preferred to static call done with CDI.current()).

BeanManager bm = CDI.current().getBeanManager();

In certain circumstance, you may want to retrieve the BeanManager from a JNDI lookup through the java:comp/BeanManager, JNDI name.

The following example show how to create a non-contextual instance from MyClass in which you need to create an injection point (add @Inject) on the field MyField

using the new AnnotatedTypeConfigurator SPI in CDI 2.0 to configure the underlying AnnotatedType. Before CDI 2.0 you’d have to implement AnnotatedType to add your annotation and use it in previous step (2)

4

looking for the MyField field and adding @Inject to it (we use the new InjectLiteral introduced in CDI 2.0)

5

creating the InjectionTarget. As it’s for a non-contextual instance, we create it by passing null (no bean) to the method

6

creating the CreationalContext. As it’s for a non-contextual instance, we create it by passing null (no bean) to the method

7

creating the instance, performing @PostConstruct lifecycle call back and injection

8

call the @Predestroy lifecycle callback

9

release the CreationalContext and all the dependents bean instances

Note, that, we could also have added interceptor bindings to the AnnotatedTypeConfigurator during step (3).
In this case, MyClass shouldn’t be unproxyable as detailed in the spec.

Unfortunately, this gem is a bit hidden in the spec and some developers totally missed it while others may wrongly think that using extension is too complicated.

With this article, I’ll try to show that everybody can use extension in their work as it can be used to provide simple feature or advanced integration mechanism.

But first things first, let’s answer the basic question "why would you need to develop a portable extension".

What can I do with an extension

At boot time CDI scans most of the class in the classpath to create its configuration and the bean graph.
The configuration and meta data that are created at this moment are created from static content (class file) and may need some more dynamic content.

That’s where portable extension gets in.

A CDI portable extension allows you to hook on the CDI scanning process which occurs at boot time and modify or add information to the meta data created by the CDI container.

That includes add Beans, remove classes from set of type that should become bean, add producers, observers and most of the SPI elements that exist in CDI.

So to make short, extensions are how developers can configure CDI and override default behaviour created from reading the classes.

Getting started with CDI extension

Service interface is javax.enterprise.inject.spi.Extension, so to add an extension you’ll need to create a class implementing javax.enterprise.inject.spi.Extension interface and add this class qualified name to the META-INF/services/javax.enterprise.inject.spi.Extension service provider text file.

Extension feature is defined by adding observers on specific lifecycle event of the CDI container.
At boot time, the CDI container will use service provider mechanism to discover all extensions and register these observers.

This approach allows you to hook on internal lifecycle steps of the container and modify their outcome.

Let’s check what are these step.

Extension step by step

To understand how to work with extensions, we can start by splitting container lifecycle in 4 Big steps:

The major steps of the CDI container lifecycle

Eah of these step (except "Application running") contains one or more events for which you can define one or more observers in your extension to hook on CDI elements discovery and meta data building.

Let’s focus on each of these steps and describe the events that you can use in each one.

Some examples given below will use new features coming from CDI 2.0.
I’ll explain how same result can be obtained in CDI 1.2.

Types discovery

Type discovery can be illustrated like this

Types discovery

In this schema (and next ones), yellow boxes are the in which an extension can observes an event and perform actions, grey ones are simplification of internal container behaviour.

The goal of this step is to create a set of AnnotatedType which will be candidate to become beans.

Ths set can be filled explicitly in a BeforeTypeDiscovery or AfterDiscovery observers

It is also filled automatically by the container class scanning process on which developer can place a hook to alter the discovered by using a ProcessAnnotatedType observer.

Let’s see in detail how all this work.

Adding types before scanning (BeforeBeanDiscovery event)

Before CDI container start automatic types scan on the class path, it fires the BeforeBeanDiscovery event.

Observing this events allows addition of a specific type to the set of discovered types or addition of specific CDI annotations like qualifier, stereotype or interceptor binding.

class from a legacy framework that we want to integrate into CDI programming model without changing its code

2

using an AnnotatedTypeConfigurator (new in CDI 2.0) based on the MyLegacyFrameworkService class

3

adding @ApplicationScoped scope on the AnnotatedTypeConfigurator

4

find the first constructor with one parameters and add the @Inject on it

The example above use new feature from CDI 2.0: the AnnotatedTypeConfigurator returned by one of the addAnnotatedType() methods of BeforeBeanDiscovery event.
If you are in CDI 1.1 you can don the same but you’ll have to implement your own AnnotatedType to do the same in more verbose way.
to configure a new AnnotatedType add a scope on it and an @Inject annotation on one of its constructors.
At the end of observer invocation, the container will automatically build the matching AnnotatedType from this configurator and add it to the discovered type set.

Automatic types scanning process

After this first event, the container starts a process of type discovery in the application classpath.

This scanning can be configured differently for each bean archive (i.e. jar or module) in the classpath.

Each jar in the application path may (or may not) contain a beans.xml file defining how types will be scanned by the CDI container for this bean archive.

Remember that CDI doesn’t provide a global configuration file so each of your bean archive (including the war container others bean archive) must define its discovery mode.

these methods give you access to classes list discovered as possible alternatives beans, interceptors or decorators.
You can use these inventory list to check everything you need is here or add a new class to them since these lists are mutable

2

as in BeforeBeanDiscovery you can add a custom AnnotatedType to the set of discovered AnnotatedType

The following extension checks that if LastInterceptor class was discovered as an interceptor, this one will be invoked after all other interceptors.

returns the Annotated defining the bean (i.e an AnnotatedType for managed Bean or a session bean, an AnnotatedField or AnnotatedMethod for a producer and null for a custom bean)

3

returns the created Bean

4

allows observer to abort deployment by adding a definition error

This event is mainly here to check that a specific bean is created and sometimes capture its definition for further use.

An observer on ProcessBean for all kind of bean.
If you want to be more specific, you can use a child of this event to only observe the event for a specific kind of bean.

ProcessProducer event

This event is fired for all producers find in the application.

Remember that a producer is a kind of bean.
But its definition and discovery depends on the bean that contains it.
In other words, producer defined in a class that will not be discovered as bean will be ignored.

It mainly allows overriding of the producing code (i.e. you can override the code written to produce a specific bean instance in the application from an extension )

When user will declare a producer for a metric in the app, we want to check in the metric registry that it doesn’t already exist.
If it exist, instead of creating an new instance, we’ll return the one in the registry.
If it doesn’t exist, we’ll use the producer code to instantiate the metric, add it to the registry and returns it to the application.

allows creation of a custom bean either by creating a custom implementation of Bean interface or by using the BeanConfigurator helper (new in CDI 2.0).
registering a custom bean will trigger all the events linked to bean discovery and creation.

3

allows creation of an ObserverMethod either by creating a custom implementation of ObserverMethod interface or by using the ObserverMethodConfigurator helper (new in CDI 2.0).

4

add a nex context to the container

5

returns a discovered AnnotatedType for the given class and id.

6

returns an Iterable on all the discovered AnnotatedType in the application

AfterDeploymentValidation event

This last bootstrapping event is only a hook to check that everything is as expected in the meta data (remember that the observer can inject BeanManager to inspect these meta data).

When this event is fired, the meta data in the container are no more mutable and the application is ready to run

CDI users ask me very often why they should adopt CDI and stop using their old framework or way of doing their developments.
The answer to this question can be found in advanced CDI stuff: extension mechanism and CDI SPI.

Yes, CDI true killing feature is not accessible out of the box and you have to dig into the spec to grab its power.
Unfortunately, the way it’s introduced and explained in the specification document doesn’t make it particularly shine.

With this article and a coming one on portable extensions, I’ll try to fix that and help beginner users to get an overview of the power they’ll have if they invest time in learning CDI SPI.

I’ll try to show you all the aspects of the CDI SPI and how you can use part of it in your day to day work.
In this article I’ll use the term "usual code" in opposition to portable extension code to differentiate standard development from development to extend CDI.
At the end of the day you’ll see how much the CDI SPI loves developers ;).

What is this SPI?

CDI SPI is the introspection part of the spec allowing developers to access meta-information about CDI concepts (Beans, events, injection point, interceptors, etc…​)

While some of you may be more familiar with the term API (Application Programming Interface), the CDI specification is mainly built on a SPI concept (Service Provider Interface).
So what’s the difference?

An API is the description of classes/interfaces/methods/…​ that you call and use to achieve a goal

An SPI is the description of classes/interfaces/methods/…​ that you extend and implement to achieve a goal

To make short, CDI provides interfaces that you implement (or that spec implementation implement for you) to perform a specific task.
Access to these implementation are usually done through injection or event observation but you’ll have on the rare occasion to create your own implementation.

To ease the understand of the SPI, I’d like to split in 4 parts:

CDI entry points

Type meta-model

CDI meta-model

SPI dedicated to extensions

This division is a subjective approach I use to introduce elements of the SPI, it doesn’t reflect organisation of CDI packages or documentation.

Let’s explore these different parts

SPI providing CDI entry points

Usually, when you develop a Java EE application you don’t have to bother "entering" in CDI bean graph.
It’s automatically done from the UI (via expression language), CDI event triggered automatically at boot time or EJB call.

But sometimes, you may need to access CDI from non CDI code or plug non CDI code to CDI beans at run time.
This part of the SPI gives you the tools to do it.

BeanManager and CDI

In CDI 1.0 the only solution you had to access CDI bean graph was to retrieve the BeanManager from JNDI

retrieving all the beans having MyService in their type and the @Default qualifier

3

apply the ambiguous dependency resolution for the set of beans

4

create a CreationalContext to help contextual instance creation for complex use cases like circularities

5

get the instance

This verbosity is the proof that the BeanManager is and advanced CDI tool allowing very basic operation on CDI echos system.
It’s obviously not the best solution if you just want to access an instance.

That’s why, in CDI 1.1 we introduced the abstract CDI class which use Java Service Loader to retrieve a concrete CDI class from the implementation.

CDI<Object> cdi = CDI.current();

CDI gives a faster access to the BeanManager with CDI.getBeanManager() method, but more interestingly, it provides a convenient way to request a contextual instance without using the cumbersome code with BeanManager.

Unmanaged

CDI 1.1 introduced an other nice feature to help you integrating CDI in non CDI code.
The Unmanaged class allows you to apply some CDI operation to a non CDI class.

With it you can call lifecycle callbacks (@Postconstruct and @Predestroy) and perform injection on such class instance.
Third party framework developers can then provide their non CDI class including injection point (remember @Inject is not part of CDI spec but AtInject spec) and Unmanaged can be used to get instances of this class.

SPI for type meta-model

As all configuration in CDI is based on annotations, we need a mutable meta-model to create or modify existing configuration.

In an other world we could have rely on JDK for type representation and reflection, but as it is read only we had to create our own model in CDI.

The AnnotatedType interface is main element of this annotation centric type meta-model.
other interfaces are abstraction or contained by it.

Defining an AnnotatedType let’s you put all annotations you need on the type, fields, methods or method parameters.

AnnotatedType are mainly used in portable extension
They are constructed by the container from existing types.

As you can see, this model has no CDI specific feature, so if a third party developer decide to couple his framework to CDI he can allow his users to play with AnnotatedType to configure his framework

SPI dedicated to CDI meta-model

I already gave a good overview of the interfaces related to Bean meta model in my previous article, so I wont go back into detail on it.

Just remember that while this meta-model is mainly used in portable extensions to declare custom beans, it can also be used in your bean to get introspection feature about the current bean, interceptor, decorator or the currently intercepted or decorated bean.

The rest of the CDI meta data SPI interfaces are below:

ObserverMethod and EventMetaData

ObserverMethod interface represent meta data for a given observer method and doesn’t have any usage outside a potable extension.
So I’ll deal with in my next article on extensions.

EventMetadata is also related to events but at the opposite logic of EventMetadata, it is only used in usual code and never in an extension.
You can inject it in your observer to get information about the event that triggered it.

For instance, you can use it to have stricter approach to observer resolution.

As I wrote in my event post, observer resolution for a given type and qualifiers set, also include an observer for any subclass of the event type and without any qualifier.
You could use EventMetadata to restrict this rule by checking effective event type and qualifier like this:

this code will be executed only if event type is strictly Payload and its qualifiers contains @Qualified

Producer and InjectionTarget and their factories

Producer and InjectionTarget are also mostly used in extension.
But if you took a look to Unmanaged presented above you may have seen that InjectionTarget can be used in usual code to perform some lifecycle operations an injection on a non CDI class.

As Unmanaged doesn’t allow you to perform injection on existing object you can use this code to do it yourself.
This can be useful if you want to have object provided by a third party, perform injection in CDI way.

CDI 1.1 introduced ProducerFactory and InjectionTargetFactory to resolve circular dependency issues when using Producer or InjectionTarget in an extension to create a new kind of Bean.
I will detail them in my next post.

InjectionPoint meta-data

Last but not least in this SPI family: the InjectionPoint.
This swiss-army knife is as much used in extension than in usual code.
But in the later case you can only use it to get information on injection point related to @Dependent scoped bean.
It’s the only way to guarantee the injection point uniqueness (i.e. the same @RequestScoped instance can be injected in multiple place).
That’s the price to access InjectionPoint power.

Let’s check some nice way to use the InjectionPoint.

Using a qualifier to pass parameter to a producer

As InjectionPoint is used to get info about what’s being injected, info included in a qualifier can be used to decide what to return in a producer

this code retrieve the parameterized type defined at the injection point and send it to the test function

2

this test function will check the effective type of the second type prameter (type of the map values) and return true if this type inherit Number

With the code above @Inject Map<String,String> map will use an HashMap under the hood while @Inject Map<String,Integer> map will use a TreeMap.
An elegant way to optimize or change behaviour without leakage in business code.

conclusion

There are lot of features you can imagine to build with InjectionPoint and keep in mind that we only saw a few example in usual code.
Imagine what you can do in an extension…​

SPI dedicated to extensions

Let’s end this SPI tour by a cliffhanger.

The following SPI classes are totally dedicated to extension development.

In fact they defined events type for each step in the container lifecycle (mainly the bootstrap part) where the portable extension magic occurs.

In CDI, Beans are a very centric concept.
Yet, for a lot of user, this concept stays fuzzy and requires experiment to achieve an expected result.
In this article I’ll try to clarify most of bean related concepts and detail the hidden mechanism behind bean definition and injection.

Bean, contextual instance and typesafe resolution

When most CDI users write

@Inject
@MyQualifier
MyBean bean;

they think: "I have injected the MyBean bean having @MyQualifier qualifier".

That’s not correct and it’s important to understand the exact mechanism behind this injection point definition.

Bean vs contextual instances

One of the specific feature in CDI is the fact that all components (qualifiers, beans, producers, etc..) are discovered at deployment time.

It allows the container to raise errors very early (before runtime) and for you to be sure that all injection points you defined will be satisfied and not ambiguous.

While this discovery process is not the topic of this article you should know that all classes packaged with your application will be analyzed at deployment to discover beans (and other components).

At the end of this discovery task, the container had created collections of meta-data for most elements included in CDI SPI.
The more centric meta-data created by CDI container is the collection of Bean<T> discovered during deployment.
These metadata are the real applications beans and in basic CDI usage you’ll never use them.

So don’t mix beans and the contextual instances (instances of the bean for a given context) you request to the container when adding an injection point in your code.

The content of Bean<T> interface

The Bean interface has two main functions:

Providing a "recipe" to create and destroy contextual instances (methods from Contextual<T>)

Bean Interface hierarchy, yes Interceptor and Decorator are also Beans

The metadata stored in Bean<T> come from the user code defining the bean (type and annotations).
If you take a look at BeanAttributes in the above schema, you’ll see that these metadata include a set of types (yes a bean as multiple types) and a set of qualifiers (each bean has at least 2 qualifiers: @Default and @Any).
These 2 sets are used in the CDI typesafe resolution mechanism.

Typesafe resolution for Dummies

When you use @Inject in your code, you’re asking the container to look for a certain Bean.
The search is done by using info in Bean metadata.

For most injection point this search is done at deployment time to check if each injection point is satisfied and not ambiguous, the only exception is the programmatic lookup (use of Instance<T>).
This approach allows the implementation to cache the matching bean for a given injection point.

When the matching Bean is found, the container use its create method to provide you an instance.

Another limitation is linked to client proxies.
In a lot of occasion (interceptor or decorator, passivation, usage of normal scope, possible circularity), the container may need to provide a contextual instance wrapped in a proxy.
For this reason, managed bean classes should be proxyable or the container will raise an exception.

Thus in addition to the above rules the spec also restrictions on managed bean class to support certain services or be in normal scopes.

So, if possible you should avoid the following limitation on your bean class to be sure that they can be proxyable:

it should have a non private constructor with parameters,

it shouldn’t be final,

it shouldn’t have non static final methods.

Bean types of a managed bean

The set of bean types (used during typesafe resolution) for a given managed bean contains:

the bean class,

evey superclass (including Object),

all interface the class implements directly or indirectly.

Keep in mind that @Typed annotation can restrict this set.
When it’s used, only the types whose classes are explicitly listed using the value member, together with Object, are bean types of the bean.

Session beans

CDI Session beans are EJB in CDI flavor.
If you define a session bean with EJB 3.x client view in a bean archive without @Vetoed annotation on it (or on its package) you’ll have a Session Bean at runtime.

Local stateless, singleton or stateful EJB are automatically treated as CDI session bean: they support injection, CDI scope, interception, decoration and all other CDI services.
Remote EJB and MDB cannot be used as CDI beans.

Note the following restriction regarding EJB and CDI scopes:

Stateless session beans must belong to the @Dependent scope,

Singleton session beans can belong to the @Dependent or @ApplicationScoped scopes,

Stateful session beans can belong to any scope

When using EJB in CDI you have the features of both specifications.
You can for instance have asynchronous behavior and observer features in one bean.

But keep in mind that CDI implementation doesn’t hack EJB container, it only use it as any EJB client would do.

Thus, if you don’t use @Inject but @EJB to inject a session bean, you’ll obtain a plain EJB in your injection point and not a CDI session bean.

Bean types of a session bean

The set of bean types (used during typesafe resolution) for a given CDI session bean depend on its definition:

A stateful bean (with no-interface view) defined in @ConversationScoped scope. It has ShoppingCart and Object in its bean types.

2

A stateless bean in @Dependent scope with a view. Usable in EL with name loginAction. It has LoginAction in its bean types.

3

It’s javax.ejb.Singleton defining a singleton session bean.

4

The EJB will be instantiated at startup triggering instantiation of MyBean CDI bean.

Producers

Producers are the way to transform standard pojo into CDI bean.

A producer can only be declared in an existing bean through field or method definition.

By adding the @Produces annotation to a field or a non void method you declare a new producer and so a new Bean.

Field or method defining a producer may have any modifier or even be static.

Producers behave like standard managed bean:

they have qualifiers,

they have scope,

they can inject other beans: parameters in producer method are injection points that the container will satisfied when it will call the method to produce a contextual instance
This injection points are still checked at deployment time.

Yet, producers have limitation compared to managed or session bean as they don’t support interceptors or decorators.
You should keep this in mind when creating them as this limitation is not obvious when reading the spec.

If your producer (field or method) can take the null value you must put in in @Dependent scope.

Remember the Bean<T> interface we talked above ?
You can see a producer method as a convenient way to define the Bean.create() method, even if it’s a bit more complicated.

So if we can define create() what about destroy()?
It’s also available with disposers methods.

Disposers

A less known feature of producer is the possibility to define a matching disposer method.

A disposer method allows the application to perform customized cleanup of an object returned by a producer method or producer field.

Like producers, disposers methods must be define in a CDI bean, can have any modifier and even be static.

Unlike producer they should have one and only one parameter, called the disposer parameter and annotated with @Disposes.
When the container container finds producer method or field, it looks for matching disposer method.

More than one producer can match to one disposer method.

Bean types of a producer

It depends of the type of the producer (field type or method returned type):

If it’s an interface, the bean type set will contain the interface all interface it extends (directly or indirectly) and Object.

If it’s a primitive or array type, the set will contain the type and Object.

If it’s a class, the set will contains the class, every superclass and all interface it implements (directly or indirectly).

CDI events are one of the shiniest feature in the CDI specification. They are a easy to understand and use and are a straight forward implementation of the Observer Design Pattern. To sum up they add more decoupling to the Dependency Injection by allowing notification of unknown target at development time (great to develop framework). Yet, documentation about event is often misleading and contains inaccurate information, probably due to the fact that the specification was wrong before we corrected it for CDI 1.2 release ;). This post is the opportunity to update or clarify your knowledge about how events work in CDI 1.0 and 1.1+ and what could come in CDI 2.0.
If you want to “play” with event you can checkout my Github project EventsTest to use it as a sandbox.

If you are familiar with events you can directly go to the more advanced or less know features

Back to the basics

What’s an event?

CDI events are defined by 2 things :

A java object (the event object)

A set of qualifiers (annotations having the meta annotation @Qualifier)
The event Object could be of any Java type and don’t have to be CDI related (try to avoid using bean instance as event object, it’s confusing and if the bean scope is not @Dependent could bring issues related to bean lifecycle). Qualifiers are the same used to define CDI Bean or injection point. They can have members or not. And their members value are part of the qualifier definition or not (if they have the @NonBinding annotation).

How to fire an event?

The most universal way to fire an event is to use the BeanManager.fireEvent(Object event,Annotation…​ qualifiers) method. BeanManger is directly accessible in CDI bean by injecting it:

The Event<T> interface is an helper to fire event whose type is totally CDI agnostic and thus doesn’t include a way of being fired. To make a gun fire analogy, In the previous example, see payloadEvent as the bullet case while the bullet is the instance of Payload you gave as parameter of the fire() method.

Observing events

To observe an event you’ll have to add an observer method in an enable bean of your application. An observer method is a method whose first parameter has the @Observes annotation. The type of the parameter with @Observes will be used to resolve target observer when an event is fired as we’ll see later. So:

public void listenToPayload(@Observes Payload event) {
...
}

will be triggered (if the method is in an active bean) for all events whose type are Payload or a super type of Payload. Off course qualifier may be added to the observer to restrict event triggering:

The observers resolution occurs at runtime when an event is fired. All the observers that match the event will be triggered by the CDI container. Note that the observer method may have other beans as parameters. They will be injected by the container before calling the method :

Features you may have missed regarding CDI events

The following CDI events feature are less known or badly documented.

No type erasure for event type

It’s not an hidden feature but more something implicit in CDI than can be missed. As CDI is a type centric specification (I always sigh when I see and injection point with a @Name qualifier), it does a better job than standard Java regarding parameterized type.

The container will make the distinction between both when resolving observer depending of the parameterized type of the event. And in CDI 1.1+ (wildcards are not allowed in observer event parameter in CDI 1.0) if you declare the following observers :

Both will be called if your event type is List<Integer> or List<Number>. Although the first observer will fit for add elements to the list while the second will be used to fetch elements from the list.

Remember that if wildcards are allowed in observer in CDI 1.1+ if they aren’t in Event injection point.

Qualifiers don’t work with event as they work with beans

That’s an important point that was very badly explained in the spec before CDI 1.2. Developers often assume that Event<> and Instance<> have quite similar way of functioning regarding qualifiers, that’s a big mistake. But let’s start with the most important here :

An observer matches an event if its type is in the event types set and if the observer has a subset of the qualifier of the event.

Yes, all the 4 declared observers will be called by the container when the event is fired. Useful to know that ;).

So @Any qualifier is totally useless on events or observers

The spec requires that all created events should have the @Any automatically added, but as we just saw @Any has the same behavior in event that @Default qualifier (no qualifier), so prefer using no qualifier instead of using @Any, it’ll be less confusing.

Event<> is here to build events not filter them

Again Event looks like Instance but is very different. While Instance is a tool to lookup for beans, Event is a tool to build an event from an object and qualifiers.
So keep in mind that when you use Event.select(Annotation... qualifiers) you are adding qualifier to the event you’ll be firing.
For instance :

will add the @Qualified qualifier to the event before firing it. So the final event will have @MyQualifier @Qualified("") qualifiers.

Advanced Event Features

Conditional Observer methods

As we saw, observer methods have to be in a bean to be registered by the container. If the bean containing the observer has a different scope than @Dependent we may want to control if the call to the observer should trigger bean instantiation.
You can do that with the receive member of @Observes annotation which can take the enum values javax.enterprise.event.Reception.ALWAYS (by default) or javax.enterprise.event.Reception.IF_EXISTS.

@RequestScoped
public class EventTestService {
// will always be called (bean my be instantiated for this call)
public void processQualifiedPayload(@Observes(receive=ALWAYS) Type1 event) {}
// will be called only if the bean already exists in Request scope
public void processUnqualifiedPayload(@Observes(receive=IF_EXISTS) Type2 event) {}
}

Remember that IF_EXISTS cannot be used in a bean having @Dependent scope since the bean cannot exists before observer is called. If you do the mistake the container will remember you that at startup.

Transactional observer methods

Transactional observer methods are observer methods which receive event notifications during the before or after completion phase of the transaction in which the event was fired. If no transaction is in progress when the event is fired, they are notified at the same time as other observers.

A before completion observer method is called during the before completion phase of the transaction.

An after completion observer method is called during the after completion phase of the transaction.

An after success observer method is called during the after completion phase of the transaction, only when the transaction completes successfully.

An after failure observer method is called during the after completion phase of the transaction, only when the transaction fails.

You can specify the transaction phase of the observer call with the during member of the @Observes annotation.
The enumeration javax.enterprise.event.TransactionPhase identifies the kind of transactional observer method the enum values are:

@RequestScoped
public class EventTestService {
// is called when the event is fired
public void processCustomerUpdateRequest(@Observes(during=IN_PROGRESS) @Updated customer cust) {}
// is called by the same event fired than previous observer but only after the trnsaction complete successufully
public void processCustomerUpdated(@Observes(during=AFTER_SUCCESS) @Updated customer cust) {}
}

Note that the transaction observer mechanism is the only way to differ and order some observer right now.

Built-in events linked to scope lifecycle (CDI 1.1+)

Since CDI 1.1, the container fire events when context are created and destroyed, thanks to the provided @Intialized and @Destroyed qualifiers.
If your application is deployed in a servlet container, the event payload correspond to the servlet scope object corresponding to the initialized or destroyed CDI scope. Otherwise payload will be java.lang.object
You can observe these event in your application like this (if it’s deployed in a servlet container) :

This bring a solution to add more fine-grained filtering on observer execution depending on actual metadata of the triggered event

Events limitation

Right now, CDI events have two big limitation out of the box

Events are only synchronous

Out of the box events are synchronous: method firing an event has to wait the end of all observers invocation before executing instruction after event firing. So no fire and forget option and off course no callback approach.
The obvious solution if you need asynchronous event approach is to use an EJB method as an observer and annotate it @Asynchronous. Other options exists but you need to create a CDI portable extension and play with threads. I’ll try to explore that in a future post.

Observers have no orders

Yes, there’s no out of the box solution to guarantee order of observers execution. The only tiny exception is using transaction phase to do so but it’s very limited. Perhaps a CDI extension could help us here again. I’ll try to explore this approach in a future post.

Pattern and tips with events

Putting all the knowledge we have now on event and other CDI stuff we can figure out some interesting pattern for our developement.

The plugin Pattern

We saw that CDI event data is totally free. You can choose any object (again avoid no dependent bean) to fire an event and this object will be received as a playlod by each observer matching the event type and qualifier.
An other interesting fact is that this payload is mutable and can be modified by its observers. Following this idea, observers can become a way to enrich a given object with new data. We can use this approach to seamlessly enhance content by adding a CDI archive to an existing application.

The catch them all pattern

Need to observe all fired event and have their info (for logging purpose for instance), you only have to observe Object.

EventMetadata will even help you to know in which bean the event was fired. A nice way to build a bridge with a messaging service (did I say JMS? ;) )

Don’t forget Interceptors and Decorators

While it’s forbidden to declare observer in decorators or interceptors, you can still fire event from them. So they can be used to enhance existing bean and add event triggering to them without touching their code.
A nice way to add event notification only when needed.

Future for CDI events

We have a lot of idea in CDI 2.0 regarding event enhancement. Off course adding observer priority and asynchronous treatment are on the top of the list. On asynchronous event we could even think of adding callback method support based on java.lang.invoke package.
More ambitious ideas are floating around like giving a range to events making them cross the War or Ear barrer and spread across the server or the cluster. That could lead us to provide an event bus at the server level and help java EE to adopt new application architectures in the future EE versions.