James Robinson James Robinson - 7 months ago 34
Java Question

JSON Jersey Auto serialization Wrapper Problems

I have a POJO

public class Graph {
public int v;
public int e;
}


and a very simple service

@Service("graph-service#default")
public class DefaultGraphService implements GraphService {
public Response createGraph(Graph graph) {
return Response.ok().build();
}
}


which implements a very simple interface

@Path( "graph-service" )
public interface GraphService {

@Path( "create-graph" )
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response createGraph(Graph graph);
}


I have a simple spring-context.xml set up as follows

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

<context:annotation-config/>
<context:component-scan base-package="me.jamesphiliprobinson.graphs"/>

<jaxrs:server id="testServices" address="/testServices">
<jaxrs:serviceBeans>
<ref bean="graph-service#default"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</beans>


If I spin the service up in tomcat it works fine can I can curl an object like

{"v":2,"e":1}


Without any difficulty. However, if I run this test

@Test
public void testCreateGraph() {
UncertaintyGraphService service =
JAXRSClientFactory.create( "http://localhost:" + port + "/" + getRestServicesPath() + "/testServices/",
GraphService.class );
Graph graph = new Graph();
graph.e = 1;
graph.v = 2;
Response result = service.createGraph(graph);
assertNotNull(result);
}


Then it fails as there is

No message body writer has been found for class : class me.jamesphiliprobinson.graphs.Graph, ContentType : application/json


If I add an

@XmlRootElement


to the POJO then the service serializes the graph object but seems to send

{"graph":{"e":1,"v",2}}


Instead which I can see making sense but the deserialization seems to still expect

{"e":1,"v":2}


As I get the error

WARNING: WebApplicationException has been caught : Unrecognized field "graph" (Class me.jamesphiliprobinson.graphs.Graph), not marked as ignorable


I'm surely missing something incredibly simple. I would prefer for the items to serialise to

{"v":2,"e":1}


But if they will deserialise correctly I can live with a root element. i.e.

{"graph":{"v":2,"e":1}}

Answer

See where you are registering the JacksonJsonProvider on the server?

<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />

This is to handle JSON (de)serizalization to/from POJO on the server side. But the client needs the same support. You can use the overloaded

to register the provider on the client side. Just add the JacksonJsonProvider to the List of providers.

JAXRSClientFactory.create(baseUri, Service.class, Arrays.asList(new JacksonJsonProvider())