Jersey Error: MessageBodyReader not found for media type=application/json
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.
- Create - POST
- Retriecve - GET
- Update = PUT
- Delete - DELETE
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.
Cheknov
Updated on July 31, 2022Comments
-
Cheknov almost 2 years
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?
-
Cheknov over 9 yearsThanks for your answer, I updated the post with the required information. As you can see, to return the map I use the Jackson as JSON provider adding the dependency to the pom.xml file and registering it in the ResourceConfig object before starting the HttpServer but still not working...
-
Paul Samsotha over 9 yearsTry registering it with the client also, since the problem is on the client side (since the problem is with the client) i.e.
client.register(...)
. Since you have the MOXy still, the client may be implicitly registered with MOXy. -
Cheknov over 9 yearsthanks for the help, again, I updated the post with the error I get when I register the client...I have been considering also use the adapter, but I do not know how to implement it.
-
Paul Samsotha over 9 yearsplease show the
New
andTerm
class. I created my own to test and it worked fine. -
Cheknov over 9 yearsYou can see the classes requested, thanks. Could you give an example of how to use
GenericEntity
? -
Paul Samsotha over 9 yearsI see the problem. Keys in JSON are supposed to be Strings. If you want to use an object, 1) You need to create a custom serializer that will serialize and deserializer the object to a String 2) it'll look funky in JSON
-
Paul Samsotha over 9 yearsAre you sure you meant for the
New
to be the key, and not the other way around?Term
only has one field, which will be easier to represent as a key.New
has four fields, which is an awkward key -
Cheknov over 9 yearsI can change the order without any problem, that would solve the problem?
-
Paul Samsotha over 9 yearsNo you still need a serializer/deserializer, but it's pretty easy. I just suggested switching the order, because trying to represent 4 fields as a json key just looks weird. I'll put together something. Give me a few minutes
-
Paul Samsotha over 9 yearsSo it actually looks like just using the
Term
type for the key makes it work. But the actual text in the json is thetoString
So you can just have it return thename
. No need for any serializers -
Cheknov over 9 yearsSo, If I change the
toString
method to return only the name, will work? I get the same first error:GRAVE: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map
etc. by just changing thetoString
method like this:public String toString() {return word;}
-
Paul Samsotha over 9 yearsDid you register the client with the JacksonFeature. You should get rid of the MOXy dependency if you're not going to use it. The Jackson module should autoconfigure itself. But the MOXy will take precedence
-
Cheknov over 9 yearsYes, I closed Eclipse, I have reopened and no longer returns an error. Thank you very much!