Jersey restful webservices in java application tested with Postman plugin sending complex Objects
eclipse, java, jersey, json, web-services
Solution
Indeed, the problem is that Jersey does not know how to map the json to your object.
You can use Genson, when it is in your classpath JSON serialization/deserialization will automatically be enabled with Jersey.
Problem
I have created one java restful ws with jersey 1.8 library, it is one post operation of a Pojo called Loc and consumes JSON format. Here is the webservice: ``` import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.hibernate.Session; import org.hibernate.Transaction; import persistence.HibernateUtil; import entities.Loc; @Path("EnvironmentService") public class Environment { @POST @Path("/post/location") @Consumes(MediaType.APPLICATION_JSON) public Response createLocation(Loc location) { System.out.println("ENTROU NO LOCATION"); Session session = HibernateUtil.openNewSession(); Transaction tx = session.beginTransaction(); session.save(location); tx.commit(); session.close(); String result = "Location saved"; return Response.status(201).entity(result).build(); } ``` I want to send the webservice a Loc object: ``` /** * Loc is a hibernate enitity class which represents a raw data table for location entries.*/ @Entity @XmlRootElement public class Loc implements Serializable { private static final long serialVersionUID = 1184003645439013748L; @Id @GeneratedValue(strategy = GenerationType.TABLE) private long id; private double latitude; private double longitude; private long time; private double accuracy; private String provider; @Column(name = "yProcessed", nullable = false, columnDefinition = "int default '0'") private int yProcessed = 0; @Column(name = "zClass", nullable = false, columnDefinition = "double default 0.0") private double zClass = 0d; public long getId() { return id; } public void setId(long id) { this.id = id; } public double getLatitude() { return this.latitude; } public void setLatitude(double latitude) { this.latitude = latitude; } public double getLongitude() { return this.longitude; } public void setLongitude(double longitude) { this.longitude = longitude; } public long getTime() { return this.time; } public void setTime(long time) { this.time = time; } @Override public String toString() { return "latitude: " + latitude + " longitude: " + longitude + "time: " + time; } public double getAccuracy() { return accuracy; } public void setAccuracy(double accuracy) { this.accuracy = accuracy; } public int getyProcessed() { return yProcessed; } public void setyProcessed(int yProcessed) { this.yProcessed = yProcessed; } public double getzClass() { return zClass; } public void setzClass(double zClass) { this.zClass = zClass; } public String getProvider() { return provider; } public void setProvider(String provider) { this.provider = provider; } } ``` This is my web.xml file for jersey configuration the jar i am using is 1.8: ``` <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>RememberMeServer</display-name> <servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>webservices</param-value> </init-param> <init-param> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/rest/*</url-pattern> </servlet-mapping> </web-app> ``` And i am testing this webservice with the postman plugin in chrome. I give him the following url `http://localhost:8080/RememberMeServer/rest/EnvironmentService/post/location` which is correct. I pass him the following header: ``` Content-Type application/json ``` and select `raw` and `JSON` type format and send the following JSON code which was gathered using GSON from a Loc object: ``` {"provider":"network","latitude":39.1237894,"longitude":-9.2501239,"accuracy":34.5,"time":1400957412206} ``` In the Postman plugin i get that `415: UnsupportedMediaType` and in eclipse i get this jersey error: ``` Mai 25, 2014 12:49:42 PM com.sun.jersey.spi.container.ContainerRequest getEntity SEVERE: A message body reader for Java class entities.Loc, and Java type class entities.Loc, and MIME media type application/json was not found. The registered message body readers compatible with the MIME media type are: application/json -> com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App */* -> com.sun.jersey.core.impl.provider.entity.FormProvider com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider com.sun.jersey.core.impl.provider.entity.StringProvider com.sun.jersey.core.impl.provider.entity.ByteArrayProvider com.sun.jersey.core.impl.provider.entity.FileProvider com.sun.jersey.core.impl.provider.entity.InputStreamProvider com.sun.jersey.core.impl.provider.entity.DataSourceProvider com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General com.sun.jersey.core.impl.provider.entity.ReaderProvider com.sun.jersey.core.impl.provider.entity.DocumentProvider com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General com.sun.jersey.core.impl.provider.entity.EntityHolderReader com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General ``` Which is weird from what i understand the entities.Loc should be in here somewhere, but it is not. Some anotations in class Loc are for Hibernate Framework and dont concern the webservice. i think they dont interfere. i can't figure out how to pass this problem i want to test this webservice first and just after that i go to the client. Does anyone knows how to solve this problem? EDIT: here is the request preview in postman: ``` POST /RememberMeServer/rest/EnvironmentService/post/location HTTP/1.1 Host: localhost:8080 Content-Type: application/json Cache-Control: no-cache {"provider":"network","latitude":"39.1237894","longitude":"-9.2501239","accuracy":"34.5","time":"1400957412206"} ``` EDIT2 When i changed the type to text/plain and the parameter to a string it worked i think the problem is the mapping of the json string to Loc object any help? EDIT3: Now i changed the type to string in the post webservice and he receives the json pretty good but how can i do it with a Loc object instead of a string? EDIT4 By adding Genson has a user sugestion actually changed the error to internal server error here is the stacktrace: ``` Mai 28, 2014 2:12:26 PM com.sun.jersey.spi.container.ContainerResponse logException SEVERE: Mapped exception to response: 500 (Internal Server Error) javax.ws.rs.WebApplicationException: com.owlike.genson.JsonBindingException: Could not deserialize to type class java.lang.String at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:127) at com.sun.jersey.spi.container.ContainerRequest.getEntity(ContainerRequest.java:490) at com.sun.jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider$EntityInjectable.getValue(EntityParamDispatchProvider.java:123) at com.sun.jersey.server.impl.inject.InjectableValuesProvider.getInjectableValues(InjectableValuesProvider.java:86) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$EntityParamInInvoker.getParams(AbstractResourceMethodDispatchProvider.java:153) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:203) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:302) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108) at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147) at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1542) at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1473) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419) at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409) at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:540) at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:715) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caused by: com.owlike.genson.JsonBindingException: Could not deserialize to type class java.lang.String at com.owlike.genson.Genson.deserialize(Genson.java:442) at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:125) ... 38 more Caused by: com.owlike.genson.stream.JsonStreamException: Readen value can not be converted to String at com.owlike.genson.stream.JsonReader.valueAsString(JsonReader.java:193) at com.owlike.genson.convert.DefaultConverters$StringConverter.deserialize(DefaultConverters.java:282) at com.owlike.genson.convert.DefaultConverters$StringConverter.deserialize(DefaultConverters.java:269) at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:57) at com.owlike.genson.Genson.deserialize(Genson.java:440) ... 39 more ```