【问题标题】:A message body writer for Java type, class myPackage.B, and MIME media type, application/octet-stream, was not found找不到 Java 类型 myPackage.B 类和 MIME 媒体类型 application/octet-stream 的消息正文编写器
【发布时间】:2011-12-11 13:51:24
【问题描述】:

我是 RESTful webservices 的新手,正试图从独立的客户端应用程序更新我的 @OneToMany 关系,但我无法做到这一点。我正在使用 Glassfish 3.1.1 附带的 JAX-RS 的 Jersey 实现。

我有一个类A,它与类B@OneToMany 关系。

MyRestClient 是我的独立客户端,它正在调用已部署在 Glassfish 3.1.1 上的 RESTful Web 服务。

MyRestClient.java

public class MyRestClient {
    public static void main(String[] args) {    
        Client client = Client.create();        
        WebResource resource = client.resource("http://localhost:8080/myapp/rest/a/update/123");    
        B b1 = new B("debris");     
        ClientResponse response = resource.put(ClientResponse.class, b1);
        System.out.println(response.getEntity(A.class).getTitle() + " has " + response.getEntity(A.class).getBList().size() + " Bs.");
    }
}

AResource 是一个 EJB 会话 bean,我将其用作 RESTful Web 服务。

AResource.java

@Stateless
@Path("/a")
public class AResource {

    @EJB
    private AManager aManager;

    @PUT
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    @Path("/update/{id}")
    public Response updateA(B b, @PathParam("id") int id) {
        A a = aManager.findAById(id);
        a.addB(b);
        return Response.status(Status.OK).entity(a).build();
    }
}

当我运行客户端时,我收到以下错误消息: com.sun.jersey.api.client.ClientHandlerException:找不到 Java 类型 myPackage.B 类和 MIME 媒体类型 application/octet-stream 的消息正文编写器

以下是我的独立客户端应用程序中的域对象,它正在调用 AResource EJB 会话 bean,我将其用作 RESTful Web 服务。

A.java

@XmlRootElement
public class A implements Serializable{ 

    private List<B> bList = new ArrayList<B>();
    public List<B> getBList() {
        return bList;
    }
    //remaining code

}

B.java

public class B implements Serializable {

    private String text;
    private A a;    


    @XmlTransient
    public A getA() {
        return a;
    }

    public void afterUnmarshal(Unmarshaller u, Object parent) {
        this.a = (A) parent;
    }
    //remaining code

}

有人能帮我理解为什么会发生这种情况以及我应该如何解决这个问题吗?

