The Hollywood Principle

Tutorial – Introduction to CDI – Contexts and Dependency Injection for Java EE (JSR 299)

MarkStruberg
Java-CDI

Pete Muir and Mark Struberg offer us an introduction to CDI: Contexts and Dependency Injection for Java EE, delving into the history of the two year project and its implementations

One of the most
exciting features of CDI is to allow anyone to write powerful
extensions to the core Java EE platform, even change core behaviour
itself. These extensions are fully portable across any environment
which supports CDI. This article provides an overview of the major
CDI features, explores a sample web application, and outlines some
of the basic mechanisms of the framework.

There are
currently three CDI implementations available: JBoss Weld (the Reference
Implementation), Apache
OpenWebBeans
, and
Caucho CanDI
. Several libraries already provide CDI extensions,
such as Apache DeltaSpike, JBoss Seam 3, and Apache MyFaces
CODI.

A little bit of
history

Originally
developed under the name ‘Web Beans’, the CDI specification was
created to fill the gaps between Enterprise Java Beans (EJB) on the
back end, and JavaServer Faces (JSF) in the view layer. The first
draft targeted only Java Enterprise Edition (Java EE), but during
the creation of the specification it became obvious that most
features were very useful for any Java environment, including Java
SE.

At the same time,
both Guice and
Spring communities had begun an effort to specify the basics of
injection as “JSR-330: Dependency Injection for Java” (nicknamed
“AtInject”). Considering that it did not make sense to provide a
new dependency injection container without collaborating on the
actual injection API, the AtInject and CDI expert groups worked
closely together to ensure a common solution across dependency
injection frameworks. As a result, CDI uses the annotations from
the AtInject specification, meaning that every CDI implementation
fully implements the AtInject specification, just like Guice and
Spring. CDI and AtInject are both included in Java Enterprise
Edition 6 (JSR-316) and thus an integral part of almost every Java
Enterprise Edition server.

Essential
CDI

Before we go on to
dive into some code, let’s take a quick look at some key CDI
features:

  • Type
    Safety
    : Instead of injecting objects by a (string) name,
    CDI uses the Java type to resolve injections. When the type is not
    sufficient, a
    Qualifier annotation can be used. This allows the compiler
    to easily detect errors, and provides easy refactoring.
  • POJOs: Almost every Java object can be
    injected by CDI! This includes EJBs, JNDI resources, Persistence
    Units and Persistence Contexts, as well as any object which
    previously would have been created by a factory method.
  • Extensibility: Every CDI container can enhance
    its functionality by using portable “Extensions”. The attribute
    “portable” means that those CDI Extensions can run on every CDI
    container and Java EE 6 server, no matter which vendor. This is
    accomplished by a well-specified SPI (Service Provider Interface)
    which is part of the JSR-299 specification.
  • Interceptors: It has never been easier to
    write your own Interceptors. Because of the portable behaviour of
    JSR-299, they now also run on every EE 6-certified server and on
    all standalone CDI containers.
  • Decorators: These allow to dynamically extend
    existing interface implementations with business aspects.
  • Events: CDI specifies a type-safe mechanism to
    send and receive events with loose coupling.
  • Unified EL integration: EL-2.2 opens a new
    horizon in regard of flexibility and functionality. CDI provides
    out-of-the-box support for it!

Diving into CDI

Let’s start by exploring a sample web application. The
application allows you to send e-mail via a web form – fairly
simple. We only provide code fragments, but they should be enough
to get the gist of how CDI is used. After showing each part of the
application, we will discuss the details in the next chapter.

For our mail application, we need an
“application-scoped”
MailService. Application-scoped objects are essentially
singletons – the container will ensure you always get the same
instance whenever you inject it into your application. The

replyTo
address is taken from
the
ConfigurationService which is also application-scoped. Here we see our
first injection – the “configuration” field is not set by the
application’s code, but is injected by CDI. The

@Inject
annotation tells CDI to perform
the injection.

