Bringing Real Dependency Injection to the Platform

How To Use DI in Java EE 6

Antonio Goncalves
How-to-Use-DI-in-Java-EE-6

In this article, Java Champion Antonio Goncalves looks at using the new dependency injection model brought by Contexts and Dependency Injection.

Java EE 6 is over a year old now. With this new version of the
Enterprise Edition came some improvements to the existing
specifications (EJB 3.1, JPA 2.0, JSF 2.0…) but also completely
new ones (JAX-RS, Bean Validation and CDI). This article is about
how to use the new dependency injection model brought by Contexts
and Dependency Injection.

Dependency Injection (DI) is a design pattern that decouples
dependent components. It is a specific form of inversion of
control, “where the concern being inverted is the process of
obtaining the needed dependency”. The term was first coined by
Martin Fowler.

Java is an object-oriented programming language, meaning that
the real world is represented using objects. A Book class
represents a copy of “H2G2″, a Customer represents you and a
PurchaseOrder represents you buying this book. These objects depend
on each other: a book can be read by a customer and a purchase
order refers to several books. This dependence is one value of
object-oriented design.

For example, the process of creating a purchase order
(OrderService) can be reduced to printing the PO (PrintingService),
writing and sending an email to the customer (EmailService) and
delivering the books to the customer (DeliveryService). The
EmailService can be as simple as “writing a message and sending it
to an email address” or more complex such as “writing a message
body, a subject, adding bold/italic/underlying to the message,
checking spelling, validate the email address and sending the
message to the valid email address”. The OrderService would end up
depending either on a SimpleEmailService or a RichEmailService
according to some condition or environment. How would you connect
an OrderService to an EmailService ? One solution is to use the
good old new operator:

This is simple and does the job. But
what if I want to choose between implementations and not just get
stuck with Simple-EmailService ? One solution is to pass the
implementation to the constructor and leave the external services
to choose which implementation they want to use:

 

So now an external component could
use the OrderService with the implementation it needs:

This illustrates what inversion of
control is : the control of creating the dependency between
OrderService and EmailService is inverted because it’s given to an
external component, not the component itself.

 

Since you end up connecting the
dependencies yourself this technique is referred to as construction
by-hand. In the code above we used the constructor to choose
implementation (constructor injection) but another common way is to
use setters (setter injection). Instead of constructing the object
dependency graph by hand you can use a Factory. This Gang of Four
(GoF) design pattern offloads the burden of creating dependencies
and assembling objects to a third party (called a factory).

 

One way or the other, you end-end
writing some code. With Java EE being a managed environment you
don’t need to construct by hand nor use a factory, but instead
leave the container to inject a reference for you. One way to think
about a DI in a managed environment is to think of JNDI turned
inside out. Instead of an object looking up other objects, the
container injects those dependent objects for you. This is the
so-called Hollywood Principle, “Don’t call us?” (lookup objects),
“we’ll call you” (inject objects).

 

Dependency Injection in Java
EE


Java EE was created in the late 90’s
(it was then called J2EE). The first version already had EJBs,
Servlets, JMS and so on. From there, each new version added extra
specifications (Web Services, JSF…), to reach the number of 28
specifications for Java EE 6. Dependency injection, which was a
common concept in other frameworks, arrived in Java EE 5. But it
was limited and could be seen as resource injection as you could
only inject certain resources (JDBC DataSource, JMS factories or
destinations, and JPA Entity Manager) and services (TimerService,
User Transaction, Web Services, EJBs) to certain components (mostly
EJBs and servlets). It allowed you to simplify component
dependencies and let the EJB container deal with the complexities
of managing the life-cycle of the resource (instantiating,
initializing, sequencing and supplying resource references to
clients as required). It is the responsibility of the container to
inject a reference to a resource based on the dependency
declaration.

 

This first step taken in Java EE 5
wasn’t enough so two brand new specifications were created in Java
EE 6 to bring real dependency injection to the platform and also to
bring real consistency between specifications: Dependency Injection
(JSR 330) and Contexts & Dependency Injection (JSR 299).

 

