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.

Configuring JSF to work on Tomcat

This project is available on GitHub https://github.com/stuartbrand/JSFforTomcat

I have been using Glassfish and Weblogic for many years and they have been very good to work with. They have lots of features and a comprehensive administration interface.

Glassfish – I noticed that the more Web applications I deployed, the slower the server became. I have one server that even after removing all of the applications and just leaving one it still took 2-3 minutes just to load the list of installed applications. Even clean installs are not as responsive and lean as I would like them to be with each instance taking 500mb of ram just to start up. No good for Microservices.

Weblogic – As with Glassfish, Weblogic has an administrative interface with lots of configurable features. And Weblogic, just like Glassfish,  can also be heavy on the resources, needing 500-1000mb ram just to start up!

So I started to look into other JavaEE application servers. There are lots of JavaEE servers, some of which are derivatives of the open source Glassfish, such as Payara, which is a commercially supported version of Glassfish with patches and updates.

I didn’t want to use just another version of Glassfish or Weblogic, then I came across Tomcat.

Tomcat is small, the install is only 15mb! and when running it only uses 140mb of ram to start up.

Tomcat is also fast, really fast, from the log file on a cold start “Server startup in 360 ms” compare this to the 1-2 minutes that Glassfish or Weblogic can take. And application deployment, again, fast! where Glassfish and Weblogic can take minutes, Tomcat will do the same deployment in seconds.

So, it’s fast, small, quick to deploy, what are the down sides?

Tomcat is lightweight… but this also means it doesn’t do a lot by itself. Tomcat runs on the JVM and doesn’t come with any extra’s.

What do I mean? Glassfish has built in support for Jax-RS and JSF, Weblogic has a suit of extra’s like ASF out of the box. All you do is tell your code that you want to use ASF components and deploy.

So when I tried to move applications over to Tomcat I found out very quickly the limitations of the out of the box server. However, with a little configuration of your web app, Tomcat can handle everything any JavaEE server can.

Now the background is out of the way, let’s get JSF working.

Java Server Faces, or JSF, is a Java specification for building component-based user interfaces for web applications. From your Classes/Beans you can dynamically work with methods from a web page. Working with input forms and buttons to control your methods allows you to create feature rich web apps.

Like I said before, Tomcat does not have a lot features out of the box and you have to configure your web app to use the JSF specification.

This is simple if you are using a Maven based project, a little harder if not, but not too hard. If you don’t use Maven then you will need to download the .jar files and add them to your library.

To start, create a new Maven project. Right click on the new project and go to Properties. Navigate to Frameworks and Add JavaServer Faces. This will configure the web.xml to use the JSF servlet filter but it also adds the following dependancy to your projects pom.xml that isn’t compatible with Tomcat.

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.2.7</version>
</dependency>

Delete this dependancy and add the following dependancies so Maven downloads the required libraries for Tomcat.

<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.13</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.13</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>1.1.10.Final</version>
</dependency>

You may have noticed the weld library, this is a helper servlet that will allow JSF to access your Classes.

Add the following to your web.xml file.

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

One more important configuration that I sometimes miss and it drives me crazy when troubleshooting is the requirement of a special file that serves no purposes other then enabling JSF to use your Classes. It’s called beans.xml.

To add beans.xml just right click on your project and New -> Other… and choose the category “Contexts and dependancies” you’ll find the Beans.xml in there, just add it to your project.

Create a new Class called SaySomething with the following contents

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class SaySomething {
public String getHello() {
return “Hello”;
}
}

There are 2 important parts to this class, @Named and @RequestScoped. @Named will make this a managed bean and usable by JSF, @RequestScoped defines the lifecycle of the bean, in this case it will only last in memory for the time of the request.

It is very important to use javax.enterprise.context.RequestScoped and not javax.faces.bean.RequestScoped as the latter will not work with Tomcat.

Now you can use the bean from a JSF page. Open the index.xhtml file that was created when you added the JavaServer Faces framework.

Put the following into the body area #{saySomething.hello}

That’s it, run the application and you should see a web page pop up with the word Hello.

Now you have a JSF configured web app you can add more classes and methods and use these inside JSF components like

<h:outputText value=”#{saySomething.hello}” />

I will be writing other blogs on how to use these components but for now this is a configured running application that is compatible with Tomcat.

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