For those who may be interested, see the attached files to
https://issues.apache.org/jira/browse/CAMEL-7147

(blueprint.xml, jaxrs-beans.xml), the route works nicely with CXF 2.7.7 with minor modifications, which won't be needed with the newer CXF versions

Sergey
On 22/01/14 22:13, David wrote:
I tried using org.apache.cxf.jaxrs.provider.json.JSONProvider as the JSON
provider instead of JacksonJsonProvider, and that results in an exception
being thrown, telling me that no message body reader was found for my
class. I'm using the same test case that's attached to the JIRA, just with
a different JSON provider, and adding @XmlRootElement(name="container") to
the domain class.



On Wed, Jan 22, 2014 at 5:23 AM, Sergey Beryozkin <sberyoz...@gmail.com>wrote:

Hi, sure, I only referenced Jettison as a possible alternative.
I think Jackson is picked up, Jettison only works, as you mentioned, with
JAXB sending the write events to it, and as I understand you've no
XMLRootElement/etc added to the data beans

Sergey

On 21/01/14 21:14, David wrote:

Comments in-line.


On Tue, Jan 21, 2014 at 12:34 PM, Sergey Beryozkin <sberyoz...@gmail.com
wrote:

  Hi
Please see comments below,

On 21/01/14 17:01, David wrote:

  I think this is more of a Camel question than a CXF question, but let me
know if that's not the case (would it have been bad form to cross-post
this
to cxf-user?).

I have questions regarding use of Jackson with CXF, as well as how to
get
CXFRS not to wrap the root value of a JSON payload.

I am trying to use Camel and CXF as part of a service orchestration
using
JSON over REST. My biggest question is how to configure cxfrs to use
Jackson for all JSON marshal/unmarshal operations.

So far, I've configured a cxf:rsServer and added a cxf:providers element
with a reference to a org.codehaus.jackson.jaxrs.JacksonJsonProvider
bean.
I've also added the following to my route, although I haven't found
anywhere to reference it yet:

       <dataFormats>
           <json library="Jackson" id="jack"/>
       </dataFormats>

I'm basically exposing the configured cxf:rsServer service as an
external
entry-point:

<cxf:rsServer id="processService" address="http://localhost:8182";
serviceClass="org.my.Service"
loggingFeatureEnabled="true">
<cxf:providers>
<ref component-id="jsonProvider" />
</cxf:providers>
</cxf:rsServer>
<bean id="jsonProvider"
class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />

I'm then using a couple cxfrs producer endpoints to invoke external
REST/JSON services implemented using RESTEasy:

           <setHeader headerName="CamelHttpMethod">
               <simple>POST</simple>
           </setHeader>
           <setHeader headerName="CamelHttpPath">
               <simple>/service1/operation1</simple>
           </setHeader>
           <setHeader headerName="Content-Type">
               <simple>application/json</simple>
           </setHeader>
           <to uri="cxfrs:http://localhost:8080?exchangePattern=InOut"/>
           <setHeader headerName="CamelHttpMethod">
               <simple>POST</simple>
           </setHeader>
           <setHeader headerName="CamelHttpPath">
               <simple>/service2/operation2</simple>
           </setHeader>
           <setHeader headerName="Content-Type">
               <simple>application/json</simple>
           </setHeader>
           <to uri="cxfrs:http://localhost:8080?exchangePattern=InOut"/>


The idea is that each of those services will modify the payload, and the
resulting object will be passed back to the caller.

The services themselves are pretty standard. Class annotated with @Path,
along with a single method annotated with @POST, @Consumes and @Produces
(both types are set to MediaType.APPLICATION_JSON). The methods expect
and
return a single container class with id and a couple string values.

When I call my service, however, an exception is thrown by the code
that's
attempting to call the cxfrs producer endpoint, saying there's no
message
body writer for my container class and applicaiton/json. At one point I
had
it working (not sure what was different back then) and I was running
into
issues where the CXF client code was wrapping the JSON payload (I.e.
{"classname": {"id": 1, ...}}), which the RESTEasy services didn't
like. I
got around it by registering a custom ContextResolver for the RESTEasy
services that sets the WRAP_ROOT_VALUE feature on the Jackson object
mapper, and adding a @JsonRootName annotation to my container class, but
would prefer to solve the problem by telling the CXFRS client not to
wrap
the root value. From looking at
http://camel.apache.org/schema/blueprint/cxf/camel-cxf-2.9.0.xsd, I see
that both rsServer and rsClient have a "features" element that I think
might allow me to do this, .but I can't find any documentation or
examples
for using it.

I hope the above made sense, and thanks in advance for your help.

   The client-side wrapper is added by the active JSON provider which is

Jackson in this case.



I might be doing something wrong, but that doesn't seem to be the case. It
seems to be using Jackson for the service I'm exposing using cxf:rsServer.
However, the cxfrs client endpoint (I.e. <to uri="cxfrs:http://etc.../>)
seems to still be using Jettison. I also tried configuring a cxf:rsClient
to access one of my external services, but the paths from my configured
cxf:rsServer bean keep getting appended to the end of my URL. Are the two
beans tightly coupled somehow? I.e.

<cxf:rsServer id="processService" address="http://localhost:8182";
serviceClass="my.Service1"
loggingFeatureEnabled="true">
<cxf:providers>
<ref component-id="jsonProvider" />
</cxf:providers>
</cxf:rsServer>

<cxf:rsClient id="auditService"
address="http://localhost:8080/service2/service2path";
serviceClass="my.Service2"
loggingFeatureEnabled="true">
<cxf:providers>
<ref component-id="jsonProvider" />
</cxf:providers>
</cxf:rsClient>

When my route attempts to invoke Service2, the URI is set to:
http://localhost:8080/service2/service2path/service1/service1path, where
service1/service1path is configured in my.Service1. I'm also not sure why
I'm providing a serviceClass for rsClient. I thought maybe it was going to
instantiate my service, but that doesn't seem to be the case.




  So one option is to configure org.codehaus.jackson.jaxrs.
JacksonJsonProvider
directly in Spring to drop a root element - that should be possible. Can
you try it ?


I was able to find an example for wiring a Jackson ObjectMapper bean and
providing a reference to it to the JacksonJsonProvider bean, but I need to
get my service client working before I can test it.




By the way, how complex the actual sequence is ? The other alternative
can
be to use CXF JSONProvider (Jettison-based) - it is quite flexible in the
way it can shape the sequence



I would rather avoid using Jettison for JSON because of the intermediate
JAXB marshal step it performs. I would also like to avoid annotating my
domain classes with @XmlRootElement (or any other annotation, for that
matter). I'm open to using Jettison, however, if it will allow me to
accomplish what I want.

the sequence is very simple. I basically included the entire camel route
in
my original message. I have a camelContext which contains the dataFormat
configuration for JSON that I posted, along with a route that contains the
two jaxrs calls I posted in the original message (all that was missing
from
that route was the <route></route>. I also have that rsServer bean with
the
JSON provider wired in, and have now added a rsClient that I tried to use
in my route, but it failed as described above. I'm open to trying
something
that is simpler than what I have been doing.






Sergey







--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com




Reply via email to