DI and CDI both in Java EE
6


These two specifications are
complementary and can’t be used one without the other.

Dependency Injection for Java (aka
@Inject) defines a set of annotations (@Inject, @Named, @Provider,
@Qualifier, @Scope and @Singleton) mainly used for injection. If
you download this JSR (which is actually just Javadoc) and read
through it, you will be surprised to see that no semantic is
defined (i.e. the injection behaviour is not portable across
implementation). This specification is implemented in Spring 3,
Guice, and also in Java EE 6 with CDI. You will find the DI
annotations in the javax.inject package.

 

Contexts and Dependency Injection
gives semantic to JSR 330 and adds more features such as context
management, events, decorators and enhanced interceptors (AOP).
Further more, CDI allows to extend the platform in a standard way,
which was impossible until now. The aim of CDI was to fill all
these gaps : give more cohesion to the platform, knit together the
web tier and the transactional tier, turn dependency injection into
a first class citizen and have the ability to add new extensions
easily. DI and AOP are the foundation of many Java frameworks, and
CDI could be the foundation of future frameworks or even JSRs. The
reference implementation is Weld, an open source project from
JBoss. You will find the CDI annotations and classes in the
javax.enterprise.inject package.

 

In a nutshell, dependency injection
is the ability to inject components into an application in a
typesafe way (yes, typesafe way, which means no XML !), and
contexts is the ability to bind the life-cycle and interactions of
stateful components to well-defined life-cycle scopes. This article
concentrates on the DI part.

 

Default
Injection


Injection already existed in Java EE
5 with the @Resource, @PersistentUnit or @EJB annotations for
example. But it was limited to certain resources (datasource,
EJB…). With DI you can inject nearly anything (we call that
“managed beans”, which are beans managed by CDI) anywhere thanks to
the @Inject annotation. Note that in Java EE 6 you can still use
the other injection mechanisms (@Resource…) but you should
consider using @Inject from now on.

 

To take the previous example, here
is how you would inject a reference of the SimpleEmailService into
the OrderService :

 

As you can see, a simple @Inject
annotation on the property (or on the setter or constructor) will
inform the container that it has to inject a reference into
emailService. If you only have one implementation, CDI will be able
to inject it. We then talk about default injection. In fact, the
code @Inject SimpleEmailService emailService could have been
written @Inject @Default SimpleEmailService emailService. @Default
is a built in qualifier that informs CDI to inject the default bean
implementation. If you define a bean with no qualifier, the bean
automatically has the qualifier @Default. The following code is
identical to the previous one.

 

If you only have one implementation
of a bean to inject, the default behaviour applies and a straight
forward @Inject does the job. But sometimes you have to choose
between several implementations, that’s where qualifiers come into
play.

 

I first mentioned that no XML was
needed in CDI. Well, it’s not completely true. To make CDI work you
need a beans.xml file in your classpath (in the META-INF or WEB-INF
directory). The good news is this beans.xml file is usually totally
empty (except for alternatives as you’ll see later). This file
tells CDI to discover beans (aka bean discovery) in the
application.

 

   
  

Ambiguous Injection and
Qualifiers

 

For a given bean type, there may be
multiple beans which implement the type. Coming back to our
example, a component can choose between two implementations
(SimpleEmailService or RichEmailService) of the interface
EmailService. How do you make the choice? Most frameworks heavily
rely on external XML configuration to declare and inject beans. CDI
uses qualifiers, which basically are annotations. That’s how type
safe injection comes into play (strong typing).

 

Coming back to the previous code, as
you saw, it will work if you only have one implementation, but if
you try to run it with more than one implementation of the
interface EmailService, this is the kind of error that you will get
:

 

 

The injection is ambiguous, CDI
doesn’t know which bean to inject (either SimpleEmailService or
RichEmailService). It needs some way to distinguish between the two
different managed beans. One approach would be for the client to
explicitly specify the class that implements the EmailService
interface. However, this approach creates a hard dependence (strong
coupling) between client and implementation. To have loose coupling
and strong typing, CDI uses qualifiers.

 

