小さなREST APIをフレームワークとしてJerseyを使用して実装しようとしていますが、原則としてコードは正常に機能しましたが、ハッシュテーブルの「GET」を実行しようとすると、次のエラーが発生します。 :
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 + "]";
}
}
誰かが地図を返してくれるのを手伝ってくれる?
プロバイダーの依存関係には_jersey-media-moxy
_と_jersey-media-json-jackson
_の2つがあります。私は常にMOXyでMaps
に問題がありました。彼らは上手くプレイしないと思います。ご覧のように、アダプターを使用してそれをニースで再生する必要があるようです Blaise Doughanから 。
そうは言っても、MOXyは自動構成し、_jersey-media-json-jackson
_よりも優先されるため、(上記のコメントで)サーバー側の構成を確認するように要求しました。なぜだかわかりませんが、これはいつも経験したことです。ですから、クライアントに応答が返される前にサーバー側が失敗しなかったのが気になります。 JacksonFeature
をサーバーアプリケーションで構成する場合を除き、クライアントでも構成する必要があります。 (MOXyの依存関係もあるため、これは唯一のケースです)。
とにかく、上のリンクにあるように、面倒なアダプターの作成をやりたくない場合は、_jersey-media-moxy
_依存関係を取り除くだけです。 _jersey-media-json-jackson
_も機能を自動構成します。どちらか一方を使用する必要があります。
余談ですが:
@Path("/getAllNews")
。パスセグメントは、通常のCRUD操作(_/register
_など)以外のアクションを通常実行するコントローラーリソースでない限り、名詞である必要があります。 HTTPメソッドはすでに、各CRUDアクションが実行される動詞で構成されています。
考慮すべきいくつかのセマンティクス:-)
[〜#〜]更新[〜#〜]
問題はNew
キーにあります。ジャクソンはこれを逆シリアル化する方法を知りません。キーと値のタイプを切り替えるつもりなので、toString
がname
クラスのTerm
を返すように変更すれば、問題ありません。