The Hollywood Principle

Tutorial - Introduction to CDI - Contexts and Dependency Injection for Java EE (JSR 299) - Part 3


The Lifecycle of a CDI container

Let's look at an easy scenario with a CDI container inside a plain Servlet engine such as Apache Tomcat. If a WebApplication gets started, a ServletFilter will automatically also start your CDI container which will firstly register all CDI-Extensions available on the ClassPath and then start with the class scanning. All ClassPath entries with a META-INF/beans.xml will be scanned and all classes will be parsed and stored as ‘Managed Bean’ (interface Bean<T>) meta-information inside the CDI container. The reason for scanning this information on startup is to: first. detect errors early and second, vastly improve the performance at runtime.

To be able to handle all the CDI Scopes correctly, a CDI container simply uses standard Servlet callbacks like ServletRequestListener and HttpSessionListener.

Standard scopes

JSR-299 defines the most important scopes to build classic web applications:

  • @ApplicationScoped
  • @SessionScoped
  • @ConversationScoped
  • @RequestScoped

Those scopes are meta-annotated as @NormalScope which means they have a well-defined lifecycle.

Beside those, there is another non-normal scope: @Dependent. If a class doesn't have any explicit CDI scope annotation or is explicitly annotated with @Dependent, an instance will be created for each and every InjectionPoint and will share the lifecycle of the contextual instances they get injected into.

An example: if a @Dependent MySecurityHelper is injected in a @RequestScoped MyBackingBean, then the MySecurityHelper instance will be destroyed along with the MyBackingBean instance at the end of the request. If you @Inject the MySecurityHelper into a @SessionScoped UserSettings object, it will also be treated as @SessionScoped.


If an application needs multiple implementations of one and the same interface, this previously has been solved by giving them different names. The problem with this approach is that this string-based solution is not typesafe and can easily lead to ClassCastExceptions. The CDI specification introduced a typesafe way to achieve the same result with the @Qualifier meta-annotation.

A small sample: An application needs to access two different databases with JPA. Thus we need two different EntityManagers. To distinguish between those, we just create two @Qualifier annotations @CustomerDb and @AdminDb (in analogue):

public @interface CustomerDb {}

Those Qualifiers can now easily be used to inject the appropriate EntityManager:

public @ApplicationScoped class MyService {
 private @Inject @CustomerDb EntityManager customerEm;
 private @Inject @AdminDb EntityManager adminEm;

If no Qualifier is being used, the pre-defined @Default Qualifier will be assumed.



Mark Struberg
Mark Struberg
Peter Muir
Peter Muir

What do you think?

JAX Magazine - 2014 - 03 Exclucively for iPad users JAX Magazine on Android


Latest opinions