4 Feb 2013

Configuring Tomcat 7 as a JAX-RS server with Jersey

In order to allow Tomcat to serve as a RESTful web server we can use Oracle's RI implementation of JAX-RS, Jersey.

The main principle of the JAX-RS standard is the use of POJO (Plain Old Java Objects) to declare resources that can be accessed through assigned URLs and parameters. Thanks to the use of annotations, the developer can avoid the burden of analyzing and splitting the incoming URLs to redirect the call to the appropriate service; this dispatching job is done by the JAX-RS implementing classes.

To deploy the resources, a subclass of the Application abstract class must be developed. Put simply, this class has methods that return the available resources. When deploying the service, the application server must scan the Application subclasses and record the available resources declared by these.

Let's see how we can configure Tomcat to do this job.

First of all, we need the following Maven dependencies:

<dependencies>
   <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.0.1</version>
   <scope>provided</scope>
   </dependency>
<dependency>
     <groupId>com.sun.jersey</groupId>
     <artifactId>jersey-servlet</artifactId>
     <version>1.10</version>
</dependency>
  </dependencies>

The jersey-servlet artifact includes not only the Jersey Server and the Jersey Core artifacts, but also a servlet which will, upon start, scan and register all root resource classes.

If we don't use Maven, the libraries that must be deployed on the WEB-INF/lib directory are:

asm-3.1.jar
jersey-core-1.10.jar
jersey-server-1.10.jar
jersey-servlet-1.10.jar

Anyway, the servlet has to be declared in our web.xml this way:

<servlet>
    <servlet-name>Root resource classes registry</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
 </servlet>

Please note there is not url-mapping declaration. This servlet is not meant to be called; it serves only as a scanner for Application subclases (as described above) when Tomcat starts. This is also the reason for the <load-on-startup> tag, to ensure the servlet is called during the bootstrap process.

If we have a look into Tomcat's logging, we will see lines like these (shortened for better understanding):

Info: Registering the Jersey servlet application, named com.mworking.rest.AplicationTestRest, at the servlet mapping, /resources/*, with the Application class of the same name
(that is, the servlet has found one Application subclass, namely AplicationTestRest).

Info: Scanning for root resource and provider classes in the Web app resource paths:
  /WEB-INF/lib
  /WEB-INF/classes
Info: Root resource classes found:
  class com.mworking.rest.Customer
(that means, our Application subclass has declared one resource class, Customer)

Info: No provider classes found.

This is the subclass of Application found by Jersey:

@ApplicationPath("/resources")
public class AplicationTestRest extends Application {

@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
        s.add(Customer.class);
        return s;
}
}

And the Customer resource is declared as follows:


@Path("customer")
public class Customer {

@GET
@Produces("text/plain")
public String get() {
return "Customer simple get";
}

}

When calling the URL /<context name>/resources/customer, we will get a "Customer simple get".
From here, you will have a fully functional RESTFul server atop Tomcat. Enjoy!

For more information, have a look at the Jersey User Guide.

2 comments:

Unknown said...

Hi Angel,
I think the jar name jersey-servñet-1.10.jar should be modified. I couldn't find such jar.

Unknown said...

Hi Denis,
thank you for the hint. The right name is "servlet".
Regards