A qualifier represents some semantic
associated with a type that is satisfied by some implementations of
the type. For example, you could introduce qualifiers to represent
rich or simple email service. In Java code, qualifier types are
represented by annotations that you apply to a managed bean defined
as @Target({FIELD, TYPE, METHOD}) and @Retention(RUNTIME). It is
declared by specifying the @javax.inject.Qualifier meta-annotation
as follow:

As you can see, the code above is
quite simple: two annotations annotated with Qualifier. These
qualifiers are then applied to injection points to distinguish
which implementation is required by the client. In Listing 1 the
OrderService explicitly defines which implementation by injecting a
reference of the @Rich EmailService.

 

If you run this code you will not have any ambiguous dependency
any more as CDI knows exactly which implementation of the managed
bean to inject. You could even rename the RichEmailService class to
RichMailerService and the code will work with no other change as
CDI relies on the name of the qualifier, not the name of the
implementation (that’s loose coupling in action). Note that any
bean may declare multiple qualifiers.

Choosing implementation at development time is very useful, but
sometimes you need to choose at deployment time. That’s when you
can use alternatives.

Alternatives

As you’ve just seen, when you have more than one version of a
bean that you use for different purposes, you can choose between
them during the development phase by injecting one qualifier or
another. Qualifiers let us choose between multiple implementations
of an interface at development time. But sometimes you want to
inject an implementation depending upon the deployment environment.
For example, you may want to use a mock email service in a testing
environment. This is possible with alternatives and a bit of
XML.

Alternatives are beans whose implementation is specific to a
particular deployment scenario. They are annotated with the special
qualifier javax.enterprise.inject.Alternative. This is what an
alternative to the rich email service could look like:

As you can see the MockEmailService
implements the EmailService interface as usual. It is both
annotated with @Alternative and @Rich, meaning that this managed
bean is an alternative to the RichEmailService. By default,
@Alternative beans are disabled and you need to explicitly enable
them in the beans.xml descriptor.

 

 

Now if you execute the application
with the following code with the beans.xml file, the OrderService
will get injected the MockEmailService rather than the
RichEmailService.

 

 

If the <alternatives> element
is commented out in the beans.xml file, the RichEmailService class
is used. You can have several beans.xml file declaring several
alternatives depending on your environment (development,
production, test…).

 

If you think of qualifiers being an aggregation of annotations,
then you can refactor your code and create a @Mock qualifier which
is an @Alternative and a @Rich email service. You will then get the
following code :

Now you can go back to the
MockEmailService and change it to being a @Mock. The behaviour is
exactly the same as having @Alternative and a @Rich together in the
same managed bean:

@Inject, alternatives and qualifiers
allow you to have a flexible and type-safe injection model. But the
beauty of it is that you can use this exact injection model in most
of Java EE 6 components.

 

Inject Everything
Everywhere


Java EE 5 was about injecting
resources (Datasource, JMS factories…) to certain components
(mostly EJBs). Java EE 6 is about injecting nearly everything (or
so called managed beans) to nearly all the components. So far
you’ve seen plain old Java objects (POJOs) injecting other POJOs.
But you can inject an EJB into a Servlet or a RESTful Web Service.
Below you can see a servlet injecting our rich email service as
well as an EJB that deals with orders. As you can see, the @Inject
annotation is used exactly the same way in both cases :

Bootstraping CDI in Several
Environments


Both JSRs 299 and 330 are included in Java EE 6 as well as the
Web Profile 1.0 (which is a subset of the entire platform). This
means you don’t have to do any extra work to use injection in a
Servlet 3.0 or EJB 3.1 container. It works out of the box. But the
beauty of CDI is that it doesn’t require Java EE 6. You can use CDI
with simple POJOs in a Java SE environment, as well as some Servlet
2.5 containers (Tomcat 6.5 or Jetty). Of course, because it’s not
built in, you’ll need a bit of configuration. And because this
feature is not standard, each different environment will need its
own configuration. But it then works fine and you can use all the
previous examples within Tomcat 6.5 or even just with Java SE
6.

