38
votes

I have a Jersey based Rest WS which outputs JSON. I am implementing a Jersey Client to invoke the WS and consume the JSON response. The client code I have is below

WebResource r = restClient.resource(UriBuilder.fromUri("http://localhost/").port(8080).build());
String resp = r.path("/user").accept(MediaType.APPLICATION_JSON).get(String.class);
User[] users = r.path("/user").accept(MediaType.APPLICATION_JSON).get(User[].class);

The 2nd line outputs the JSON string response correctly, however the 3rd line to marshal JSON to the POJO is not happening and I get the following exception stacktrace

SEVERE: A message body reader for Java class [Lorg.shoppingsite.model.entity.jpa.User;, and Java type class [Lorg.shoppingsite.model.entity.jpa.User;, and MIME media type application/json was not found
Dec 21, 2011 11:32:01 AM com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: The registered message body readers compatible with the MIME media type are:
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
  com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
  com.sun.jersey.core.impl.provider.entity.EntityHolderReader

I have the correct MIME TYPES in my request. My POJO has been annotated with XMLRootElement. What am I missing.

Thank you

15
Just FYI... In my case, the code ran fine inside IntelliJ but failed when it was packaged and deployed. I was using the maven-assembly-plugin with jar-with-dependencies option. I'm going to change to use Jackson ObjectMapper which is a work around.PatS
@PatS I am facing a similar issue. The code is running fine when its run using Intellij but throwing same error when packaged. Unlike you I don't have liberty to use Jackson ObjectMapper as the issue is in a dependency. Have you found an alternative solution to your problem?Ajay
@Ajay. The solution I marked worked for me. My guess is that in your IntelliJ you have some jar file that is needed or is "the right version" and it is picked over another file. These kinds of problems are difficult. I would suggest trying to use Shade Plugin (See maven.apache.org/plugins/maven-shade-plugin) and enable debugging to see what classes are duplicates. Most likely the code is pulling in the wrong version of a file when running outside of IntelliJ.PatS

15 Answers

35
votes

To make it work you only need two things. Check if you are missing:

  1. First of all, you need @XmlRootElement annotation for your object class/entity.
  2. You need to add dependency for jersey-json if you are missing.For your reference I added this dependency into my pom.xml.

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>1.17.1</version>
    </dependency>
    
34
votes

I was able to fix the issue by adding the maven dependency for jersey-json.

11
votes

just put this

    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
11
votes

I know that this post is old and you figured this out a long time ago, but just to save the people who will read this some time.

You probably forgot to add annotation to the entity you are passing to the endpoint, so Jersey does not know how to process the POJO it receives. Annotate the pojo with something like this:

@XmlRootElement(name = "someName")
8
votes

If you are building an uberjar or "shaded jar", make sure your meta inf service files are merged. (This bit me multiple times on a dropwizard project.)

If you are using the gradle shadowJar plugin, you want to call mergeServiceFiles() in your shadowJar target: https://github.com/johnrengelman/shadow#merging-service-files

Not sure what the analogous commands are for maven or other build systems.

3
votes

In my case, I'm using POJO. And I forgot configure POJOMappingFeature as true. Maycon has pointed it out in an early answer. However some guys might have trouble to configure it in web.xml correctly, here is my example.

<servlet>
    <servlet-name>Jersey Servlet</servlet-name>
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
3
votes

We also decided to use jersey as a solution. But as we are using org.JSON in most of the cases this dependency is unecessary and we felt not good.

Therefore we used the String representation to get a org.JSON object, instead of

JSONObject output = response.getEntity(JSONObject.class); 

we use it this way now:

JSONObject output = new JSONObject(response.getEntity(String.class)); 

where JSONObject comes from org.JSON and the imports could be changed from:

-import org.codehaus.jettison.json.JSONArray;
-import org.codehaus.jettison.json.JSONException;
-import org.codehaus.jettison.json.JSONObject;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
3
votes

Just add below lines in your POJO before start of class ,and your issue is resolved. @Produces("application/json") @XmlRootElement See example import javax.ws.rs.Produces; import javax.xml.bind.annotation.XmlRootElement;

 /**
 * @author manoj.kumar
 * @email [email protected]
 */
 @Produces("application/json")
 @XmlRootElement  
 public class User {

 private String username;
 private String password;
 private String email;
 public String getUsername() {
 return username;
 }
 public void setUsername(String username) {
     this.username = username;
 }
 public String getPassword() {
     return password;
 }
 public void setPassword(String password) {
     this.password = password;
 }
 public String getEmail() {
    return email;
 }
 public void setEmail(String email) {
    this.email = email;
 }

}
add below lines inside of your web.xml
<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>  
Now recompile your webservice everything would work!!!
2
votes

Try adding:

<dependency>
    <groupId>com.owlike</groupId>
    <artifactId>genson</artifactId>
    <version>1.4</version>
</dependency>

Also this problem may occur if you're using HTTP GET with message body so in this case adding jersey-json lib, @XmlRootElement or modifying web.xml won't help. You should use URL QueryParam or HTTP POST.

0
votes

You need to implement your own MessageBodyReader and MessageBodyWriter for your class Lorg.shoppingsite.model.entity.jpa.User.

package javax.ws.rs.ext;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

public interface MessageBodyReader<T extends Object> {

    public boolean isReadable(Class<?> type, 
        Type genericType, 
        Annotation[] annotations, 
        MediaType mediaType);

    public T readFrom(Class<T> type, 
        Type genericType, 
        Annotation[] annotations, 
        MediaType mediaType, 
        MultivaluedMap<String, String> httpHeaders, 
        InputStream entityStream) throws IOException, WebApplicationException;
}

package javax.ws.rs.ext;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;

public interface MessageBodyWriter<T extends Object> {

    public boolean isWriteable(Class<?> type, 
        Type genericType, 
        Annotation[] annotations, 
        MediaType mediaType);

    public long getSize(T t, 
        Class<?> type, 
        Type genericType, 
        Annotation[] annotations, 
        MediaType mediaType);

    public void writeTo(T t, 
        Class<?> type, 
        Type genericType, 
        Annotation[] annotations, 
        MediaType mediaType, 
        MultivaluedMap<String, Object> httpHeaders, 
        OutputStream entityStream) throws IOException, WebApplicationException;
}
0
votes

Just check if you are running different instances in eclipse. I quit all my other sessions, clean build fixed the problem

0
votes

Some may be confused why add jersey-json jar can't solve this problem. I found out that this jar has to newer than jersey-json-1.7.jar( 1.7.0 doesn't work, but 1.7.1 works fine.). hope this can help

0
votes

for Python and Swagger example:

import requests
base_url = 'https://petstore.swagger.io/v2'
def store_order(uid):
    api_url = f"{base_url}/store/order"
    api_data = {
        'id':uid,
        "petId": 0,
        "quantity": 0,
        "shipDate": "2020-04-08T07:56:05.832Z",
        "status": "placed",
        "complete": "true"
        }
    # is a kind of magic..
    r = requests.post(api_url, json=api_data)
    return r
print(store_order(0).content)    

Most important string with MIME type: r = requests.post(api_url, json=api_data)

0
votes

Q) Code was working fine in Intellj but failing in command line.

