Jersey错误:找不到适用于媒体类型“application/json”的MessageBodyReader

11

我正在尝试使用Jersey框架实现一个小型的REST API。原则上,代码工作正常,但当我尝试获取哈希表时,会出现以下错误:

nov 23, 2014 4:27:40 PM org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor aroundReadFrom
GRAVE: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<upf.dad.proyecto.New, upf.dad.proyecto.Term>.
1440 [DefaultQuartzScheduler_Worker-3] ERROR org.quartz.core.JobRunShell - Job DEFAULT.testJob3 threw an unhandled Exception: 
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<upf.dad.proyecto.New, upf.dad.proyecto.Term>.
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:230)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:810)
)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:313)
    at upf.dad.proyecto.HotTopicDetector.News(HotTopicDetector.java:110)
    at upf.dad.proyecto.ScheduledTestJob3.execute(ScheduledTestJob3.java:11)
1440 [DefaultQuartzScheduler_Worker-3] ERROR org.quartz.core.ErrorLogger - Job (DEFAULT.testJob3 threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<upf.dad.proyecto.New, upf.dad.proyecto.Term>.]
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<upf.dad.proyecto.New, upf.dad.proyecto.Term>.
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:230)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:810)
    at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:368)
    at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:846)
    at org.glassfish.jersey.client.JerseyInvocation.access$600(JerseyInvocation.java:91)
    at org.glassfish.jersey.client.JerseyInvocation$3.call(JerseyInvocation.java:705)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:701)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:417)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:313)
    at upf.dad.proyecto.HotTopicDetector.News(HotTopicDetector.java:110)
    at upf.dad.proyecto.ScheduledTestJob3.execute(ScheduledTestJob3.java:11)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    ... 1 more

这是有问题的那一行:
    Client client = ClientBuilder.newClient();

    WebTarget targetGetAllNews = client.target("http://localhost:15000").path("news/getAllNews");


    Map<New, Term> NewsAll = targetGetAllNews.request(
             MediaType.APPLICATION_JSON_TYPE).get(new GenericType<Map<New, Term>>(){});

这是我实现该服务的方法:

@GET
@Path("/getAllNews")
@Produces(MediaType.APPLICATION_JSON)
public Map<New, Term> getAllNews() {
    return NewsCrawler.getNewAndTerm();
}

pom.xml(Maven依赖项)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>upf.dad.proyecto</groupId>
<artifactId>JAXRS-proyecto</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- Rome RSS and Atom utilities @ http://rometools.github.io/rome/ -->        
<dependency>
        <groupId>rome</groupId>
        <artifactId>rome</artifactId>             
        <version>1.0</version>
</dependency>

<!-- jsoup HTML parser library @ http://jsoup.org/ -->         
<dependency>             
        <groupId>org.jsoup</groupId>             
        <artifactId>jsoup</artifactId>             
        <version>1.8.1</version>               
</dependency>
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.twitter4j</groupId>
        <artifactId>twitter4j-core</artifactId>
        <version>4.0.2</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.12</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-jdk-http</artifactId>
        <version>2.12</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>2.12</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>2.12</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.13</version>
    </dependency>
</dependencies>
</project>

服务器端配置:

public class NewsCrawlerRestServer {

public static void main(String[] args) throws IOException {

    URI baseUri = UriBuilder.fromUri("http://localhost/").port(15000).build();
    ResourceConfig config = new ResourceConfig(NewsCrawlerServices.class, HotTopicDetectorServices.class);
    config.register(JacksonFeature.class);
    HttpServer server = JdkHttpServerFactory.createHttpServer(baseUri, config);
    System.out.println("Server started...");

    }
}

在客户端注册Jackson时出现错误:

org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: javax.ws.rs.ProcessingException: Error reading entity from input stream.]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
    Caused by: javax.ws.rs.ProcessingException: Error reading entity from input stream.
        at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:866)
        at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:810)
        at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:368)
        at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:846)
        at org.glassfish.jersey.client.JerseyInvocation.access$600(JerseyInvocation.java:91)
        at org.glassfish.jersey.client.JerseyInvocation$3.call(JerseyInvocation.java:705)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
        at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:701)
        at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:417)
        at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:313)
        at upf.dad.proyecto.HotTopicDetector.News(HotTopicDetector.java:112)
        at upf.dad.proyecto.ScheduledTestJob3.execute(ScheduledTestJob3.java:11)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        ... 1 more
    Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class upf.dad.proyecto.New]
        at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:580)
        at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:170)
        at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:404)
        at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:232)
        at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:572)
        at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:386)
        at com.fasterxml.jackson.databind.ObjectReader._findRootDeserializer(ObjectReader.java:1380)
        at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1228)
        at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:677)
        at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:777)
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:264)
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:234)
        at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)
        at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
        at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)

新的类:

package upf.dad.proyecto;

import java.util.Date;

public class New {

private String tittle;
private String description;
private Date date;
private String link;

public New(){

}

public New(String t, String d, Date date, String l){
    this.tittle = t;
    this.description = d;
    this.date = date;
    this.link = l;
}

public String getTittle() {
    return tittle;
}

public void setTittle(String tittle) {
    this.tittle = tittle;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public Date getDate() {
    return date;
}

public void setDate(Date date) {
    this.date = date;
}

public String getLink() {
    return link;
}

public void setLink(String link) {
    this.link = link;
}

@Override
public String toString() {
    return "New [tittle=" + tittle + ", description=" + description
            + ", date=" + date + ", link=" + link + "]";
}


}

术语类:

package upf.dad.proyecto;

public class Term {

private String word;

public Term(){

}

public Term(String word){
    this.word = word;

}

public String getWord(){
    return word;
}

public void setWord(String _word){
    word = _word;
}

@Override
public String toString() {
    return "Termino =" + word + "]";
}
}

请问有人可以帮我返回地图吗?


我知道这是客户端的问题,但你能展示一下服务器应用程序的配置吗? - Paul Samsotha
1个回答

9
我看到你有两个不同的提供者依赖项jersey-media-moxyjersey-media-json-jackson。我一直对MOXy的Maps有问题。我猜它们不太兼容。看起来你需要使用一个适配器让它能够正常工作,可以参考这里的Blaise Doughan
话虽如此,在上面的评论中,我要求查看你的服务器端配置,因为MOXy会自动配置并优先于jersey-media-json-jackson。为什么会这样,我不确定,这只是我一直以来的经验。所以我很好奇在响应返回给客户端之前,服务器端怎么没有失败。除非你在服务器应用程序中配置了JacksonFeature,那么你也应该在客户端中进行配置。(这只是因为你还有MOXy依赖的情况下才成立)。
无论如何,如果您不想经历创建适配器的麻烦,就像上面链接中所示,只需摆脱jersey-media-moxy依赖项。 jersey-media-json-jackson也会自动配置该功能。您应该只使用一个或另一个。

顺便一提:

@Path("/getAllNews")。路径段应该是名词,除非它们是控制器资源,通常执行一些动作,而不仅仅是普通的 CRUD 操作(例如 /register)。HTTP 方法已经包含了应该执行的每个 CRUD 操作的动词。

  • Create - POST
  • Retriecve - GET
  • Update = PUT
  • Delete - DELETE

只是一些要考虑的语义问题 :-)


更新

问题出在 New 键上。Jackson 不知道如何反序列化它。既然你愿意切换键和值的类型,只需将 Term 类中的 toString 修改为返回 name,应该就可以了。


感谢您的回答,我已经更新了帖子并提供了所需的信息。正如您所看到的,为了返回地图,我使用Jackson作为JSON提供程序,将其添加到pom.xml文件中的依赖项中,并在启动HttpServer之前在ResourceConfig对象中注册它,但仍然无法工作... - Cheknov
请展示NewTerm类。我创建了自己的测试,它运行良好。 - Paul Samsotha
你可以看到所请求的类,谢谢。你能举个使用GenericEntity的例子吗? - Cheknov
你确定你想让New成为键,而不是反过来吗?Term只有一个字段,更容易表示为键。New有四个字段,这是一个笨拙的键。 - Paul Samsotha
我可以毫无问题地更改顺序,这样能解决问题吗? - Cheknov
显示剩余8条评论

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