Listing 1

 

@ApplicationScoped
public class MyMailService implements MailService {
 private @Inject ConfigurationService configuration;

 public send(String from, String to, String body) {
   String replyTo = configuration.getReplyToAddress();
   ... // send the email
 }
}

Our application also identifies the current user (note that it
doesn’t try to perform any authentication or authorization, we
simply trust everyone!), and the current user is scoped to the HTTP
session. CDI provides the session scope, which ensures that you
will get the same instance of an object per HTTP Session (in a web
application).

By default, CDI beans are not available for use in JSF via
the Unified Expression Language. In order to expose it for use by
JSF and EL, we add the
@Named annotation:

Listing 2

@SessionScoped
@Named
public class User {
 public String getName() {..}
 ..
}

The web page is implemented with JSF 2. We suggest you use a controller class:
@RequestScoped
@Named
public class Mail {
 private @Inject MailService mailService;
 private @Inject User user;
 
 private String text; // + getter and setter
 private String recipient; // + getter and setter 
 
 public String sendMail() {
   mailService.send(user.getName(), recipient, text);
   return "messageSent"; // forward to 'message sent' JSF2 page
 }

}
The only missing part now is the JSF page itself, sendMail.xhtml:
<h:form>
 <h:outputLabel value="Username" for="username"/>
 <h:outputText id="username" value="#{user.name}"/><br/>
 <h:outputLabel value="Recipient" for="recipient"/>
 <h:inputText id="recipient" value="#{mail.recipient}"/><br/>
 <h:outputLabel value="Body" for="body"/>
 <h:inputText id="body" value="#{mail.body}"/><br/>

 <h:commandButton value="Send" action="#{mail.send}"/>
</h:form>

Now that we have a
working application, let’s explore some of the CDI features we are
using.

 
 

Basic
mechanisms

Sometimes it’s
very helpful to look behind the scenes of a framework to understand
at least the very basic mechanisms. Thus we like to explain a few
of those techniques first.

Dependency
Injection
: DI
is sometimes described as the ‘Hollywood Principle’ – “don’t call
us, we call you”. It means that we let the container manage the
creation of instances and inject it instead of creating them
ourselves with the new operator. Of course, even in DI containers,
nothing happens without anyone triggering this process. For a
JSR-299 container, this trigger is a call to one of the
method

 

T BeanManager#getReference(Bean<T> type, Qualifier... qualifiers);

 

which returns an instance of the given type T. By
doing so, it will not only create the returned instance, but also
all of its
@Inject-annotated children in a recursive way.

Usually the getReference(Bean<T>)
method is not called manually,
but internally by the Expression Language Resolver. By writing
something like

 

<h:inputText value="#{mailForm.text}"/>

 

the ELResolver
will look for the Bean<T> with the name “mailForm”
and resolve the instance.

Scopes, contexts,
singletons
:
Each of a CDI container’s managed objects is a ‘singleton’ in the
original sense specified by Ward Cunningham, who invented not only
the Wiki but also, together with Kent Beck, introduced design
patterns into computer science in 1987. A ‘singleton’ in this sense
means that there is exactly one instance in a well-specified
context. In a comment on „Refactoring to Patterns“ by Joshua
Kerievsky, Ward noted:

There is a proper
context for every computation. So much of object-oriented
programming is about establishing context, about balancing the
lifetimes of variables, causing them to live the right length of
time and then die gracefully.

CDI is all about creating singletons in a
well-specified context. In our case, the lifecycle of instances is
defined by their scopes. A
@SessionScoped-annotated bean exists exactly once per session. We could
also name it a “session singleton”. If a user accesses our

@SessionScoped
bean for the first time, it
will get created and stored inside the session. Every subsequent
access will return exactly this same instance. When the session
ends, all the CDI-managed instances stored inside it will also be
properly destroyed.

