Unable to find a MessageBodyReader of content-type

2019-01-14 21:14发布

问题:

I am using RestEasy client with jackson providers and getting the above error

clientside code is:

ClientRequest request = new ClientRequest(url);
request.accept(MediaType.APPLICATION_JSON);
ClientResponse<String> response = request.get(String.class);

if (response.getStatus() != 200) {
  throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}

BufferedReader br =
  new BufferedReader(new InputStreamReader(new ByteArrayInputStream(response.getEntity().getBytes())));

response.getEntity() is throwing ClientResponseFailure exception with the error being

Unable to find a MessageBodyReader of content-type application/json and type class java.lang.String

My server side code is below:

@GET
@Path("/{itemId}")
@Produces(MediaType.APPLICATION_JSON)
public String item(@PathParam("itemId") String itemId) {
  //custom code

  return gson.toJSON(object);
}

回答1:

You could try to add the following dependency to your maven pom.

   <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson-provider</artifactId>
    <version>2.3.4.Final</version>
   </dependency>


回答2:

The problem actually is that RestEasy is unable to find the Jackson provider. I had to manually register it by the following code:

   ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
    RegisterBuiltin.register(instance);
    instance.registerProvider(ResteasyJacksonProvider.class);

Everything is working fine with this. But I am still unhappy with the solution as Resteasy is supposed to scan for the providers and register them automatically.



回答3:

Just adding the line org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider into META-INF/services/javax.ws.rs.ext.Providers file, solves the problem.

This file is included into resteasy-jackson-providers.jar but same file is also included into another jar, restasy-jaxrs.jar and for an executable jar file, that use both these jars, they are not merged !!



回答4:

Client client = ClientBuilder.newBuilder().register(ResteasyJacksonProvider.class).build();


回答5:

I don't know the full rationale behind that but we've hit the exact same problem (multiple times :P) and you need to change the MediaType to TEXT_PLAIN.

Or you can also let JAX-RS do the job for you: instead of doing gson.toJSON(object), simply return object and change your method signature to whatever class that is. JAX-RS (RESTEasy in your case) will automatically call Jackson (if it's properly configured) and serialize your object to json. Then on your client side you would request for that same class instead of String and everything should work on its own. I'm not particularly familiar with ClientRequest/Response so it might not work as I said; we use RESTEasy proxy functionality on the client side instead (see ProxyFactory). Nevertheless, JAX-RS/RESTEasy can do json serialize/deserialize automatically on the client side too so there's definetly a way.



回答6:

If you really want to by-pass goodness of JAX-RS actually doing serialization for you (instead of manually calling GSON), use StreamingOutput (i.e. wrap outputter as StreamingOutput, return that object).



回答7:

I had a similar problem and I realized that the problem was related with the version of resteasy-jackson-provider. I just moved from 3.0.4.Final to 3.0.5.Final and the problem disappeared.

Additionally I also realized that if I change the third line to the following the result was the expected with no need to change the dependencies.

Response response = request.get(Object.class).toString();


回答8:

Things that had made work my code were that I added:

<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson2-provider</artifactId>
    <version>&{resteasy.version}</version>
</dependency>

Beside this I don't know why but it seems that resteasy not initializing providers when client were created, this means that it required to init them manually:

 ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
 RegisterBuiltin.register(instance);
 instance.registerProvider(ResteasyJackson2Provider.class);

In general it's enough to run the client.