无法找到内容类型为application/json且类型为java.lang.String的MessageBodyReader

22
我使用带有jackson提供程序的RestEasy客户端,遇到了上述错误。
客户端代码如下:
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() 抛出ClientResponseFailure异常,错误信息为

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

我的服务器端代码如下:

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

  return gson.toJSON(object);
}
8个回答

61
你可以尝试将以下依赖项添加到你的Maven pom文件中。
   <dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-jackson-provider</artifactId>
    <version>2.3.4.Final</version>
   </dependency>

6
请注意,resteasy-jackson-provider似乎已经被弃用了(http://docs.jboss.org/resteasy/docs/3.1.0.Final/javadocs/org/jboss/resteasy/plugins/providers/jackson/ResteasyJacksonProvider.html),而resteasy-jackson2-provider是新的工件。 - Pieter De Bie

8
问题实际上是RestEasy无法找到Jackson提供程序。我必须通过以下代码手动注册它:
   ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
    RegisterBuiltin.register(instance);
    instance.registerProvider(ResteasyJacksonProvider.class);

这个方案目前工作正常。但是我对它并不满意,因为Resteasy本应该自动扫描提供者并注册它们。


1
我将resteasy、jaxrs、resteasy-spring和jackson库更新到最新版本,并使它们无缝运行。 - user1632803
您还可以从components.xml声明式地注册提供者: - tkotisis
1
RESTeasy自行进行一些动态类加载,这在OSGi环境中会引起问题,因为所需的类可能无法被OSGi类加载器找到。在这种情况下,手动添加所需的类是有意义的。 - Gregor

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

这解决了我的问题!谢谢。我使用了 Response response = target("path here").register(ResteasyJacksonProvider.class).request().get(); - Jad Chahine

2

只需将org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider一行添加到META-INF/services/javax.ws.rs.ext.Providers文件中,就可以解决问题。

这个文件包含在resteasy-jackson-providers.jar中,但是同样的文件也包含在另一个jar文件restasy-jaxrs.jar中,对于使用这两个jar文件的可执行jar文件,它们没有合并!


1
谢谢,这让我找对了方向。事实上,如果您将几个Java组件合并成一个JAR,则需要合并不同的javax.ws.rs.ext.Providers。Gradle阴影插件例如具有名为mergeServiceFiles的函数,但必须在build.gradle中显式调用:shadowJar { mergeServiceFiles() } - ocroquette

1

让我的代码工作的因素是我添加了:

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

除此之外,我不知道为什么,但似乎resteasy在创建客户端时没有初始化提供程序,这意味着需要手动初始化它们:
 ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
 RegisterBuiltin.register(instance);
 instance.registerProvider(ResteasyJackson2Provider.class);

通常只需运行客户端即可。

1
我遇到了类似的问题,后来发现这个问题与 resteasy-jackson-provider 的版本有关。我将版本从 3.0.4.Final 更改为 3.0.5.Final,问题就解决了。
此外,我还发现如果将第三行更改为以下内容,则可以得到预期的结果,无需更改依赖项。
Response response = request.get(Object.class).toString();

0

我不知道背后的全部原理,但我们已经遇到了完全相同的问题(多次:P),你需要将MediaType更改为TEXT_PLAIN

或者你也可以让JAX-RS代劳:不用再使用gson.toJSON(object),只需返回对象并更改方法签名为所需的类。JAX-RS(在你的情况下是RESTEasy)会自动调用Jackson(如果正确配置)并将对象序列化为json。然后在客户端上,你将请求相同的类而不是字符串,一切应该能够自动完成。我对ClientRequest/Response并不是特别熟悉,所以它可能不像我说的那样工作;我们在客户端上使用RESTEasy代理功能(参见ProxyFactory)。尽管如此,JAX-RS/RESTEasy也可以在客户端上自动执行json序列化/反序列化,因此肯定有一个方法可行。


我通过显式注册ResteasyJacksonProvider使其正常工作。RestEasy本应自动完成此操作,但我不知道为什么它没有注册提供程序。我正在使用Spring与Resteasy。ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance(); RegisterBuiltin.register(instance); instance.registerProvider(ResteasyJacksonProvider.class); - user1632803

0

如果你真的想绕过 JAX-RS 的序列化功能(而不是手动调用 GSON),可以使用 StreamingOutput(即将输出器包装为 StreamingOutput,并返回该对象)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接