【问题标题】:Unable to find a MessageBodyReader of content-type application/json and type class java.lang.String找不到内容类型 application/json 和类型类 java.lang.String 的 MessageBodyReader
【发布时间】:2012-08-23 22:09:44
【问题描述】:

我正在使用带有 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);
}

【问题讨论】:

    标签: json rest jax-rs jackson resteasy


    【解决方案1】:
    Client client = ClientBuilder.newBuilder().register(ResteasyJacksonProvider.class).build();
    

    【讨论】:

    • 这解决了我的问题!谢谢我用Response response = target("path here").register(ResteasyJacksonProvider.class).request().get();
    【解决方案2】:

    使我的代码工作的东西是我添加的:

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

    一般来说,运行客户端就足够了。

    【讨论】:

      【解决方案3】:

      我遇到了类似的问题,我意识到问题与resteasy-jackson-provider 的版本有关。我刚从3.0.4.Final 移动到3.0.5.Final,问题就消失了。

      此外,我还意识到,如果我将第三行更改为以下内容,则结果是预期的,无需更改依赖项。

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

      【讨论】:

        【解决方案4】:

        只需将 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 文件,它们不会合并!!

        【讨论】:

        • 谢谢,这让我走上了正轨。事实上,如果将多个 Java 组件合并到一个 JAR 中,那么不同的 javax.ws.rs.ext.Providers 也需要合并。例如,Gradle 影子插件有一个名为 mergeServiceFiles 的函数,但它也在 build.gradle:shadowJar { mergeServiceFiles() } 中显式调用
        【解决方案5】:

        问题实际上是 RestEasy 无法找到 Jackson 提供程序。我必须通过以下代码手动注册它:

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

        一切正常。但是我仍然对解决方案不满意,因为 Resteasy 应该扫描提供程序并自动注册它们。

        【讨论】:

        • 我将 resteasy、jaxrs、resteasy-spring、jackson 库更新到最新版本并让它们无缝运行
        • 您也可以从 components.xml 以声明方式注册提供者:
        • RESTeasy 会自行进行一些动态类加载,这会在 OSGi 上下文中造成麻烦,其中 OSGi 类加载器可能找不到所需的类。在这种情况下,手动添加所需的类是有意义的。
        【解决方案6】:

        您可以尝试将以下依赖项添加到您的 maven pom。

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

        【讨论】:

        • 谢谢!这对我也有帮助。
        • 请注意,resteasy-jackson-provider seems deprecated 和 resteasy-jackson2-provider 是新的工件。
        【解决方案7】:

        如果您真的想绕过 JAX-RS 的优点,实际上为您进行序列化(而不是手动调用 GSON),请使用 StreamingOutput(即将输出器包装为 StreamingOutput,返回该对象)。

        【讨论】:

          【解决方案8】:

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

          或者您也可以让 JAX-RS 为您完成这项工作:而不是执行 gson.toJSON(object),只需返回 object 并将您的方法签名更改为任何类即可。 JAX-RS(在您的情况下为 RESTEasy)将自动调用 Jackson(如果配置正确)并将您的对象序列化为 json。然后在您的客户端,您将请求同一个类而不是 String,并且一切都应该独立工作。我对 ClientRequest/Response 不是特别熟悉,所以它可能不会像我说的那样工作;我们在客户端使用 RESTEasy 代理功能(请参阅ProxyFactory)。不过,JAX-RS/RESTEasy 也可以在客户端自动进行 json 序列化/反序列化,所以肯定有办法。

          【讨论】:

          • 我通过显式注册 ResteasyJacksonProvider 让它工作。 RestEasy 应该自己做这件事,但我不知道为什么它不注册提供者。我正在使用带有弹簧的 Resteasy。 ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance(); RegisterBuiltin.register(实例); instance.registerProvider(ResteasyJacksonProvider.class);
          猜你喜欢
          • 1970-01-01
          • 2017-02-13
          • 1970-01-01
          • 2018-01-06
          • 2016-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-27
          相关资源
          最近更新 更多