找不到媒体类型= application / json的MessageBodyReader

时间:2014-05-03 09:14:34

标签: java json jersey jax-rs

我写了一个JAX-RS服务器,客户端都使用Jersey。我想将我的实体集合发送给客户端,我做了这个步骤:

  1. Made实体扩展Serializable
  2. 写了一个自定义提供程序并将其扩展为支持集合
  3. 将实体和提供商复制粘贴到客户端
  4. 我发出请求,它在服务器端成功处理,客户端收到错误:

    org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.List, genericType=java.util.List<model.HotelsEntity>.
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:225)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:149)
    org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
    org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853)
    org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:812)
    org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:377)
    org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:813)
    org.glassfish.jersey.client.JerseyInvocation.access$600(JerseyInvocation.java:90)
    org.glassfish.jersey.client.JerseyInvocation$3.call(JerseyInvocation.java:693)
    org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
    org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:689)
    org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:405)
    org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:301)
    service.HotelService.getHotels(HotelService.java:30)
    actions.HotelAction.perform(HotelAction.java:42)
    MainServlet.processResponse(MainServlet.java:33)
    MainServlet.doPost(MainServlet.java:22)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    

    服务器:

        @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getHotelsList(@QueryParam("startDate") String startDate,
                                  @QueryParam("endDate") String endDate) {
        List<HotelsEntity> list = hotelService.getAll();
        return ResponseFactory.response(Response.Status.OK, list);
    }
    

    客户端:

        GenericType<List<HotelsEntity>> genericType = new GenericType<List<HotelsEntity>>(){};
        WebTarget target = client.target(preparePath());
        List<HotelsEntity> hotels = target.request(MediaType.APPLICATION_JSON_TYPE).get(genericType);
    

    提供者:

    public class JsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> {
    
    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return MediaType.APPLICATION_JSON.equals(mediaType.getType()) &&
                MediaType.APPLICATION_JSON.equals(mediaType.getSubtype());
    }
    
    @Override
    public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
        Gson gson = createGson();
        Reader reader = new InputStreamReader(entityStream, Charset.forName(Constants.UTF_8));
        return gson.fromJson(reader, genericType);
    }
    
    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return MediaType.APPLICATION_JSON.equals(mediaType.getType()) &&
                MediaType.APPLICATION_JSON.equals(mediaType.getSubtype());
    }
    
    @Override
    public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return -1;
    }
    
    @Override
    public void writeTo(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
        Gson gson = createGson();
        JsonElement element = gson.toJsonTree(entityStream);
        Writer writer = null;
        try {
            writer = new OutputStreamWriter(entityStream, Charset.forName(Constants.UTF_8));
            gson.toJson(element, writer);
        } finally {
            if (writer != null) {
                writer.flush();
            }
        }
    }
    
    private Gson createGson() {
        return new GsonBuilder().setPrettyPrinting().create();
    }
    

    }

    @Provider
    public class JsonCollection extends JsonProvider<Collection<? extends HospitalityEntity>> {}
    
    @Entity
    @Table(name = "hotels", schema = "", catalog = "mydb")
    public class HotelsEntity implements HospitalityEntity{
    private int idHotel;
    private String name;
    private String region;
    private String description;
    
    @Id
    @Column(name = "id_hotel")
    public int getIdHotel() {
        return idHotel;
    }
    
    public void setIdHotel(int idHotel) {
        this.idHotel = idHotel;
    }
    
    @Basic
    @Column(name = "name")
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Basic
    @Column(name = "region")
    public String getRegion() {
        return region;
    }
    
    public void setRegion(String region) {
        this.region = region;
    }
    
    @Basic
    @Column(name = "description")
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
    
        HotelsEntity that = (HotelsEntity) o;
    
        if (idHotel != that.idHotel) return false;
        if (description != null ? !description.equals(that.description) : that.description != null) return false;
        if (name != null ? !name.equals(that.name) : that.name != null) return false;
        if (region != null ? !region.equals(that.region) : that.region != null) return false;
    
        return true;
    }
    
    @Override
    public int hashCode() {
        int result = idHotel;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (region != null ? region.hashCode() : 0);
        result = 31 * result + (description != null ? description.hashCode() : 0);
        return result;
    }
    }
    

8 个答案:

答案 0 :(得分:33)

你可以使用泽西json库:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.22</version>
</dependency>

或者genson:

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

答案 1 :(得分:22)

很抱歉重新发布这篇文章,但我遇到了Maven项目的这个问题,发现我需要在我的pom中包含jackson-jaxrs-json-provider的依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.4.1</version>
</dependency>

MVN存储库:http://mvnrepository.com/artifact/com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider

答案 2 :(得分:11)

您的实体类没有空构造函数,这是JAX-RS解组所需的。

看看这里:

https://blogs.oracle.com/groundside/entry/jax_rs_2_0_messagebodyreader

答案 3 :(得分:7)

检查您是否正在注册媒体类型以获取JSON支持。你的班级路径上有 jersey-media-moxy 吗?如果没有,请将此依赖项添加到您的pom.xml,请检查您的球衣版本,在此示例中我使用的是Jersey 2(2.24)

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>2.24</version>
    </dependency>

答案 4 :(得分:2)

对于Gradle,添加以下依赖项:

compile group: 'org.glassfish.jersey.media',
name         : 'jersey-media-moxy',
version      : '2.24.1'

答案 5 :(得分:0)

jersey-media-moxy还会因类似愚蠢的错误而抛出同样的异常,例如在您确实需要@XmlAttribute的地方使用@XmlElement注释。在我的情况下就是这种情况,这是值得研究的问题,尤其是当问题仅在某些类中发生而另一些类工作正常时。

答案 6 :(得分:0)

添加此依赖性已解决了我的错误,而其他建议的答案却没有:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-jaxb</artifactId>
    <version>${jersey2.version}</version>
</dependency>

答案 7 :(得分:0)

是否可能具有以下依赖性:

jersey-common-2.25.1.jar
jersey-media-json-jackson-2.25.1.jar

...?

我在执行客户端剩余调用的丰富Java应用程序中拥有该功能。当我为此客户端组装可执行jar时,所有依赖项都将解压缩到一个jar文件中。原来,这两个文件都有一个文件org.glassfish.jersey.internal.spi.AutoDiscoverable ...具有不同的内容!

一切在我的IDE中都可以正常运行,一旦将其组装在一个罐子中,所需的内容就会被另一个罐子覆盖。

原来的解决方案是,如何声明依赖项中的顺序以及一些排除项。我将此放在列表的前面:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.25.1</version>
        <exclusions>
            <exclusion>
                <groupId>org.glassfish.jersey.core</groupId>
                <artifactId>jersey-common</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-annotations</artifactId>
            </exclusion>
        </exclusions>
</dependency>

后来我放了:

 <dependency>   
      <groupId>org.glassfish.jersey.core</groupId>
      <artifactId>jersey-common</artifactId>
      <version>2.25.1</version>
 </dependency>

我还从其他依赖项中排除了jersey-common的任何其他依赖项。 最好的祝福 弗雷德里克