If we have a
@RequestScoped bean, we could call it a ‘request
singleton’, a @ConversationScoped bean is a ‘conversation
singleton’, etc.

Terminus ‘Managed
Bean’
: There
are a few terms used in the CDI specification which need a short
explanation. The term ‘Bean’ in Java is already pretty
well-established and means a POJO (Plain Old Java Object) with
getters and setters. The terminus technicus ‘Managed Bean’ now
means something completely different. It doesn’t refer to instances
of a class but meta-information which can be used to create those
instances. It is represented by the interface

Bean<T> and will
be gathered on container startup via classpath scanning.

Terminus ‘Contextual
Instance’
:
Contextual Instances are exactly our singleton instances per scope,
our ‘session singletons’, ‘request singletons’, etc. Usually a user
never uses a Contextual Instance directly, but only via its
‘Contextual Reference’

Terminus ‘Contextual
Reference’
: By
default, a CDI container wraps all Contextual Instances via a proxy
and only injects those proxies instead of the real instances. In
the CDI specification those proxies are called ‘Contextual
Reference’. There are plenty of reasons why CDI uses proxies by
default:

  • Serialisation: Instead of serialising the full
    object, we only need to serialise the proxy. On de-serialisation,
    it will automatically ‘connect’ to the right Contextual Instance
    again.
  • Scope
    differences
    : With proxies, it is possible to inject
    a
    @SessionScoped UserSettings into an @ApplicationScoped MailService because the Proxy will ‘connect’ to the
    right UserSettings itself.
  • Interceptors and Decorators: a proxy is the
    perfect way to implement interceptors and decorators in a
    non-intrusive way.

  

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.

Qualifiers

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):

@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@Qualifier
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.

 
 

Producer
Methods

In the previous example, we knowingly omitted how
those
EntityManagers will be created. One possibility would be to use Producer
Methods:

Listing 3

public class MyEntityManagerProducers {
 @Produces @RequestScoped @CustomerDb
 public EntityManager createCustomerDbEm() {
   return Persistence.createEntityManagerFactory(„customerDb“).
          createEntityManager();
 }

 @Produces @RequestScoped @AdminDb
 public EntityManager createAdminEm() {
   return Persistence.createEntityManagerFactory("adminDb").
          createEntityManager();
 }
 ...

We create @RequestScoped EntityManagers, since an EntityManager is per definition not serialisable – thus we cannot store
it in the session. We also need to implement a way to properly
clean up the
EntityManagers at the end of each request. This can be done with
disposal methods, using the @Disposes annotation:

 // class MyEntityManagerProducers continued
 public void disposeUdEm(@Disposes @UserData EntityManager em) {
   em.close();
 }
 public void disposeBoEm(@Disposes @BackOffice EntityManager em) {
   em.close();
 }
}

Events

The CDI specification defines a flexible but very easily usable
eventing mechanism based on the Observer/Observable pattern.

In many EE applications it makes sense to ‘cache’ some
information in the session. An example of such information would be
user roles and privileges and the menu tree based on those rights.
It’s usually not necessary to perform this expensive calculation
for each and every request. Rather, it can simply be stored in the
session.

One problem with this approach is that changing user
settings during runtime – e.g. when a user logs in temporarily as
administrator or changes his view language – is not easy. By using
the CDI event system we can implement this in a very elegant way.
Instead of manually cleaning up all depending information, we just
send a
UserSettingsChanged event – and everyone who is interested can react
accordingly. The event itself is typesafely represented by a class,
which might also contain payload data:

public class UserSettingsChanged {
 public UserSettingsChanged(String userName) {
   this.userName = userName;
 }
 private String userName; // + getter und setter
 ...
}

Let’s now focus on the event
source. For firing a
UserSettingsChangedEvent, we first need to inject an
event-source:

public class MyLoginBean {
 private @Inject Event<UserSettingsChanged> userChangedEvent;
 ...
 public boolean login(String username, String password) {
   .. do the login stuff
   userChangedEvent.fire(new UserSettingsChanged(username));
   ...
 }
} 

