Consume application/json in REST services using Jersey in Osgi - json

I'm deploying some REST services in an Osgi bundle using Jersey. The services are notated like
#POST
#Path("/adduser")
#Consumes(MediaType.APPLICATION_XML+","+MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_XML)
public Message addUser(User user) {
...
}
The first problem I have is that the service doesn't accept both of the MIME types I put into the #Consumes notation but just the first one.
The second and worst is that receive the following exeception when I try to call to the services. I can #Consumes text/plain and I can #Produces application/xml for example but if I try to #Consumes an application/json or application/xml the server throw the exception.
The exception is throwed when I make the call with a wellformed json or xml using a REST client or an ajax call, if the service just receive text/plain or doesnt receive anything the response to the client is made correctly in xml so the serializer is working ok when I send POJO's but not receiving them.
javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.bind.Unmarshaller.unmarshal(Ljavax/xml/transform/Source;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/glassfish/jersey/message/internal/XmlRootElementJaxbProvider, and the class loader (instance of <bootloader>) for resolved class, javax/xml/bind/Unmarshaller, have different Class objects for the type ject; used in the signature
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:353)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.felix.http.base.internal.handler.ServletHandler.doHandle(ServletHandler.java:96)
at org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:79)
at org.apache.felix.http.base.internal.dispatch.ServletPipeline.handle(ServletPipeline.java:42)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:49)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at es.upm.cedint.gateway.api.corssupport.CORSFilter.doFilter(CORSFilter.java:164)
at es.upm.cedint.gateway.api.corssupport.CORSFilter.doFilter(CORSFilter.java:246)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at es.upm.cedint.gateway.api.security.SecurityFilter.doFilter(SecurityFilter.java:87)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at org.apache.felix.http.base.internal.dispatch.FilterPipeline.dispatch(FilterPipeline.java:48)
at org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:39)
at org.apache.felix.http.base.internal.DispatcherServlet.service(DispatcherServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: org.glassfish.jersey.server.ContainerException: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.bind.Unmarshaller.unmarshal(Ljavax/xml/transform/Source;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/glassfish/jersey/message/internal/XmlRootElementJaxbProvider, and the class loader (instance of <bootloader>) for resolved class, javax/xml/bind/Unmarshaller, have different Class objects for the type ject; used in the signature
at org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:230)
at org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:212)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:401)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:243)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
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:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:322)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:211)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:979)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:344)
... 36 more
Caused by: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.bind.Unmarshaller.unmarshal(Ljavax/xml/transform/Source;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, org/glassfish/jersey/message/internal/XmlRootElementJaxbProvider, and the class loader (instance of <bootloader>) for resolved class, javax/xml/bind/Unmarshaller, have different Class objects for the type ject; used in the signature
at org.glassfish.jersey.message.internal.XmlRootElementJaxbProvider.readFrom(XmlRootElementJaxbProvider.java:140)
at org.glassfish.jersey.message.internal.AbstractRootElementJaxbProvider.readFrom(AbstractRootElementJaxbProvider.java:122)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:181)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:72)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:252)
at org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.get(EntityParamValueFactoryProvider.java:96)
at org.glassfish.jersey.server.internal.inject.AbstractHttpContextValueFactory.provide(AbstractHttpContextValueFactory.java:66)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:94)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:353)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:343)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:237)
... 45 more
Anyone have any idea of what could be wrong?
PD:I have #XMLRootElement at the begining of the User class that I want to serialize and the server I use is Jetty.

For the first question, I do not think you should have one function with two different signatures. I mean if you want to accept json or XML those are two different functions although they look the same from the java point of view. In your case I would create these three functions:
#POST
#Path("/adduser")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Message addUserXML(User user) {
return addUserInternal(user);
}
#POST
#Path("/adduser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_XML)
public Message addUserJSon(User user) {
return addUserInternal(user);
}
private Message addUserInternal(User user) {
...
}
As the second question: One of the worst thing that happened with Java 6 (in my opinion) is that they moved JAXB and other technologies into the JRE classpath. I guess you have also JAXB in one of your bundles. Jersey and the bundle that contains the REST API wire to different packages. One of them wires to the bundle that contains JAXB while the other wires to the boot classpath (package coming from JDK)
You can have two solutions (at least)
First solution
You exclude the JAXB packages from the boot classpath by configuring your OSGi environment.
Second solution
The packages coming from JDK have the version 0.0.0_jdkversion. The JAXB package coming from the bundle has a nicer and higher version like 2.1.1. You can edit the MANIFEST.MF of Jersey and your bundle to point to that version of the package.

