uyetch uyetch - 6 months ago 124
JSON Question

Getting Jersey 2.x POJO JSON support to work with Jetty

I'm new RESTful web services and have been playing around with Jersey and Heroku (which uses a Jetty stack). I'm writing a simple REST API which returns a

Map<String,String>
in JSON for a
GET
request.

I'm however running into a 500 eror. The error message is :

HTTP Status 500 - org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class java.util.LinkedHashMap, genericType=java.util.HashMap<java.lang.String, java.lang.String>.


Below is the code snippet for my resource :

@GET
@Produces("application/json")
public HashMap<String,String> getIt() {
HashMap<String,String> nameValue = new LinkedHashMap<String,String>();
nameValue.put("Alpha","One");
return nameValue;
}


Below is my
web.xml
file:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.example.services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>


Here is my Main class

public class Main {

public static void main(String[] args) throws Exception{
// The port that we should run on can be set into an environment variable
// Look for that variable and default to 8080 if it isn't there.
String webPort = System.getenv("PORT");
if (webPort == null || webPort.isEmpty()) {
webPort = "8080";
}

final Server server = new Server(Integer.valueOf(webPort));
final WebAppContext root = new WebAppContext();

root.setContextPath("/");
// Parent loader priority is a class loader setting that Jetty accepts.
// By default Jetty will behave like most web containers in that it will
// allow your application to replace non-server libraries that are part of the
// container. Setting parent loader priority to true changes this behavior.
// Read more here: http://wiki.eclipse.org/Jetty/Reference/Jetty_Classloading
root.setParentLoaderPriority(true);

final String webappDirLocation = "src/main/webapp/";
root.setDescriptor(webappDirLocation + "/WEB-INF/web.xml");
root.setResourceBase(webappDirLocation);


server.setHandler(root);

server.start();
server.join();
}
}


Even after browsing through previous Stackoverflow answers like this or this, I could not find a way to solve my problem as they do not address Jersey 2.x with Jetty. I've added the following to my pom.xml file, however the problem still persists as unable to register the JSON bindings with the Jetty server.

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>

Answer

Automatic registration of providers by moxy didn't work as stated by Jersey Reference.

As per what they have stated, only moxy and jackson has POJO to JSON conversion feature.

Documentation says Jackson doesn't auto register(Not a problem any way!)

1. Swap Moxy with Jackson in POM.XML

Remove :

<dependency>
 <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-moxy</artifactId>
  <version>${jersey.version}</version>
</dependency>

Add:

<dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <version>${jersey.version}</version>
</dependency>

2. Register Jackson Message Body Readers and Writers :

Add org.codehaus.jackson.jaxrs to provider packages list. Here is my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
    <servlet-name>Web app name</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.myorg.myproj.api;org.codehaus.jackson.jaxrs</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Web app name</servlet-name>
    <url-pattern>/v1/*</url-pattern>
</servlet-mapping>


P.S.
I am not promoting jackson, just that moxy didn't work for me, its writers failed to auto register as they advertised and could not find documentation about manual registration!

Comments