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 >