Related

Cannot Deserialize LifeRay Service Model Object from JSON that came from ElasticSearch, Default Constructor not Found

Using LifeRay portal and ElasticSearch, Serializing custom object composed from ServiceModel Objects, Serialisation goes fine:
public String toJSON(){
return JSONFactoryUtil.looseSerializeDeep(this);
}
I index this into ES which is also fine, it contains list of those objects as well as single object, no problem.
When I Deserialize this I get this Error:
10:10:53,972 ERROR [ExceptionHandlerBridgeImpl:78] jodd.json.JsonException: Default ctor not found for: eu.project.drives.platform.model.model.TainingProvider
For each parameter which is Object from Service Model.
Code (should be ok as well, example for one field):
JSONObject obj = JSONFactoryUtil.createJSONObject(h.getSourceAsString());
TainingProvider t = JSONFactoryUtil.looseDeserialize(obj.getString("provider"), TainingProvider.class);
I cannot simply induce the Default constructor since it is generated by service builder nor I can do the "TainingProviderImpl.class" since it is different project but the Impl class should be what is called through the "TainingProvider.class" and it includes the default constructor.
Thank you.
The provided type when doing a deserialize is an interface in your example, so the internal Parser (here Jodd) might not find an implementation class to use as a bean class.
I did not find a nice solution, but used the internal Jodd parser directly.
When you subclass jodd.json.JsonParser you can overwrite the protected method for instantiation.
#Override
protected Object newObjectInstance(Class targetType) {
if (targetType.isAssignableFrom(TainingProvider.class)) {
return TainingProviderLocalServiceUtil.createTainingProvider(0L);
}
return super.newObjectInstance(targetType);
}
Now you can use the parser directly via parser.parse(obj.getString("provider"), TainingProvider.class)
I am not sure if it possible to hook in this instantiation hints to Liferays JSONFactoryUtil, which would be nicer instead of having a direct dependency to the jodd Parser in your module.

Camel ignores custom Jackson ObjectMapper

I am trying to replace the standard Jackson as it is described here: http://camel.apache.org/json.html
I am using the following configuration
<bean name="myJsonObjectMapper" class="com.my.app.MyJsonObjectMapper" primary="true"/>
<camel:camelContext id="camel-client">
<camel:template id="camelTemplate"/>
<camel:dataFormats>
<camel:json id="json" library="Jackson" objectMapper="myJsonObjectMapper"/>
</camel:dataFormats>
</camel:camelContext>
MyJsonObjectMapper extends ObjectMapper. I can see it in Spring context, I can autowire and use it. I see that Camel context is started OK, I am using the Camel version 2.20 where this feature is enabled and fixed. However when I am trying to parse JSON I am getting the exceptions which will non-modified ObjectMapper generate.
When debugging I see that JacksonDataFormat is not initialized with customized ObjectMapper but rather creates a new one on doStart() method.
What am I missing on the Camel configuration?
UPD:
I am using that mapper in scope of Camel REST DSL routes in one of the following ways:
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/somepath")
.description("blah")
.post("/subpath/")
.type(MyRQ.class)
.outType(MyRS.class)
.route().id("under-test")
.bean(service)
.endRest();
or
restConfiguration().component("servlet");
rest("/somepath")
.description("blah")
.post("/subpath/")
.route().id("under-test")
.unmarshal().json(JsonLibrary.Jackson)
.bean(service)
.marshal().json(JsonLibrary.Jackson)
.endRest();
In both cases I am getting the marshaller error due to the usage of the default marshaller instead of custom one. The routes seem to be started in scpe of the correct context, the same I am configuring ObjectMapper for.

ConnectionFactory exception Camel testing JMS

