i'm trying to implement a small REST API using Jersey as framework, in principle the code worked fine but when I try to do a 'GET' of a hash table, I get the following error:
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
This is the problematic line:
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>>(){});
and this is how I implemented the service:
@GET
@Path("/getAllNews")
@Produces(MediaType.APPLICATION_JSON)
public Map<New, Term> getAllNews() {
return NewsCrawler.getNewAndTerm();
}
pom.xml (maven dependencies)
<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>
Server side configuration:
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...");
}
}
Error registering Jackson in the client:
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)
New Class:
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 + "]";
}
}
Term class:
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 + "]";
}
}
can someone help me please to return the map?
I see you have two different provider dependencies jersey-media-moxy
and jersey-media-json-jackson
. I've always had a problem with Maps
with MOXy. I guess they don't play well. Seems you will need to use an adapter to make it play nice, as seen here from Blaise Doughan.
That being said, I requested (in the comments above) to see your Server side configuration, as MOXy will auto configure itself, and take precedence over the jersey-media-json-jackson
. Why, I'm not sure, this is just what I've always experienced. So I'm curious how the Server side didn't fail even before the response came back to the client. Unless you confgiure the JacksonFeature
with the server application, in which you should have also configured it with the client. (This is only the case, because you also have MOXy dependency).
Anyway, if you don't want to go through the hassle creating adapters, as seen in the link above, just get rid of the jersey-media-moxy
dependency. jersey-media-json-jackson
will also auto configure it feature. You should just use one or the other.
As an aside:
@Path("/getAllNews")
. Path segments should be nouns, unless they are controller resources, which normally perform some action, other than normal CRUD operations (e.g. /register
). The HTTP method already consists of the verb to which each CRUD action should be performed.
Just some semantics to consider :-)
UPDATE
The problem is with the New
key. Jackson doesn't know how to deserialize this. Since you are willing wot switch the key and value type, just change have the toString
return the name
in the Term
class, and it should be ok.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With