13
votes

I am using a JAX-RS web application with Jersey and Tomcat. Get requests are fine however when I try to post JSON I get an HTTP status 415 - Unsupported Media Type.

Here is my simple HelloWorld.java:

package service;

import javax.ws.rs.*;

@Path("hello")
public class HelloWorld {
    @GET
    @Produces("text/plain")
    public String get() {
        return "hello world";
    }

    @POST
    @Consumes("application/json")
    public String post(JS input) {
        return input.hello;
    }

    public static class JS {
        public String hello;
    }
}

Here is the request I try in Postman (with 'application/json' header):

enter image description here Here is the project layout with libraries: enter image description here

I am using:

  • Java 7 x64
  • Jersey 2.17
  • Tomcat 7.0.62 x64

Thanks!

5

5 Answers

53
votes

The Jersey distribution doesn't come with JSON/POJO support out the box. You need to add the dependencies/jars.

Add all these

With Maven, below will pull all the above in

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.17</version>
</dependency>

For any future readers not using Jersey 2.17 (and using jars directly instead of Maven), you can go here to find the Jersey version you are using, and see what transitive dependency versions you need. The current version of this Jersey dependency uses Jackson 2.3.2. That's the main thing you need to look out for.

3
votes

Gone through a lot of the answers both on this page and others but to no avail. This actually worked for me:

METHOD 1: Instead of passing JSONObject as parameter to the resource method, pass a String rather. Take the String and create an JSONObject with it and then you can use it in you code. Like so,

    @Path("/people")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response doGetperson(String jsonRequest) {
        try { 
            JSONObject requestedJSON = new JSONObject(jsonRequest);

            //So now you can use requestedJSON object created to do your stuff

            return Response.ok("{\"name\":" + requestedJSON.getString("user") + "}").build();
        } catch (Exception ex) {  
            return Response.ok("{ \"name\":\"\"}").build();
        } 
    }

METHOD 2:

Adding this dependency as of September, 2017:

<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-moxy -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.26</version>
</dependency>

Reference from here

1
votes

Check your REST call contentType. It should be contentType: 'application/json', if you are passing json data to POJO class.

0
votes

I was using firebase APIs which was internally using gson (JSON) apis and jersey JSON databinding wanted jersey-media-json-jackson-2.29.jar. Default class path was keeping firebase gson APIs as first JSON APIs and hence things were not working.

Changed the manifest.mf for classpath sequence and things started working for me. Although I couldn't continue with maven in this scenarios and couldn't figure out as how to add our custom classpath in Maven built war's Manifest.mf.

Added below class path entry in Manifest.mf in of dynamic web project. Copied source of my project to source and downloaded jars of maven to web-inf\lib. Created war using eclipse export as WAR file and things worked for me.

Class-Path: jersey-media-json-jackson-2.29.jar jackson-databind-2.9.9.jar gson-2.6.2.jar json-20160212.jar google-http-client-gson-1.21.0.jar

Most of the miscellaneous errors are due to classpath conflicts when you are using multiple APIs in your project. Gets really difficult to figure out.

-1
votes

I think you post request is working correctly but your browser/Postman can not parse the response returned from the service. It is returning plain text and Postman is waiting json. Add Produce annotation to your web service and set it to json too. I also suggest you to check with Fiddler2 to see exact information going over the wire.