Sol) Add dependencies of jersey as a direct dependency rather than a transient one.

Reasoning: Since, it was working fine with IntelliJ, dependencies are correctly configured.

  1. Get required dependencies by one of the following:

    1. check for the IntelliJ running command. Stackoverflow-link
    2. List dependencies from maven mvn dependency:tree
  2. Now, add those problematic jersey dependencies explicitly.

-3
votes

Mine was similar situation. I get this error in crucial times and I did not remember how I had solved it before, which I did many number of times. After strenuous hours of inspection, I have solved and reproduced the error and made sure how simple is the solution for this situation.

Okay - solution : remove (or correct) any newly made changes to your main project's properties files.

Yes, this is it. In fact, my project is a multi-moduled huge one, and you know going without correct dependencies is a rare case scenario as is fetched often from git (RAC too). My project was getting almost all configurable things from a properties file that is common to about 15 or so modules (sub projects) with good amount of intra-dependencies among them. jersey-json's dependency is always there in my merged parent pom. XML Annotations aren't a problem as the project is being run for around 100 times after modifying them. some solutions here point to web.xml and things like POJOMappingFeature. In my case, I haven't even touched the webapp module in this build. so anyhow, this solution worked for me and I am spending time to record this in SO in case if I ever happen to fall into this error, I would not have to waste my sleepy nights. (of course, for you too)