Jersey Exception : SEVERE: A message body reader f

2019-01-07 23:41发布

问题:

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

回答1:

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



回答2:

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>
    


回答3:

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")


回答4:

just put this

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


回答5:

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.



回答6:

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;


回答7:

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>


回答8:

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 kumarmanoj.mtech@gmail.com
 */
 @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!!!


回答9:

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.



回答10:

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;
}


回答11:

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



回答12:

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



回答13:

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)