2014-11-23 15 views
9

Próbuję zaimplementować mały interfejs API REST, wykorzystując system Jersey jako strukturę, w zasadzie kod zadziałał dobrze, ale gdy próbuję wykonać polecenie "GET" z hashem stół, pojawia się następujący błąd:Błąd sieci Jersey: MessageBodyReader nie został znaleziony dla typu nośnika = aplikacja/json

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 

jest to problematyczne linia:

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>>(){}); 

i to w jaki sposób realizowane usługi:

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

pom.xml (zależnościami Maven) Konfiguracja strona

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

Serwer:

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

    } 
} 

Błąd rejestracji Jacksona w kliencie:

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) 

Nowa Klasa:

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 + "]"; 
} 


} 

Klasa:

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 + "]"; 
} 
} 

Czy ktoś może mi pomóc, proszę, zwrócić mapę?

+0

Wiem, że to jest problem po stronie klienta, ale możesz pokazać konfigurację aplikacji serwera –

Odpowiedz

6

Widzę, że masz dwie różne zależności od dostawcy: jersey-media-moxy i jersey-media-json-jackson. Zawsze miałem problem z Maps z MOXy. Myślę, że nie grają dobrze. Wygląda na to, że będziesz musiał użyć adaptera, aby gra była przyjemna, jak widać here from Blaise Doughan.

W związku z powyższym, poprosiłem (w komentarzach powyżej), aby zobaczyć konfigurację po stronie serwera, ponieważ MOXy automatycznie skonfiguruje się i będzie mieć pierwszeństwo przed jersey-media-json-jackson. Dlaczego, nie jestem pewien, to jest to, czego zawsze doświadczyłem. Ciekaw jestem więc, w jaki sposób strona serwera nie zawiodła, zanim odpowiedź wróciła do klienta. Jeśli nie utożsamiasz się z JacksonFeature z aplikacją serwera, w której powinieneś również skonfigurować ją z klientem. (Jest tak tylko w przypadku, ponieważ masz również zależność od MOXy).

W każdym razie, jeśli nie chcesz przechodzić przez kłopotliwe adaptery tworzenia, jak widać w powyższym linku, po prostu pozbyć się zależności zależnej od jersey-media-moxy. jersey-media-json-jackson będzie także automatycznie konfigurować funkcję. Powinieneś po prostu użyć jednego lub drugiego.


Tak na marginesie:

@Path("/getAllNews"). Segmenty ścieżki powinny być rzeczownikami, chyba że są zasobami kontrolera, które zwykle wykonują pewne działanie, inne niż zwykłe operacje CRUD (na przykład /register). Metoda HTTP zawiera już czasownik, dla którego należy wykonać każdą akcję CRUD.

  • C Reate - słupek
  • R etriecve - GET
  • U pdate = PUT
  • ď suĹ - usunięcie

tylko niektóre semantyki do rozważenia :-)


UPDATE

Problem jest z kluczem New. Jackson nie wie, jak to zrobić z deserializacji. Ponieważ chcesz zmienić klucz i typ wartości, po prostu zmień, aby toString zwrócił name w klasie Term i powinno być w porządku.

+0

Dziękuję za odpowiedź, zaktualizowałem post z wymaganymi informacjami. Jak widać, aby zwrócić mapę, używam Jacksona jako dostawcy JSON, dodając zależność do pliku pom.xml i rejestrując go w obiekcie ResourceConfig przed uruchomieniem HttpServera, ale wciąż nie działa ... – Gera

+0

Spróbuj zarejestrować go u klienta także, ponieważ problem występuje po stronie klienta (ponieważ problem dotyczy klienta), czyli 'client.register (...)'. Ponieważ masz MOXy nadal, klient może być niejawnie zarejestrowany w MOXy. –

+0

dzięki za pomoc, ponownie, zaktualizowałem post z błędem, który dostaję, gdy rejestruję klienta ... Zastanawiam się również używać adaptera, ale nie wiem jak go wdrożyć. – Gera