Any class which needs to react on this event can now comfortably
observe it via an observer method:

public @SessionScoped class MyBackingBean {
 Locale userLanguage;
 ...
 public void refreshLanguage(@Observes UserSettingsChanged usc) {
   userLanguage = getDefaultLanguageOfUser(usc.getUserName());
 }
 ...
}

If the
UserSettingsChange event gets fired, all observer methods of beans in
currently active scopes will get invoked.

Inceptors

CDI provides an easy way to create own custom interceptors,
as we will show by creating our own
@Transactional
interceptor. Instead of having
to manage the transactions manually, our small interceptor will do
this for us as shown in the following usage example:

@ApplicationScoped
public class MyUserService {
 private @Inject EntityManager em;

 @Transactional
 public storeUser(User u) {
   em.persist(u);
 }
}

For implementing this feature, we need to provide two
parts. The first one is obviously the annotation itself. It is
meta-annotated as
@InterceptorBinding which marks it as an annotation that is intended
to be used for interceptors:

@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.TYPE, ElementType.METHOD })
@InterceptorBinding
public @interface Transactional {}

The second part is the interceptor implementation itself.
This class must be annotated as
@Interceptor and additionally with its intended interceptor
binding. The interceptor functionality itself is implemented in a
method which gets annotated as
@AroundInvoke:

Listing 4

@Interceptor @Transactional
public class TransactionalInterceptor {
 private @Inject EntityManager em;
 @AroundInvoke
 public Object invoke(InvocationContext context) throws Exception{
   EntityTransaction t =em.getTransaction();
   try {
     if(!t.isActive()) 
       t.begin();    
     return context.proceed();
   } catch(Exception e) {
     .. rollback and stuff
   } finally {
     if(t != null && t.isActive()) 
       t.commit();
   }
 } 
}

Final Thoughts

After two years of availability, CDI is already seeing wide
adoption. It has proven itself in a wide range of projects, from
providing productivity in small start-ups to offering reliability
and scalability websites with millions of users per day.

The Expert Group is currently working actively on CDI 1.1, a
specification which will bring small fixes and improvements,
including much-requested standardization of Java SE bootstrap
functionality for non-web applications.

 

More about the Authors:

Mark Struberg is a software architect with over 20 years of
programming experience. He has been working with Java since 1996
and is actively involved in open source projects in the Java and
Linux area. He is Apache Software Foundation member and serves as
PMC and Committer for Apache OpenWebBeans, MyFaces, Maven, OpenJPA,
BVal, DeltaSpike and other projects. He is also a CDI Expert Group
member actively working on the specification. Mark works for the
Research Group for Industrial Software (INSO) at the Vienna
University of Technology.

Pete leads the Seam, Weld and CDI TCK projects, is an
adviser to the RichFaces project, and is a founder of the
Arquillian project. He has worked on a number of specifications
including JSF 2.0, AtInject and CDI. He is a regular speaker at
JUGs and conferences such as Devoxx (Javapolis), JAX, JavaBlend,
JSFDays and JBoss World. Pete is currently employed by Red Hat Inc.
working on JBoss open source projects. Before working for Red Hat,
he used and contributed to Seam whilst working at a UK based
staffing agency as IT Development Manager.

 

This article originally appears in Java Tech Journal: CDI back
in March 2012 – find more of that issue (and others) here:

Author
MarkStruberg
Mark Struberg is a software architect with over 20 years of programming experience. He has been working with Java since 1996 and is actively involved in open source projects in the Java and Linux area. He is Apache Software Foundation member and serves as PMC and Committer for Apache OpenWebBeans, MyFaces, Maven, OpenJPA, BVal, DeltaSpike and other projects. He is also a CDI Expert Group member actively working on the specification. Mark works for the Research Group for Industrial Software (INSO) at the Vienna University of Technology.
Comments
comments powered by Disqus