I'm doing my first steps with Camel and currently working on writing a simple junit test using jms as a transport.
Here is a code I wrote:
public class FirstMockTest extends CamelTestSupport {
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("jms:topic:quote")
.to("mock:quote");
}
};
}
#Test
public void testMessageCount() throws InterruptedException {
MockEndpoint mockEndpoint = getMockEndpoint("mock:quote");
mockEndpoint.setExpectedMessageCount(1);
template.sendBody("jms:topic:quote", "Camel rocks");
mockEndpoint.assertIsSatisfied();
}
}
Because of missing connectionFactory I got the following exception:
org.apache.camel.FailedToCreateRouteException: Failed to create route route1: Route(route1)[[From[jms:topic:quote]] -> [To[mock:quote]]] because of connectionFactory must be specified
I'm able to fix it adding the following lines to my route:
ConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("vm://localhost?roker.persistent=false");
context.addComponent("jms", JmsComponent.jmsComponent(connectionFactory));
But I don't like I'm adding some components to my context inside the route. Also, If i want to have another route I will need to do it again.
Obviously, there should be another way to tell my test about connection factory.
Thank you in advance!
It's a good idea to define the JMS connection factory outside of your Camel context and, if possible, reuse it. How to do that depends on your component model / execution environment.
If you're using a Java SE version that supports CDI, that would be an obvious choice. You'd define your JMS connection factory as a named component once and inject it everywhere you need it. Have a look at http://camel.apache.org/cdi.html and for testing support at http://camel.apache.org/cdi-testing.html
If you're using Spring, define your connection factory as a spring bean and inject it wherever you need it.
If you're using Java EE on an application server, you'd usually define the JMS connection factory using the mechanisms of that app server. You'd then look up the JMS connection factory using JNDI.
If you're running in an OSGi container, you should define the JMS connection factory in its own bundle and export it as an OSGi service. In the bundle of your Camel context, import that OSGi servide and inject it into the Camel context.
In all above cases you should consider using a pooled JMS connection factory.
For CDI, Spring and OSGi, have a look at: http://activemq.apache.org/maven/5.14.5/apidocs/org/apache/activemq/jms/pool/PooledConnectionFactory.html
For Java EE the way how to set pooling parameters depends on your app server.
Note of caution: for Java SE CDI and Spring there should be only one Camel context per application (you can have many routes, though). So if the JMS connection factory is only used in that one Camel context, there is not much reuse. Despite that I still think it's preferable to define the JMS connection outside of the Camel context in a separate component. It's, well, cleaner.
Since you are writing a junit you can avoid creating a ConnectionFactory if you stub the jms endpoint. You can name the endpoint as stub:jms:topic:quote. Have a look at sample example at link https://github.com/camelinaction/camelinaction2/blob/master/chapter9/mock/src/test/java/camelinaction/FirstMockTest.java

MessageBodyWriter not found for media type=application/json when returning JSON in REST web service with Jersey

