Enterprise Java

Simple CRUD using Servlet 3.0, Redis/Jedis and CDI – Part 2

In this post we will focus on CDI and Servlet 3.0. You can see part 1 here.

Let’s start with CDI.

When I started writing the post that originated this serie, I was not thinking in writing about CDI. To be sincere I’ve never used that before. The idea of the post was to create a crud using jedis and servlets. But when I was writing the application I simply hated the idea to instantiate the beans. In my daily job I use Spring for dependency injection and other stuff, but for this post I wouldn’t like to add it. So, I decided to try CDI and I was very surprised on how simple is to add and use it in the application.

So, what is CDI?

CDI is the acronym for Context and Dependency Injection, is the javaee specification to address DI on javaee platform. So, once it is activated in your project you can easily inject a dependency by using the @Inject annotation. On CDI everything is a bean,
and almost all classes can be injected.

How to activate CDI?

If we are running our app in a Java EE application server, we need only to add an empty beans.xml in our META-INF folder. But in servers like tomcat, we need to add some more files and configurations:

  1. Add weld-servlet.jar in the lib folder. You can get it from the Weld website;
  2. Create a file context.xml under META-INF:
    <?xml version="1.0" encoding="UTF-8"?>
    <Context>
    <Manager pathname=""/> <!-- disables storage of sessions across restarts -->
    <Resource name="BeanManager"
    auth="Container"
    type="javax.enterprise.inject.spi.BeanManager"
    factory="org.jboss.weld.resources.ManagerObjectFactory"/>
    </Context>
  3. Add some weld configurations on web.xml:
    <listener>
    		<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
    	</listener>
    
    	<resource-env-ref>
    		<resource-env-ref-name>BeanManager</resource-env-ref-name>
    			<resource-env-ref-type>
    				javax.enterprise.inject.spi.BeanManager
    			</resource-env-ref-type>
    	</resource-env-ref>
  4. Then we need only to add an empty beans.xml on META-INF or WEB-INF.

After that we are ready to start coding with CDI.

In the last post we created a UserDAO class, in the methods we used a instance of Jedis class to perform Redis commands. This instance was injected into UserDAO object by using the @Inject annotation. We can see that below:

public class UserDAO {

	@Inject Jedis jedis;
        //....
}

As we can see, it is so simple to inject an instance of Jedis class. If the Jedis class had a constructor with no argument it would be injected directly. But it doesn’t, so we used a class with a method annotated with @Produces. This indicates that this is a producer method. In our example we also used a JedisPool where we get the Jedis connections from. In this case we have two producers:

  1. For the JedisPool
  2. Other for Jedis connection.

The Jedis producer has an instance of the JedisPool injected via @Inject, we can see them below:

JedisPoolFactory:

public class JedisPoolFactory {

	private String host = "localhost";
	private JedisPool jedisPool;
	@Singleton
	public @Produces JedisPool getJedisPool(){
		jedisPool = new JedisPool(new JedisPoolConfig(), host);
		return jedisPool;
	}

	public void detroy(@Disposes JedisPool jedisPool){
		jedisPool.destroy();
	}
}

In the code we see that the method getJedisPool is annotated with @Produces, saying it is a producer of JedisPool instances. In this code we see also two other annotations.

  1. @Singleton– saying the returned instance is a singleton, that means there will be only one instance of this class;
  2. @Disposes – Indicating which method should be called when destroying a instance of JedisPool;

Now we can see the JedisConnectionFactory:

public class JedisConnectionFactory {

	@Inject
	private JedisPool jedisPool;

	@Produces 
	public Jedis getJedis(){
		return jedisPool.getResource();
	}

	public void returnResource(@Disposes Jedis jedis){
		System.out.println("Returning jedis Connection");
		jedisPool.returnResource(jedis);
	}

}

To get a Jedis instance the class needs a JedisPool instance. The JedisPool is injected via @Inject and it is created by the producer method we saw in the last code. It also has a @Disposes that simply returns the connection to the Pool.

So, this way we can inject the Jedis instance into the DAO. Then in the other classes we simply use the @Inject, as we can see in the Service and Servlet class:

//UserService
@RequestScoped
public class UserService {

	@Inject
	UserDAO userDAO;
//...
}

//Servlet - UserController
public class UserController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Inject UserService userService;
//...
}

In this example we can see how simple is to add and use CDI in the application.

Servlet 3.0

The main difference we have on new servlets is that we don’t need to declare them in the web.xml, now we can simply set the servlet settings by using annotations. In the servlet we built in our example we used the annotation to set the url mapping for our servlet. Who already have developed a servlet before knows that it is one of the configurations we need to add on web.xml. We can see it in the servlet below:

@WebServlet("/UserController")
public class UserController extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@Inject UserService userService;
//...

//.. doGet
//.. doPost

}

In the code above we are saying the servlet will respond to the /UserController path. With this annotation we can add more configurations like:

@WebServlet(value="/UserController", name="userServlet")

In the code above we declared the mapping and the servlet name. There are other annotations to simplify the usage of servlets api, like @WebInitParam, @WebListener, @WebFilter. We will not talk about them but you can find great resources about them. Also, since servlets 3.0 there is support for async processing.

That’s it for today. Any comments or suggestions are welcome.

  • You can find the source code here.

 

Francisco Ribeiro Junior

Francisco is a senior software engineer working in the telecom/banking domain focused on Web Content Management. He has been technical lead on many projects for different Brazilian and worldwide clients.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button