/ #Java #Jersey 

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 {
    ...
}