I am trying to create a very simple REST service using Jersey. Here is the service code
#Path("/UserService")
public class UserService {
#GET
#Path("/users")
#Produces(MediaType.APPLICATION_XML)
public List<User> getUsers() {
User user = new User(1, "Thomas", "Greene");
List<User> userList = new ArrayList<User>();
userList.add(user);
return userList;
}
}
When I run it through Postman, it returns me a XML response
Now, I want to get a JSON response back. So, I changed the mediatype to application/json:
#Path("/UserService")
public class UserService {
#GET
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
public List<User> getUsers(){
User user = new User(1, "Thomas", "Greene");
List<User> userList = new ArrayList<User>();
userList.add(user);
return userList;
}
}
It gives me the below error in Tomcat logs:
SEVERE: MessageBodyWriter not found for media type=application/json, type=class java.util.ArrayList, genericType=java.util.List.
Can someone please guide me how to get a JSON response back?
To use Jackson 2.x as your JSON provider you need to add jersey-media-json-jackson module to your pom.xml file:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.2</version>
</dependency>
And then register the JacksonFeature in your Application/ResourceConfig subclass.
For more details, have a look at Jersey documentation.
I am a bit upset about JAXB binding as well at the moment, therefore let me summarize my findings here - please correct me if I say something stupid:
Of course you have to have a library to do the JSON (de)serialization, in my case it is Moxy.
You have to tell JAXB which classes it should support. There are multiple ways to do that, the simplest seems to be to add a jaxb.properties file in the directory matching your classes and its sole content is the text javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory. With the directory I mean, if your classes are in the directory src/main/java and there the package com.pkg1.entities, add this file in src/main/resources and there as com/pkg1/entities/jaxb.properties.
By default JAXB works on POJOs. So you need to have a constructor without arguments, a get- and a set-method. Only then this field will be present in the JSON.
What I do often is to add a second constructor that gets the runtime object passed in and sets all fields to be exposed directly. Hence I do not need and do not want a set-method. Solution is to annotate the get method with #XmlElement.
Did I say you need an empty/default constructor? Took me once three hours to find out why class1 was working fine, class2 got the MessageBodyWriter error. I had forgotten the constructor. Grrrrr.
You get the same error (I believe) when the class is configured fine but one of its fields returns a type it cannot serialize.
I believe to have had one case where the class annotation #XmlRootElement caused that error. Not sure but I barely use that annotation at the moment.
In case you have a List as one of the elements to be turned into a Json array, JAXB will use the myAbstract class to do the serialization. Not very useful, you want the actual objects to be serialized. But how should JAXB know who implemented/extended this class? You have to tell with the annotation #XmlSeeAlso. So the MyAbstract class gets a class annotation #XmlSeeAlso({MyConcrete1.class, MyConcrete2.class}). At least Moxy does add then an additional type field telling the consumer which class it was. Makes total sense.
Although you can return userList the better option would be to return Response.ok().entity(userList).build(); Then you can return errors as well. Logically it is the same.
Watchout what kind of data types you use. String is fine, ArrayList as well, Hashtable not. Depends on the serializer you use as well.
I hope this helps others.
You need a json serializer on your class path to make this work.
Just add jackson and jersey will use this in the writer.
E.g. if you are using maven, add this to the pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.7.4</version>
</dependency>
Your xml was working so I assume that you have #XmlRootElement annotation in your User class.
The thing is, it knows how to convert it to xml with the annotation #XmlRootElement but it doesn't know how to convert it to JSON.
So for making it convert everything to JSON with the same annotation of xml(ie #XmlRootElement) we can add
jersey-media-moxy-<whatever version>.jar
or for maven users
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
Also it should have a no argument constructor
I tried a ton of these dependencies but none of them worked for my version of Jersey3. What I needed to do was turn the Arraylist into an actual array. I managed this with toArray() and it started serializing correctly!

Unable to find a MessageBodyReader of content-type application/json and type class java.lang.String

I am using RestEasy client with jackson providers and getting the above error
clientside code is:
ClientRequest request = new ClientRequest(url);
request.accept(MediaType.APPLICATION_JSON);
ClientResponse<String> response = request.get(String.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
BufferedReader br =
new BufferedReader(new InputStreamReader(new ByteArrayInputStream(response.getEntity().getBytes())));
response.getEntity() is throwing ClientResponseFailure exception with the error being
Unable to find a MessageBodyReader of content-type application/json and type class java.lang.String
My server side code is below:
#GET
#Path("/{itemId}")
#Produces(MediaType.APPLICATION_JSON)
public String item(#PathParam("itemId") String itemId) {
//custom code
return gson.toJSON(object);
}
You could try to add the following dependency to your maven pom.
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>2.3.4.Final</version>
</dependency>
The problem actually is that RestEasy is unable to find the Jackson provider. I had to manually register it by the following code:
ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
RegisterBuiltin.register(instance);
instance.registerProvider(ResteasyJacksonProvider.class);
Everything is working fine with this. But I am still unhappy with the solution as Resteasy is supposed to scan for the providers and register them automatically.
Client client = ClientBuilder.newBuilder().register(ResteasyJacksonProvider.class).build();
Just adding the line org.jboss.resteasy.plugins.providers.jackson.ResteasyJacksonProvider into META-INF/services/javax.ws.rs.ext.Providers file, solves the problem.
This file is included into resteasy-jackson-providers.jar but same file is also included into another jar, restasy-jaxrs.jar and for an executable jar file, that use both these jars, they are not merged !!
I had a similar problem and I realized that the problem was related with the version of resteasy-jackson-provider. I just moved from 3.0.4.Final to 3.0.5.Final and the problem disappeared.
Additionally I also realized that if I change the third line to the following the result was the expected with no need to change the dependencies.
Response response = request.get(Object.class).toString();
Things that had made work my code were that I added:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson2-provider</artifactId>
<version>&{resteasy.version}</version>
</dependency>
Beside this I don't know why but it seems that resteasy not initializing providers when client were created, this means that it required to init them manually:
ResteasyProviderFactory instance=ResteasyProviderFactory.getInstance();
RegisterBuiltin.register(instance);
instance.registerProvider(ResteasyJackson2Provider.class);
In general it's enough to run the client.
I don't know the full rationale behind that but we've hit the exact same problem (multiple times :P) and you need to change the MediaType to TEXT_PLAIN.
Or you can also let JAX-RS do the job for you: instead of doing gson.toJSON(object), simply return object and change your method signature to whatever class that is. JAX-RS (RESTEasy in your case) will automatically call Jackson (if it's properly configured) and serialize your object to json. Then on your client side you would request for that same class instead of String and everything should work on its own. I'm not particularly familiar with ClientRequest/Response so it might not work as I said; we use RESTEasy proxy functionality on the client side instead (see ProxyFactory). Nevertheless, JAX-RS/RESTEasy can do json serialize/deserialize automatically on the client side too so there's definetly a way.
If you really want to by-pass goodness of JAX-RS actually doing serialization for you (instead of manually calling GSON), use StreamingOutput (i.e. wrap outputter as StreamingOutput, return that object).