【问题标题】:Jersey Exception : SEVERE: A message body reader for Java class泽西岛异常:严重:Java 类的消息正文阅读器
【发布时间】:2012-01-25 13:16:54
【问题描述】:

我有一个基于 Jersey 的 Rest WS,它输出 JSON。我正在实现一个 Jersey 客户端来调用 WS 并使用 JSON 响应。我的客户端代码如下

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

第二行正确输出 JSON 字符串响应,但是将 JSON 编组到 POJO 的第三行没有发生,我得到以下异常堆栈跟踪

严重:Java 类 [Lorg.shoppingsite.model.entity.jpa.User; 和 Java 类型类 [Lorg.shoppingsite.model.entity.jpa.User; 和 MIME 媒体类型 application/json 的消息正文阅读器没有成立 2011 年 12 月 21 日上午 11:32:01 com.sun.jersey.api.client.ClientResponse getEntity SEVERE:与 MIME 媒体类型兼容的注册消息正文阅读器是: */* -> 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

我的请求中有正确​​的 MIME 类型。我的 POJO 已经用 XMLRootElement 进行了注释。我错过了什么。

谢谢

【问题讨论】:

  • 仅供参考...在我的情况下,代码在 IntelliJ 中运行良好,但在打包和部署时失败。我使用带有 jar-with-dependencies 选项的maven-assembly-plugin。我将改用 Jackson ObjectMapper,这是一种解决方法。
  • @PatS 我面临着类似的问题。代码在使用 Intellij 运行时运行良好,但在打包时抛出相同的错误。与您不同,我无权使用 Jackson ObjectMapper,因为问题在于依赖关系。您找到解决问题的替代方案了吗?
  • @Ajay。我标记的解决方案对我有用。我的猜测是,在您的 IntelliJ 中,您有一些需要的 jar 文件或者是“正确的版本”,并且它是在另一个文件中挑选出来的。这类问题很困难。我建议尝试使用 Shade 插件(请参阅 maven.apache.org/plugins/maven-shade-plugin)并启用调试以查看哪些类是重复的。在 IntelliJ 之外运行时,代码很可能引入了错误版本的文件。

标签: java json rest jersey


【解决方案1】:

Q) 代码在 Intellj 中运行良好,但在命令行中失败。

Sol) 将 jersey 的依赖项添加为直接依赖项而不是临时依赖项。

推理:因为它在 IntelliJ 上运行良好,所以依赖项配置正确。

  1. 通过以下方式之一获取所需的依赖项:

    1. 检查 IntelliJ 运行命令。 Stackoverflow-link
    2. 列出来自 maven mvn dependency:tree 的依赖项
  2. 现在,明确添加那些有问题的球衣依赖项。

【讨论】:

    【解决方案2】:

    对于 Python 和 Swagger 示例:

    import requests
    base_url = 'https://petstore.swagger.io/v2'
    def store_order(uid):
        api_url = f"{base_url}/store/order"
        api_data = {
            'id':uid,
            "petId": 0,
            "quantity": 0,
            "shipDate": "2020-04-08T07:56:05.832Z",
            "status": "placed",
            "complete": "true"
            }
        # is a kind of magic..
        r = requests.post(api_url, json=api_data)
        return r
    print(store_order(0).content)    
    

    最重要的 MIME 类型字符串: r = requests.post(api_url, json=api_data)

    【讨论】:

      【解决方案3】:

      如果您正在构建 uberjar 或“shaded jar”,请确保您的 meta inf 服务文件已合并。 (这在 dropwizard 项目中多次咬我。)

      如果您使用的是 gradle shadowJar 插件,您想在您的shadowJar 目标中调用mergeServiceFiles()https://github.com/johnrengelman/shadow#merging-service-files

      不确定 maven 或其他构建系统的类似命令是什么。

      【讨论】:

      • 为 Maven 添加一个转换器:ServicesResourceTransformer。这实际上让我通过了这个发布的错误消息。但是,它没有抱怨,而是我的 .getEntity() 调用挂起。关于 json 的一些事情,因为如果我要求一个 String 实体,它不会挂起。
      • 谢谢,使用ServicesResourceTransformer 为我解决了这个问题com.sun.jersey.api.client.ClientHandlerException: A message body reader for Java class org.x.y , and Java type class org.x.y and MIME media type application/xml; charset=UTF-8 was not found(注意我的没有抱怨json,但可能仍然适用)(在我的项目中添加更多依赖项后出现问题)
      【解决方案4】:

      我能够通过为 jersey-json 添加 maven 依赖项来解决此问题。

      【讨论】:

      • 这是正确的,有关添加 maven 依赖项的更详细步骤,请参阅this answer below
      • 对于 IntelliJ,在项目结构中添加来自 maven 的 jersey-json 是不够的。将条目添加到 pom.xml 解决了它。
      • 我面临同样的问题,我也有 sdded jersey-json。但它不能解决问题。
      • 这太糟糕了,@AmitGupta。你做了什么?
      • 这个问题是因为出现错误时的 HTML 响应。
      【解决方案5】:

      我知道这篇文章很旧,你很久以前就知道了,但只是为了拯救那些会在一段时间内阅读这篇文章的人。

      您可能忘记为要传递到端点的实体添加注释,因此 Jersey 不知道如何处理它接收到的 POJO。 用这样的东西注释 pojo:

      @XmlRootElement(name = "someName")
      

      【讨论】:

      • 即使在将 jersey-json 添加到 pom.xml 之后,这也是必需的。 +1
      【解决方案6】:

      尝试添加:

      <dependency>
          <groupId>com.owlike</groupId>
          <artifactId>genson</artifactId>
          <version>1.4</version>
      </dependency>
      

      如果您使用带有消息正文的HTTP GET,也可能会出现此问题,因此在这种情况下添加 jersey-json lib、@XmlRootElement 或修改 web.xml 将无济于事。您应该使用 URL QueryParamHTTP POST

      【讨论】:

        【解决方案7】:

        只需在课程开始前在您的 POJO 中添加以下行,您的问题就解决了。 @Produces("应用程序/json") @XmlRootElement 查看示例 导入 javax.ws.rs.Produces; 导入 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!!!
        

        【讨论】:

        • xmlrootelement 与发送 JSON 对象有什么关系?
        【解决方案8】:

        我们还决定使用球衣作为解决方案。但是由于我们在大多数情况下都使用 org.JSON,所以这种依赖是不必要的,我们感觉不好。

        因此我们使用 String 表示来获取 org.JSON 对象,而不是

        JSONObject output = response.getEntity(JSONObject.class); 
        

        我们现在这样使用它:

        JSONObject output = new JSONObject(response.getEntity(String.class)); 
        

        其中 JSONObject 来自 org.JSON 并且可以从以下位置更改导入:

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

        【讨论】:

          【解决方案9】:

          有些人可能会疑惑为什么添加 jersey-json jar 不能解决这个问题。我发现这个 jar 必须比 jersey-json-1.7.jar 更新(1.7.0 不起作用,但 1.7.1 可以正常工作。)。希望这可以帮助

          【讨论】:

          • 这是对问题的评论或尝试回答;有空的时候请把它放在那里。
          【解决方案10】:

          我的情况类似。我在关键时刻遇到了这个错误,我不记得我以前是如何解决它的,我做了很多次。经过数小时的艰苦检查,我已经解决并重现了错误,并确保解决这种情况的方法有多简单。

          好的 - 解决方案:删除(或更正)对主项目的属性文件所做的任何新更改。

          是的,就是这样。事实上,我的项目是一个多模块的大型项目,你知道没有正确的依赖关系是一种罕见的情况,因为它经常从 git(RAC 也是)中获取。我的项目从一个属性文件中获取几乎所有可配置的东西,该文件对于大约 15 个左右的模块(子项目)来说是通用的,它们之间有大量的内部依赖关系。 jersey-json 的依赖项始终存在于我合并的父 pom 中。 XML 注释不是问题,因为项目在修改它们后运行了大约 100 次。这里的一些解决方案指向 web.xml 和 POJOMappingFeature 之类的东西。在我的例子中,我什至没有在这个版本中接触过 webapp 模块。所以无论如何,这个解决方案对我有用,我花时间在 SO 中记录它,以防万一我碰巧陷入这个错误,我不必浪费我的困倦之夜。 (当然,你也一样)

          【讨论】:

            【解决方案11】:

            要让它工作,你只需要两件事。检查您是否丢失:

            1. 首先,您需要为您的对象类/实体添加 @XmlRootElement 注释。
            2. 如果您丢失,您需要为 jersey-json 添加依赖项。供您参考,我将此依赖项添加到我的 pom.xml 中。

              <dependency>
                  <groupId>com.sun.jersey</groupId>
                  <artifactId>jersey-json</artifactId>
                  <version>1.17.1</version>
              </dependency>
              

            【讨论】:

            • 在我的情况下,只需添加 jersey-json 依赖项就足够了。
            • 干得好!我们一直在追逐这个罐子......谢谢!
            • JSON 对象需要 @XmlBlahBlah 似乎很奇怪,对我没有帮助。
            • 我必须同时添加注释和 maven 依赖项
            • 您可能还需要使用 maven shade 插件来合并 META-INF/services/javax.ws.rs.ext.MessageBodyWriter 和 META-INF/services/javax.ws.rs.ext.MessageBodyReader jersey-core 和 jersey-json 库,请参考stackoverflow.com/a/13279921/1699468
            【解决方案12】:

            就我而言,我使用的是 POJO。而且我忘记将 POJOMappingFeature 配置为 true。 Maycon 在早期的回答中指出了这一点。但是有些人可能无法在 web.xml 中正确配置它,这是我的示例。

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

            【讨论】:

            • 或在代码中:clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
            【解决方案13】:

            只需检查您是否在 Eclipse 中运行不同的实例。我退出了所有其他会话,干净的构建解决了问题

            【讨论】:

              【解决方案14】:

              放这个

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

              【讨论】:

              【解决方案15】:

              您需要为您的班级Lorg.shoppingsite.model.entity.jpa.User 实现自己的MessageBodyReaderMessageBodyWriter

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

              【讨论】:

              • 我认为你的方法不是常用的方法。通常,将 JSON 映射到 POJO 可以使用 JAXB,而无需创建自己的 messageBodyReader,因为 JSON 的消息阅读器已经存在。见 VDev 的回答。
              猜你喜欢
              • 2016-04-03
              • 2011-12-08
              • 2012-06-04
              • 1970-01-01
              • 1970-01-01
              • 2015-10-06
              • 1970-01-01
              • 2011-02-13
              相关资源
              最近更新 更多