【问题讨论】:

    标签: web-services rest jersey java-ee-6 jax-rs


    【解决方案1】:

    在您的客户端代码中,您没有指定要发送的数据的内容类型 - 因此 Jersey 无法找到正确的 MessageBodyWritter 来序列化 b1 对象。

    修改你的main方法的最后一行如下:

    ClientResponse response = resource.type(MediaType.APPLICATION_XML).put(ClientResponse.class, b1);
    

    并在服务器端和客户端向 B 类添加 @XmlRootElement 注解。

    【讨论】:

    • 我做了建议的更改,但它仍然给我同样的错误。
    • 哦,你在 B 类上缺少 @XmlRootElement 注释 - 也添加它。
    • 这可能是由于服务器上的错误。尝试将响应实体读取为字符串(而不是 A)并将其打印出来以查看从服务器返回的内容。还要检查服务器日志是否有异常。
    • 这是因为泽西岛一旦读取就不会缓存实体。 getEntity() 读取响应流并将其传递给消息正文阅读器进行处理,一旦处理,它会关闭流并返回它 - 对 getEntity() 的后续调用将失败,导致流已被读取并且它不能去回来再读一遍。
    • 我同意这并不明显,应该记录在案 - 我提交了一个错误:java.net/jira/browse/JERSEY-795
    【解决方案2】:

    在您的 POM.xml 中包含此依赖项并运行 Maven -> 更新

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>1.18.1</version>
    </dependency>
    <dependency>
       <groupId>com.owlike</groupId>
       <artifactId>genson</artifactId>
       <version>0.99</version>
    </dependency>
    

    【讨论】:

    • 这是节省时间的好方法,因为 Jersey API 允许您转换从 Web 服务对象接收到的字符串
    【解决方案3】:

    您需要从 B.class 中指定 @Provider@Produces(MediaType.APPLICATION_XML)
    将您的 MessageBodyWriter&lt;B.class&gt; 的包添加到您的 /WEB_INF/web.xml 为:

    <init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>
    your.providers.package
    </param-value>
    </init-param>
    

    【讨论】:

    • 我无法尝试@Provider,因为我目前无法访问该代码。会让你知道。谢谢。
    【解决方案4】:

    你必须做两件事来消除这个错误。

    1. 模型中的@xmlElement 映射
    2. 客户端:

      response = resource.type(MediaType.APPLICATION_XML).put(ClientResponse.class, b1); //consume

      response = resource.accept(MediaType.APPLICATION_XML).put(ClientResponse.class, b1); //produce

    【讨论】:

    【解决方案5】:

    添加参考:

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>${jersey1.version}</version>
    </dependency>
    

    只要在创建客户端时添加 clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true); 就可以解决我的问题:

    ClientConfig clientConfig = new DefaultClientConfig();
    clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
    Client client = Client.create(clientConfig);
    

    【讨论】:

      【解决方案6】:

      如果您最近升级了 Ant,也会发生这种情况。我在一个项目上使用Ant 1.8.4,将Ant升级到1.9.4,在使用Ant构建fat jar时开始出现这个错误。

      对我来说,解决方案是将命令行和 Eclipse using the process detailed here 降级回 Ant 1.8.4@

      【讨论】:

        【解决方案7】:

        我在get方法中遇到了同样的问题我为@get方法返回了一个“int”奇怪的是,当我将返回类型更改为String时,错误消失了。试一试,如果有人知道背后的逻辑它请分享它

        【讨论】:

        • 我认为将返回类型更改为 String 是不可接受的解决方案
        【解决方案8】:

        这解决了我的问题。

        http://www.markhneedham.com/blog/2012/11/28/jersey-com-sun-jersey-api-client-clienthandlerexception-a-message-body-reader-for-java-class-and-mime-media-type-applicationjson-was-not-found/

        在您的 POM.xml 中包含以下依赖项并运行 Maven -> 更新也解决了我的问题。

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.19.1</version>
        </dependency>
        <dependency>
           <groupId>com.owlike</groupId>
           <artifactId>genson</artifactId>
           <version>0.99</version>
        </dependency>
        

        【讨论】:

          【解决方案9】:

          如果您缺少实体的空公共构造函数(可能是 JSON、XML 等),也会发生这种情况..

          【讨论】:

            【解决方案10】:

            确保所有这些库都在您的类路径中:

            compile(group: 'com.sun.jersey', name: 'jersey-core',        version: '1.19.4') 
            compile(group: 'com.sun.jersey', name: 'jersey-server',      version: '1.19.4') 
            compile(group: 'com.sun.jersey', name: 'jersey-servlet',     version: '1.19.4')
            compile(group: 'com.sun.jersey', name: 'jersey-json',        version: '1.19.4')
            compile(group: 'com.sun.jersey', name: 'jersey-client',      version: '1.19.4')
            compile(group: 'javax.ws.rs', name: 'jsr311-api', version: '1.1.1')
            compile(group: 'org.codehaus.jackson', name: 'jackson-core-asl', version: '1.9.2')
            compile(group: 'org.codehaus.jackson', name: 'jackson-mapper-asl', version: '1.9.2')
            compile(group: 'org.codehaus.jackson', name: 'jackson-core-asl',   version: '1.9.2')
            compile(group: 'org.codehaus.jackson', name: 'jackson-jaxrs',      version: '1.9.2')
            compile(group: 'org.codehaus.jackson', name: 'jackson-xc',         version: '1.9.2')
            

            将“Pojo Mapping”和“Jackson Provider”添加到 jersey 客户端配置中:

            ClientConfig clientConfig = new DefaultClientConfig();
            clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
            clientConfig.getClasses().add(JacksonJsonProvider.class);
            

            这解决了我!

            ClientResponse response = null;
            
            response = webResource
                    .type(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON)
                    .get(ClientResponse.class);
            
            
            if (response.getStatus() == Response.Status.OK.getStatusCode()) {
            
                MyClass myclass = response.getEntity(MyClass.class);
                System.out.println(myclass);
            }
            

            【讨论】:

              猜你喜欢
              • 2018-01-26
              • 2018-04-20
              • 2012-08-16
              • 2016-10-01
              • 2013-12-05
              • 2014-03-20
              • 2013-03-15
              • 2013-12-15
              • 2012-01-28
              相关资源
              最近更新 更多