22

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);
}
user1632803
  • 301
  • 1
  • 3
  • 5

8 Answers8

61

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>
Dog
  • 611
  • 5
  • 3
  • 6
    Note that resteasy-jackson-provider [seems deprecated](http://docs.jboss.org/resteasy/docs/3.1.0.Final/javadocs/org/jboss/resteasy/plugins/providers/jackson/ResteasyJacksonProvider.html) and that resteasy-jackson2-provider is the new artifact. – Pieter De Bie Jul 26 '17 at 07:48
8

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.

StarsSky
  • 6,721
  • 6
  • 38
  • 63
user1632803
  • 301
  • 1
  • 3
  • 5
  • 1
    I updated the resteasy, jaxrs, resteasy-spring, jackson libraries to latest and got them working seamlessly – user1632803 Aug 30 '12 at 12:21
  • You can also register the provider declaratively from components.xml: – tkotisis May 09 '14 at 10:50
  • 1
    RESTeasy does some dynamic class loading on its own and this causes trouble in an OSGi context, where the needed classes may not be found by the OSGi classloader. In this case, manually adding the needed classes makes sense. – Gregor Jun 06 '16 at 13:51
5
Client client = ClientBuilder.newBuilder().register(ResteasyJacksonProvider.class).build();
Bruno Horta
  • 201
  • 3
  • 3
  • This solved my problem! thanks I used `Response response = target("path here").register(ResteasyJacksonProvider.class).request().get();` – Jad Chahine Mar 16 '20 at 12:32
2

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 !!

MatteoM
  • 236
  • 2
  • 9
  • 1
    Thanks, that put me on the right track. As a matter of fact, if you merge several Java components into one JAR, the different javax.ws.rs.ext.Providers need to be merged too. The Gradle shadow plugin has for instance a function called mergeServiceFiles, but it has too be called explicitly in build.gradle:shadowJar { mergeServiceFiles() } – ocroquette Mar 20 '17 at 15:48
1

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();
JCalcines
  • 1,236
  • 12
  • 25
1

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.

Dmitry Svn
  • 71
  • 3
0

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.

Pascal Gélinas
  • 2,744
  • 19
  • 20
  • I got it to work by registering the ResteasyJacksonProvider explicitly. RestEasy was supposed to do this by itself, but I don't know why it is not registering the providers. I am using Resteasy with spring. ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance(); RegisterBuiltin.register(instance); instance.registerProvider(ResteasyJacksonProvider.class); – user1632803 Aug 30 '12 at 10:50
0

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

StaxMan
  • 113,358
  • 34
  • 211
  • 239