2012-01-12

Tip: Getting rid of web.xml using Servlet 3.0

EJB until 2.1 used a tremendous amount of XML configuration files. This has been reduced drastically with EJB 3.0 because it uses a lot of default that mostly fit well. Now this continued to the Servlet 3.0 standard. In the older days we first defined a servlet like this:

 public class KeyServiceServlet extends HttpServlet {  
   @Override  
   public void service(ServletRequest req, ServletResponse res)  
       throws ServletException, IOException {  

Now we need a WEB-INF/web.xml that first defines the Servlet and does a mapping to one or multiple URLs

 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
            http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
   version="3.0" metadata-complete="true">  
   <display-name>Key Service</display-name>  
   <description>  
     Simple frontend for the test service  
   </description>  
   <servlet>  
     <servlet-name>KeyService</servlet-name>  
     <servlet-class>com.prodyna.demo.key.web.KeyServiceServlet</servlet-class>  
   </servlet>  
   <servlet-mapping>  
     <servlet-name>KeyService</servlet-name>  
     <url-pattern>/*</url-pattern>  
   </servlet-mapping>  
 </web-app>  


With Servlet 3.0 we now can use annotations to do the same. We simply take the @WebServlet annotation

 @WebServlet(urlPatterns = { "/*" })  
 public class KeyServiceServlet extends HttpServlet {  
   @Override  
   public void service(ServletRequest req, ServletResponse res)  
       throws ServletException, IOException {  

I personally love the approach of removing unneeded XML and this an example where it really makes sense.

Tip: Injected Logger using CDI

In the good old days we used

        private Logger log = Logger.getLogger( getClass().getName() );  

for creating a logger. This has to be done in all classes that do logging. With CDI we can make our life easier, we simply inject the Logger using

    @Inject   
    private Logger log;   

but we have to define the Producer for the Logger in a separate class that must be part of the same deployment unit.  This can be done using

  package com.prodyna.demo.key.util;   
     
  import java.util.logging.Logger;   
     
  import javax.enterprise.inject.Produces;   
  import javax.enterprise.inject.spi.InjectionPoint;   
     
  public class Resources {   
     
    @Produces   
    public Logger produceLog(InjectionPoint injectionPoint) {   
      return Logger.getLogger(injectionPoint.getMember().getDeclaringClass()   
          .getName());   
    }   
  }   

The effort is ok, because we have to define the Resource class only once and benefit from the shorter Logger definition in multiple places.