JAX-RS using Resteasy and Maven on Tomcat 7
Create a basic Maven project called RestTest with no archetype in Eclipse. Add the dynamic web project facet to your project and let Eclipse generate a default web.xml
file for you. Then add the following Resteasy dependencies to your pom.xml
:
<!-- JAX-RS -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.5.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
<version>2.3.5.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jettison-provider</artifactId>
<version>2.3.5.Final</version>
</dependency>
Add the following servlet and servlet mapping to your web.xml
:
<servlet>
<servlet-name>RestServlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<servlet-mapping>
<servlet-name>RestServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Now lets create a very basic JAX-RS service:
package com.rest.test;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/")
public class CatService {
@Path("cats")
@GET
@Produces("application/json; charset=UTF-8")
public List<Cat> getCats() {
final List<Cat> cats = new ArrayList<Cat>();
cats.add(new Cat("Julien", 2));
cats.add(new Cat("Tom", 6));
return cats;
}
}
And a small model class:
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Cat {
public String name;
public int age;
public Cat() {
// Resteasy demands a no-arg constructor
}
public Cat(final String name, final int age) {
this.name = name;
this.age = age;
}
}
Publish to Tomcat and start the server. On startup you should see something like this in your console:
INFO: Adding scanned resource: CatService
Resteasy automatically picked up your service. Try it yourself and call the following URL in your browser: http://localhost:8080/RestTest/rest/cats. You should get the following:
[{"cat":{"name":"Julien","age":2}},{"cat":{"name":"Tom","age":6}}]
In my previous blog post I explained how to setup the same project using Jersey as JAX-RS implementation on Tomcat. A few notes on what’s different here:
- Resteasy needs one more Maven dependency in the pom.xml
- We have to explicitly enable automatic resource scanning in
web.xml
- We have to explicitly define another mapping prefix in
web.xml
- No changes in our Java classes
- We have to annotate our model class with
@XmlRootElement
to enable JSON output via JAX-B. This is actually normal behaviour and I was a little surprised Jersey did this without any annotation present. So you shouldn’t rely on that anyway. - I also noticed, that Resteasy threw an exception when there was no empty constructor in the model class. This is possibly just a consequence of
@XmlRootElement
. - The JSON output format is different. Resteasy gives a name to our cat objects and wraps them in another object. This could affect processing of our JSON output at the consumer side (e.g. jQuery).
So Resteasy needs a tiny bit of additional configuration, but that carries no weight. More important is, that I ran into a serious issue when I tried to add CDI to the Jersey project (adding the Weld dependencies and the Weld listener in web.xml). Tomcat no longer started properly, but threw an exception: java.lang.NoClassDefFoundError: javax/annotation/ManagedBean
. There is a question on stackoverflow for this problem, but no real solution.
So the next thing I will try is adding CDI to the Resteasy version of this project.