But There is More to CDI

Injection was already popular in other frameworks
(PicoContainer, Spring, Guice) and it finally became a first class
citizen in Java EE 6. But there is more to CDI that just dependency
injection.

One of the key features of CDI is it knits together the web tier
and the transactional tier (i.e EJBs). So the idea is to make a
managed bean (POJO, EJB…) accessible through expression language
(EL) and therefore be able to use it in JSF and JSP pages. For
that, you just need to give your bean a name with the
@javax.inject.Named built-in qualifier:

The @Named qualifier allows you to
access the managed bean through its name (which by default is the
class name with first letter in lower-case but you can override it
with @Named(“MyEmailService”)). Then you can invoke an attribute
(via its getter and setter) or a method straight in your JSF or JSP
page. The following example shows a JSF page with an input text to
enter the email body and a button to send the email :

 

Another interesting feature in CDI
are scopes and contexts. The scope of a bean determines its
life-cycle. Until now Java EE had stateless and stateful components
which were not tight together (you couldn’t easily tight the life
duration of a HTTP session to a stateful EJB for example). You had
to twist built-in web scopes (request, session and application) to
fit the back-end transactional layer. With CDI things are much
easier and extensible.

 

CDI defines four built-in scopes and
gives you extension points so you can create your own :

 

• @RequestScoped

• @SessionScoped

• @ApplicationScoped

• @ConversationScoped

 

The three first scopes are well
known. For example, if you have a session-scoped bean,
LoggedInUser, the RichEmailService that is called in the context of
the same HttpSession will see the same instance of LoggedInUser.
This instance will be automatically created the first time a
LoggedInUser is needed in that session, and automatically destroyed
when the session ends.

 

 

The conversation scope, however, is
a new one that acts a bit like the session scope: it holds state
associated with a user, spans multiple requests to the server but
is demarcated explicitly by the application.

 

Conclusion

 

Dependency Injection (JSR 330) and
Contexts & Dependency Injection (JSR 299) both bring a
standard, portable and type safe support for dependency injection
to Java EE 6. CDI adds extra features such as scopes and contexts
but also enhanced interceptors, decorators and events. But the
noble goal of CDI is to be a foundation for frameworks which will
extend the platform and integrate with other technologies.
Therefore, CDI exposes a set of SPIs for developers in order to
create portable extensions. The Java EE platform becomes finally
extensible in a standard way.

The good news is that you don’t need
to use a Java EE 6 application server such as GlassFish 3.x or
JBoss 6.x. You can bootstrap CDI in several environments and get
all its benefits with your Servlet 2.5 container (Jetty or Tomcat
6.x) as well as your Java SE application. Being a standard, you can
choose from several implementations (OpenWebBeans from Apache, Weld
from JBoss or CanDI from Caucho) and get started with it now.
Enjoy.

Author
Antonio Goncalves

Antonio Goncalves

All Posts by Antonio Goncalves

Antonio Goncalves is a senior software architect who has focused on Java development since the late 1990s. As a former BEA consultant he has great expertise in application servers such as WebLogic, JBoss, and GlassFish. He is particularly fond of open source and is a member of the OSSGTP (Open Source Solution Get Together Paris). He is also the co-creator and co-leader of the Paris Java User Group. Antonio has joined the JCP and was an Expert Member of various JSRs (Java EE 6, JPA 2.0, and EJB 3.1) and has joined today the Java EE 7 group. For the last few years he has given talks at international conferences mainly about Java EE, including JavaOne, The Server Side Symposium, Devoxx, Jazoon and many Java User Groups. He has also written numerous technical papers and articles. Since 2009, he has been part of the French Java podcast called Les Cast Codeurs (influenced by the Java Posse). For all his work for the Java Community, Antonio has been elected Java Champion.
Comments
comments powered by Disqus