Jersey Test Framework with Maven
Introduction
This memo records the issues while executing the unit-test with Jersey Test framework. We use the Jersey framework to implement the RESTful Web services and employ the Maven to manage the dependencies in project. First of all, we add the jersey-test-framework-grizzly2
dependency to enable the test framework in pom.xml
; Second, we deploy the application using Jersey specific servlet in web.xml
. Finally, we have the following java files within Maven Archetype – maven-archetype-webapp
:
- src/main/java – PersonResource.java (RESTful Resource)
- src/main/java – Person.java (POJO class)
- src/test/java – PersonResourceTest.java (Test Case)
The POJO class Person with two fields/properties/attributes, i.e., Name
and Country
with corresponding getter/setter functions. The PersonResource.java represents the RESTful Web service, here, we simply declare a Person instance and set the values. In test case PersonResourceTest.java, we’ll demonstrate how to retrieve/mapping the response.
PersonResource.java
package net.jersey.rest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import net.jersey.pojo.Person;
@Path("person")
public class PersonResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response fetchPerson(){
Person person = new Person();
person.setName("MyName");
person.setCountry("Taiwan, R.O.C.");
return Response.status(200).entity(person).build();
}
}
Person.java
package net.jersey.pojo;
import javax.xml.bind.annotation.XmlRootElement;
import org.codehaus.jackson.annotate.JsonProperty;
@XmlRootElement
public class Person {
private String name;
private String country;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
Here we use GenericType<T>
to restore the client response and map into the Person class we defined. Moreover, if we want to evaluate the HTTP Response status, we can utilize the ClientResponse
class.
PersonResourceTest.java
package net.jersey.rest;
import static org.junit.Assert.assertEquals;
import javax.ws.rs.core.MediaType;
import net.jersey.pojo.Person;
import org.junit.Test;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.test.framework.JerseyTest;
public class PersonResourceTest extends JerseyTest {
public PersonResourceTest() throws Exception {
super("net.jersey.rest");
}
@Test
public void testFetchPerson() {
WebResource webResource = resource();
Person person = webResource.path("person")
.accept(MediaType.APPLICATION_JSON)
.get(new GenericType<Person>(){});
assertEquals("MyName", person.getName());
}
}
The corresponding test result after running this single test as shown as following:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running net.jersey.rest.PersonResourceTest
Mar 05, 2013 5:52:09 PM com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory$GrizzlyWebTestContainer
INFO: Creating Grizzly2 Web Container configured at the base URI http://localhost:9998/
Mar 05, 2013 5:52:09 PM org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [localhost:9998]
Mar 05, 2013 5:52:09 PM org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
Mar 05, 2013 5:52:09 PM org.glassfish.grizzly.servlet.WebappContext deploy
INFO: Starting application [TestContext] ...
Mar 05, 2013 5:52:09 PM org.glassfish.grizzly.servlet.WebappContext initServlets
INFO: [TestContext] Servlet [com.sun.jersey.spi.container.servlet.ServletContainer] registered for url pattern(s) [[/*]].
Mar 05, 2013 5:52:09 PM org.glassfish.grizzly.servlet.WebappContext deploy
INFO: Application [TestContext] is ready to service requests. Root: [].
Mar 05, 2013 5:52:09 PM com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory$GrizzlyWebTestContainer start
INFO: Starting the Grizzly2 Web Container...
Mar 05, 2013 5:52:09 PM org.glassfish.grizzly.servlet.ServletHandler loadServlet
INFO: Loading Servlet: com.sun.jersey.spi.container.servlet.ServletContainer
Mar 05, 2013 5:52:09 PM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages: net.jersey.rest
Mar 05, 2013 5:52:09 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found: class net.jersey.rest.PersonResource
Mar 05, 2013 5:52:09 PM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
Mar 05, 2013 5:52:09 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.17 01/17/2013 03:31 PM'
Mar 05, 2013 5:52:10 PM com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory$GrizzlyWebTestContainer stop
INFO: Stopping the Grizzly2 Web Container...
Mar 05, 2013 5:52:10 PM org.glassfish.grizzly.http.server.NetworkListener stop
INFO: Stopped listener bound to [localhost:9998]
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.707 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Convert JSON to POJO
Mar 05, 2013 3:01:43 PM com.sun.jersey.spi.container.ContainerResponse write
SEVERE: A message body writer for Java class net.jersey.pojo.Person, and Java type class net.jersey.pojo.Person, and MIME media type application/json was not found
Maven developers, using JSON serialization support of JAXB beans when using the MIME media type application/json require a dependency on the jersey-json module (no explicit dependency on jaxb-impl is required), append the dependency in pom.xml
.
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.17</version>
</dependency>
JAXB
SEVERE: The registered message body writers compatible with the MIME media type are:
application/json ->
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$App
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$App
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
*/* ->
...
Here we need to add a XmlRootElement
annotation on that pojo-class, i.e., Person.java, this will enable jaxb to convert to and from json where necessary. The @JsonProperty annotation is used to customize the string filed in JSON output which is not necessary.
package net.jersey.pojo;
import javax.xml.bind.annotation.XmlRootElement;
import org.codehaus.jackson.annotate.JsonProperty;
@XmlRootElement
public class Person {
...
}