Search code examples
javajerseyjacksontomcat7

Jersey JSON serialization


I set up an eclipse WebApp project and placed Jersey and Jackson JARs in the WEB-INF/lib directory. I want to use JSON serialization but didn't manage to fix this error:

MessageBodyWriter not found for media type=application/json, type=class com.rest.Greeting, genericType=class com.rest.Greeting. I already googled much but all the solutions are updated or don't solve my issue. Here is the structure of my project:

The WEB-INF/lib folder contains following JARs:

aopalliance-repackaged-2.3.0-b10.jar
asm-debug-all-5.0.2.jar
cglib-2.2.2.jar
datafactory-0.8.jar
hk2-api-2.3.0-b10.jar
hk2-locator-2.3.0-b10.jar
hk2-utils-2.3.0-b10.jar
jackson-annotations-2.4.0.jar
jackson-core-2.4.0.jar
jackson-databind-2.4.0.jar
jackson-jaxrs-base-2.4.0.jar
jackson-jaxrs-json-provider-2.4.0.jar
jackson-module-jaxb-annotations-2.4.0.jar
javassist-3.18.1-GA.jar
javax.annotation-api-1.2.jar
javax.inject-2.3.0-b10.jar
javax.servlet-api-3.0.1.jar
javax.ws.rs-api-2.0.1.jar
jaxb-api-2.2.7.jar
jersey-client.jar
jersey-common.jar
jersey-container-servlet-core.jar
jersey-container-servlet.jar
jersey-guava-2.13.jar
jersey-server.jar
org.osgi.core-4.2.0.jar
osgi-resource-locator-1.0.1.jar
persistence-api-1.0.jar
validation-api-1.1.0.Final.jar

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Rest Test</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Greeting</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.rest</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Greeting</servlet-name>
    <url-pattern>/greet/*</url-pattern>
  </servlet-mapping>
</web-app>

Greeting.java:

@XmlRootElement
@Path("/greeting")
public class Greeting {
    
    private String greeting;
    
    public Greeting() {
        this.setGreeting("hello");
    }
    
    @GET
    @Produces(MediaType.TEXT_XML)   
    public Greeting sayHello() {
        return new Greeting();
    }

    public String getGreeting() {
        return greeting;
    }

    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }
    
}

The WebApp project is run in an embedded Tomcat v7 server (view "Servers" in eclipse). The request:

http://localhost:8080/com.rest/greet/greeting

As long as I use MediaType.TEXT_XML there is no error and the content looks like this:

<greeting>
<greeting>hello</greeting>
</greeting>

When I change MediaType to "MediaType.APPLICATION_JSON" then the following exception (as described above) is thrown. I already noticed that it depends on the annotation "@XmlRootElement" but there is not something like "JsonRootElement" and the jackson/genson APIs claim that it works out of the box (due to the auto registration mechanism). Do you have any idea how to fix it?

Every help is very very appreciated!


Solution

  • All you need is to register JacksonJsonProvider. There are many ways to achieve that:

    1. Register the JacksonJsonProvider explicitly in web.xml:
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider</param-value>
    </init-param>
    

    or

    1. Register your class extending javax.ws.rs.core.Application in the web.xml
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>com.rest.MyApplication</param-value>
    </init-param>
    

    and then do all the configuration in the application class:

    package com.rest;
    
    import org.glassfish.jersey.server.ResourceConfig;
    import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
    
    public class MyApplication extends ResourceConfig {
    
        public MyApplication() {
            packages("com.rest");
            register(JacksonJsonProvider.class);
        }
    

    ResourceConfig is a subclass of javax.ws.rs.Application and gives you some helper methods that makes the registration easy.

    or

    1. Use automatic registration. Just add dependency to jersey-media-json-jackson
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.13</version>
    </dependency>
    

    But be careful. It will register more than you need:

    • JacksonJaxbJsonProvider,
    • JsonParseExceptionMapper,
    • JsonMappingExceptionMapper

    Take a look at the source code to see what it does.