Configuring Contexts and Dependency Injection on Tomcat

Contexts and Dependency Injection? CDI? What’s that?

The most fundamental services provided by CDI are as follows:

  • Contexts: The ability to bind the lifecycle and interactions of stateful components to well-defined but extensible lifecycle contexts
  • Dependency injection: The ability to inject components into an application in a typesafe way, including the ability to choose at deployment time which implementation of a particular interface to inject

And in English? Contexts define how long a class will remain and will be usable in memory. This is defined by something called scope.

The most common scopes are:

  • Request
  • Session
  • Application

The javax.enterprise.context.RequestScoped scope means that the class is created at the start of your request and destroyed at the end. This can be used for a query from a database, like retrieving a list of values to populate a selection box, or maybe submitting a input text which only requires to write and forget.

The javax.enterprise.context.SessionScoped scope will cause any classes annotated to last for the length of the session. This means that if the class is called when you load the site then it will exist in memory until either the session timeout ends or you close the browser. You need to be careful with this one as you can run out of memory if too many classes exist as each will require memory while you use them. Session scopes are useful for holding variables that you would want for the whole session, like a login token.

The javax.enterprise.context.ApplicationScoped scope is a global scope, and it will last for as long as the application is running on the server and can be accessed by any session. If you store a variable in an application scoped class, then if one session writes to it another session, it can read from it, as in another user on another computer can read from it. This can be useful for information you may want to share without the need to have multiple calls to classes, such as the server status or logs.

Make sure you use the right javax.enterprise.context import as the faces one will not work with Weld.

Dependency injection is a really useful service, and I really mean useful. Before Dependency injection you would need to use creative ways of passing information between classes, without the classes being able to see each other.

It’s hard to explain how difficult it used to be before Dependency injection. You would have a class that returned some values, they would be displayed on a web page, and then you would need to use the web page to pass the values to the next class.

So if you had a class that was holding a login token and you wanted to see the user name that it was assigned to and then save that to a database log,  you would need to pass that value to the web page and then pass it back again on a user action. Very hard to work with when you compare how to do it with Dependency injection.

To use Dependency injection all you need to do is annotate a variable with @Inject

@Inject
UserManager um;

This will create a shared instance of the class that can also be used in other classes, depending on the scope. Now you can set a variable like um.loginTime and then use the same variable data in another class that has the same injection to write to a database.

Tomcat does not have CDI “out of the box” and requires a little configuration of your application, namely the Weld Library.

There are 3 parts to enable CDI on Tomcat. The Weld Library needs to be included (pom.xml), a listener needs to be declared (web.xml) and a little magic file needs to be created (beans.xml).

Add the following to the dependencies section of your pom.xml (Maven):

<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>1.1.10.Final</version>
</dependency>

Add the following to your WEB-INF/web.xml:

<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>

Create a new file called WEB-INF/beans.xml with the following:

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://xmlns.jcp.org/xml/ns/javaee&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd&#8221;
bean-discovery-mode=”annotated”>
</beans>

That’s it. You can now inject classes into other classes without the need for the new Class() declaration and also share the instance.

Well, again, I hope this has helped someone and I look forward to your comments.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s