You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Ralf Steppacher <ra...@derivativepartners.com> on 2012/09/07 16:35:39 UTC

RESTful route with Apache CXF

Hello all,

a quick question about using RESTful endpoints:
Given the route and resource definition below, I end up with the JSON
representation of the PriceRequestMessage in the exchange body, not the
Java object of type PriceRequestMessage. Is there a way to keep the
object as it was created by the nameValueProvider and passed into
getIndicativePrice(PRM prm) in the exchange body and only marshal the
object to the format requested by the client at the very end of the
route?

@POST
@Path("/price")
@Consumes("application/x-www-form-urlencoded")
@Produces("application/json")
public PriceRequestMessage getIndicativePrice(PriceRequestMessage prm) {
  return prm;
}

<camel:route id="rest.route.request.price">
  <camel:from ref="jettyEndpoint" />
  <camel:to
uri="cxfbean:pricingResource?providers=#jsonJacksonProvider,#nameValueProvider" />
  <camel:enrich ref="mq.queue.pricerequest" />
</camel:route>


Thanks!
Ralf

Re: RESTful route with Apache CXF

Posted by Ralf Steppacher <ra...@derivativepartners.com>.
Sergey,

would you say that the current behavior is a bug in the cxfbean endpoint
and at some point I will be able to remove my additional
unmarshal/marshal route steps? Or is this how the endpoint should behave
and all subsequent route steps must be able to deal with all supported
client formats (@Produces)?


Thanks
Ralf

-----Original Message-----
From: Ralf Steppacher <ra...@derivativepartners.com>
Reply-to: users@camel.apache.org
To: users@camel.apache.org
Subject: Re: RESTful route with Apache CXF
Date: Mon, 10 Sep 2012 08:45:04 +0200

Well, I guess I could with a producer template. But routes using a
producer template are not very "obvious" in the Spring XML and I try to
avoid them.
For now I worked around the problem by explicitly unmarshalling the
PriceRequestMessage after the cxfbean route step and then marshalling it
again at the very end of the route. 


Ralf

-----Original Message-----
From: Sergey Beryozkin <sb...@gmail.com>
Reply-to: users@camel.apache.org
To: users@camel.apache.org
Subject: Re: RESTful route with Apache CXF
Date: Fri, 07 Sep 2012 21:09:06 +0100

Can you do camel:enrich progarammatically, within 
getIndicativePrice(PriceRequestMessage prm) ?

Cheers, Sergey


Re: RESTful route with Apache CXF

Posted by Ralf Steppacher <ra...@derivativepartners.com>.
Well, I guess I could with a producer template. But routes using a
producer template are not very "obvious" in the Spring XML and I try to
avoid them.
For now I worked around the problem by explicitly unmarshalling the
PriceRequestMessage after the cxfbean route step and then marshalling it
again at the very end of the route. 


Ralf

-----Original Message-----
From: Sergey Beryozkin <sb...@gmail.com>
Reply-to: users@camel.apache.org
To: users@camel.apache.org
Subject: Re: RESTful route with Apache CXF
Date: Fri, 07 Sep 2012 21:09:06 +0100

Can you do camel:enrich progarammatically, within 
getIndicativePrice(PriceRequestMessage prm) ?

Cheers, Sergey


Re: RESTful route with Apache CXF

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 07/09/12 15:35, Ralf Steppacher wrote:
> Hello all,
>
> a quick question about using RESTful endpoints:
> Given the route and resource definition below, I end up with the JSON
> representation of the PriceRequestMessage in the exchange body, not the
> Java object of type PriceRequestMessage. Is there a way to keep the
> object as it was created by the nameValueProvider and passed into
> getIndicativePrice(PRM prm) in the exchange body and only marshal the
> object to the format requested by the client at the very end of the
> route?
>
> @POST
> @Path("/price")
> @Consumes("application/x-www-form-urlencoded")
> @Produces("application/json")
> public PriceRequestMessage getIndicativePrice(PriceRequestMessage prm) {
>    return prm;
> }
>
> <camel:route id="rest.route.request.price">
>    <camel:from ref="jettyEndpoint" />
>    <camel:to
> uri="cxfbean:pricingResource?providers=#jsonJacksonProvider,#nameValueProvider" />
>    <camel:enrich ref="mq.queue.pricerequest" />
> </camel:route>
>

Can you do camel:enrich progarammatically, within 
getIndicativePrice(PriceRequestMessage prm) ?

Cheers, Sergey
>
> Thanks!
> Ralf


-- 
Sergey Beryozkin

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

Blog: http://sberyozkin.blogspot.com

Re: RESTful route with Apache CXF

Posted by Ralf Steppacher <ra...@derivativepartners.com>.
OK. Thanks again!

Ralf

-----Original Message-----
From: Sergey Beryozkin <sb...@gmail.com>
Reply-to: users@camel.apache.org
To: users@camel.apache.org
Subject: Re: RESTful route with Apache CXF
Date: Tue, 15 Jan 2013 11:11:37 +0000

Hi Ralf
On 15/01/13 11:01, Ralf Steppacher wrote:
> Sergey,
>
> sorry for the extremely delayed response!
np, better later than never :-),
> What you suggest would work for me. Though it would be nice if the steps
> "restore" and "complete" were implicitly invoked. But I know way too
> little about the internal workings of Camel and the route construction
> to suggest that this was possible.
Well, I have to do some homework too and get a better appreciation, but 
I guess this all can be hidden somehow with custom processors of the 
individual route steps.
By the way, if you were to go for it, custom MBW does not need to cast 
to CXF specific output stream, it was my initial experiment really.

Cheers, Sergey
>
>
> Thanks for your help!
> Ralf
>
>
> -----Original Message-----
> From: Sergey Beryozkin<sb...@gmail.com>
> Reply-to: users@camel.apache.org
> To: users@camel.apache.org
> Subject: Re: RESTful route with Apache CXF
> Date: Wed, 03 Oct 2012 20:43:18 +0100
>
> Sorry for a noise,
>
> I think the route below is not exactly correct, should be something
> along these lines:
>
> <route>
>    <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
>    <!-- this is invokes a jaxrs bean -->
>    <to uri="direct:HelloWorldRestServerEndpoint"/>
>
>    <!-- this method will just get the cached object back into Exchange -->
>    <to uri="bean://jaxbProvider?method=restore"/>
>
>    <!-- now do whatever is needed with the bean returned from the service -->
>
>    <!-- finally write to the output stream -->
>    <to uri="bean://jaxbProvider?method=complete"/>
>    </route>
>
> The 'bean:' parts of the routes can be most likely optimized with a
> custom Processor, and the object properties can be updated on the
> provider in case the intermediate parts of the roots somehow enrich or
> change the object properties.
>
> The provider itself can be written to delegate to JAX-RS Providers to
> make sure it is not bound to XML/JAXB only....
>
> Sergey
>
>
>
> On 03/10/12 17:29, Sergey Beryozkin wrote:
>> Ralf,
>>
>> I experimented a bit with the idea of using a two-stage JAX-RS message
>> body writer, that seems to work, here is a prototype.
>>
>> Context:
>>
>> <bean id="jaxbProvider" class="server.CachingJAXBProvider"/>
>>
>> <jaxrs:server id="hello_rest"
>> address="camel://direct:HelloWorldRestServerEndpoint">
>> <jaxrs:serviceBeans>
>> <ref bean="hello-world-bean"/>
>> </jaxrs:serviceBeans>
>> <jaxrs:providers>
>> <ref bean="jaxbProvider"/>
>> </jaxrs:providers>
>> </jaxrs:server>
>>
>> <bean id="hello-world-bean" class="server.HelloWorldImpl"/>
>>
>> <camelContext id="camelContext"
>> xmlns="http://camel.apache.org/schema/spring" trace="false">
>> <route>
>> <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
>> <!-- this is invokes a jaxrs bean -->
>> <to uri="direct:HelloWorldRestServerEndpoint"/>
>> <!-- do whatever is needed with the bean returned from the service -->
>>
>> <!-- write to the output stream -->
>> <to uri="bean://jaxbProvider?method=complete"/>
>> </route>
>> </camelContext>
>>
>> Provider:
>>
>> public class CachingJAXBProvider<T>  extends JAXBElementProvider<T>  {
>>
>> private T object;
>> private Class<?>  cls;
>> private Type genericType;
>> private Annotation[] anns;
>> private MediaType m;
>> private MultivaluedMap<String, Object>  headers;
>> private CacheAndWriteOutputStream os;
>>
>> @Override
>> public void writeTo(T obj, Class<?>  cls, Type genericType, Annotation[]
>> anns,
>> MediaType m, MultivaluedMap<String, Object>  headers, OutputStream os) {
>> this.object = obj;
>> this.cls = cls;
>> this.genericType = genericType;
>> this.anns = anns;
>> this.m = m;
>> this.headers = headers;
>> this.os = new
>> CacheAndWriteOutputStream(((CacheAndWriteOutputStream)os).getFlowThroughStream());
>>
>> }
>>
>> public Object complete(Object obj) throws IOException {
>> super.writeTo(object, cls, genericType, anns, m, headers, os);
>> return os.getOut();
>> }
>>
>> }
>>
>>
>> This actually works, I think it looks a bit hacky and I wonder if a
>> utility provider like this one can be utilized internally and hidden
>> somehow. However I'm quite positive about the fact the process can
>> definitely be controlled - I'd like play with JAX-RS 2.0 AsyncResponse
>> later on.
>>
>> When we have oneway invocations, then it is a different scenario.
>> Also Christian wrote a demo showing how a custom listener is injected
>> into a JAX-RS service bean and then another route starts from this
>> listener being notified
>>
>> Sergey
>>
>>
>> On 03/10/12 12:23, Sergey Beryozkin wrote:
>>> Actually, here is the slightly updated code from one of the tests which
>>> Willem did:
>>>
>>> protected RouteBuilder createRouteBuilder() throws Exception {
>>> return new RouteBuilder() {
>>> public void configure() {
>>> final ResponseBuilder builder = Response.ok();
>>>
>>> from(CXF_RS_ENDPOINT_URI)
>>> // should be able to convert to Customer
>>> .convertBodyTo(Customer.class)
>>> .to("mock:result")
>>> // respond with OK
>>> .transform(constant(builder.entity(***new Customer()***).build()));
>>> };
>>> };
>>> }
>>>
>>> Note the cxfrs server endpoint accepts the request, the response object
>>> is run through the route and finally it can be set on the builder to do
>>> the marshalling done and the response returned.
>>>
>>> The only thing I could not figure out quickly enough was how to actually
>>> get hold of this response object :-)
>>>
>>> Cheers, Sergey
>>>
>>>
>>> On 01/10/12 11:38, Sergey Beryozkin wrote:
>>>> Hi Ralf
>>>> On 01/10/12 07:50, Ralf Steppacher wrote:
>>>>> Willam,
>>>>>
>>>>> thanks for the hint. I shall look into camel-cxfrs.
>>>>>
>>>>> Could you give me a usage example of the cxfbean component? What would
>>>>> be a scenario where immediate marshalling to the client-requested
>>>>> format
>>>>> is desired? Is the idea that all work necessary to produce a meaningful
>>>>> response is done in the resource class and the route only consists of
>>>>> the cxfbean endpoint?
>>>>>
>>>>
>>>> When you have a JAX-RS annotated bean with @Produces, it is not really
>>>> possible to 'delay' marshalling of the response object.
>>>>
>>>> I think something interesting in this regard can also done with the new
>>>> JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request
>>>> is accepted, suspended and resumed at some later stage (the end of the
>>>> route). This just a theory at the moment though, not sure how it will
>>>> can be coordinated with the Camel thread running the whole route
>>>>
>>>> Perhaps one working option is to register a custom JAX-RS
>>>> MessageBodyReader which will simply cache the response object in its
>>>> writeTo method and then at the end of the route this provider will be
>>>> asked to 'flush' the response. Will it work for you ?
>>>>
>>>> Sergey
>>>>>
>>>>> Thanks!
>>>>> Ralf
>>>>>
>>>>> -----Original Message-----
>>>>> From: Willem jiang<wi...@gmail.com>
>>>>> Reply-to: users@camel.apache.org
>>>>> To: users@camel.apache.org
>>>>> Subject: Re: RESTful route with Apache CXF
>>>>> Date: Thu, 27 Sep 2012 15:56:17 +0800
>>>>>
>>>>> Hi Ralf,
>>>>>
>>>>> I think you use misused the cxfbean component.
>>>>> cxfbean component is trying to leverage the camel components to
>>>>> provides different transports.
>>>>>
>>>>> It will marshal and unmarshal the request and response out of box.
>>>>>
>>>>> What's you need is camel-cxfrs[1] component, you should be able to get
>>>>> the Java object of PriceReuqestMessage from the message body.
>>>>>
>>>>> [1]http://camel.apache.org/cxfrs.html
>>>>>
>>>>
>>>>
>
>



Re: RESTful route with Apache CXF

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Ralf
On 15/01/13 11:01, Ralf Steppacher wrote:
> Sergey,
>
> sorry for the extremely delayed response!
np, better later than never :-),
> What you suggest would work for me. Though it would be nice if the steps
> "restore" and "complete" were implicitly invoked. But I know way too
> little about the internal workings of Camel and the route construction
> to suggest that this was possible.
Well, I have to do some homework too and get a better appreciation, but 
I guess this all can be hidden somehow with custom processors of the 
individual route steps.
By the way, if you were to go for it, custom MBW does not need to cast 
to CXF specific output stream, it was my initial experiment really.

Cheers, Sergey
>
>
> Thanks for your help!
> Ralf
>
>
> -----Original Message-----
> From: Sergey Beryozkin<sb...@gmail.com>
> Reply-to: users@camel.apache.org
> To: users@camel.apache.org
> Subject: Re: RESTful route with Apache CXF
> Date: Wed, 03 Oct 2012 20:43:18 +0100
>
> Sorry for a noise,
>
> I think the route below is not exactly correct, should be something
> along these lines:
>
> <route>
>    <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
>    <!-- this is invokes a jaxrs bean -->
>    <to uri="direct:HelloWorldRestServerEndpoint"/>
>
>    <!-- this method will just get the cached object back into Exchange -->
>    <to uri="bean://jaxbProvider?method=restore"/>
>
>    <!-- now do whatever is needed with the bean returned from the service -->
>
>    <!-- finally write to the output stream -->
>    <to uri="bean://jaxbProvider?method=complete"/>
>    </route>
>
> The 'bean:' parts of the routes can be most likely optimized with a
> custom Processor, and the object properties can be updated on the
> provider in case the intermediate parts of the roots somehow enrich or
> change the object properties.
>
> The provider itself can be written to delegate to JAX-RS Providers to
> make sure it is not bound to XML/JAXB only....
>
> Sergey
>
>
>
> On 03/10/12 17:29, Sergey Beryozkin wrote:
>> Ralf,
>>
>> I experimented a bit with the idea of using a two-stage JAX-RS message
>> body writer, that seems to work, here is a prototype.
>>
>> Context:
>>
>> <bean id="jaxbProvider" class="server.CachingJAXBProvider"/>
>>
>> <jaxrs:server id="hello_rest"
>> address="camel://direct:HelloWorldRestServerEndpoint">
>> <jaxrs:serviceBeans>
>> <ref bean="hello-world-bean"/>
>> </jaxrs:serviceBeans>
>> <jaxrs:providers>
>> <ref bean="jaxbProvider"/>
>> </jaxrs:providers>
>> </jaxrs:server>
>>
>> <bean id="hello-world-bean" class="server.HelloWorldImpl"/>
>>
>> <camelContext id="camelContext"
>> xmlns="http://camel.apache.org/schema/spring" trace="false">
>> <route>
>> <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
>> <!-- this is invokes a jaxrs bean -->
>> <to uri="direct:HelloWorldRestServerEndpoint"/>
>> <!-- do whatever is needed with the bean returned from the service -->
>>
>> <!-- write to the output stream -->
>> <to uri="bean://jaxbProvider?method=complete"/>
>> </route>
>> </camelContext>
>>
>> Provider:
>>
>> public class CachingJAXBProvider<T>  extends JAXBElementProvider<T>  {
>>
>> private T object;
>> private Class<?>  cls;
>> private Type genericType;
>> private Annotation[] anns;
>> private MediaType m;
>> private MultivaluedMap<String, Object>  headers;
>> private CacheAndWriteOutputStream os;
>>
>> @Override
>> public void writeTo(T obj, Class<?>  cls, Type genericType, Annotation[]
>> anns,
>> MediaType m, MultivaluedMap<String, Object>  headers, OutputStream os) {
>> this.object = obj;
>> this.cls = cls;
>> this.genericType = genericType;
>> this.anns = anns;
>> this.m = m;
>> this.headers = headers;
>> this.os = new
>> CacheAndWriteOutputStream(((CacheAndWriteOutputStream)os).getFlowThroughStream());
>>
>> }
>>
>> public Object complete(Object obj) throws IOException {
>> super.writeTo(object, cls, genericType, anns, m, headers, os);
>> return os.getOut();
>> }
>>
>> }
>>
>>
>> This actually works, I think it looks a bit hacky and I wonder if a
>> utility provider like this one can be utilized internally and hidden
>> somehow. However I'm quite positive about the fact the process can
>> definitely be controlled - I'd like play with JAX-RS 2.0 AsyncResponse
>> later on.
>>
>> When we have oneway invocations, then it is a different scenario.
>> Also Christian wrote a demo showing how a custom listener is injected
>> into a JAX-RS service bean and then another route starts from this
>> listener being notified
>>
>> Sergey
>>
>>
>> On 03/10/12 12:23, Sergey Beryozkin wrote:
>>> Actually, here is the slightly updated code from one of the tests which
>>> Willem did:
>>>
>>> protected RouteBuilder createRouteBuilder() throws Exception {
>>> return new RouteBuilder() {
>>> public void configure() {
>>> final ResponseBuilder builder = Response.ok();
>>>
>>> from(CXF_RS_ENDPOINT_URI)
>>> // should be able to convert to Customer
>>> .convertBodyTo(Customer.class)
>>> .to("mock:result")
>>> // respond with OK
>>> .transform(constant(builder.entity(***new Customer()***).build()));
>>> };
>>> };
>>> }
>>>
>>> Note the cxfrs server endpoint accepts the request, the response object
>>> is run through the route and finally it can be set on the builder to do
>>> the marshalling done and the response returned.
>>>
>>> The only thing I could not figure out quickly enough was how to actually
>>> get hold of this response object :-)
>>>
>>> Cheers, Sergey
>>>
>>>
>>> On 01/10/12 11:38, Sergey Beryozkin wrote:
>>>> Hi Ralf
>>>> On 01/10/12 07:50, Ralf Steppacher wrote:
>>>>> Willam,
>>>>>
>>>>> thanks for the hint. I shall look into camel-cxfrs.
>>>>>
>>>>> Could you give me a usage example of the cxfbean component? What would
>>>>> be a scenario where immediate marshalling to the client-requested
>>>>> format
>>>>> is desired? Is the idea that all work necessary to produce a meaningful
>>>>> response is done in the resource class and the route only consists of
>>>>> the cxfbean endpoint?
>>>>>
>>>>
>>>> When you have a JAX-RS annotated bean with @Produces, it is not really
>>>> possible to 'delay' marshalling of the response object.
>>>>
>>>> I think something interesting in this regard can also done with the new
>>>> JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request
>>>> is accepted, suspended and resumed at some later stage (the end of the
>>>> route). This just a theory at the moment though, not sure how it will
>>>> can be coordinated with the Camel thread running the whole route
>>>>
>>>> Perhaps one working option is to register a custom JAX-RS
>>>> MessageBodyReader which will simply cache the response object in its
>>>> writeTo method and then at the end of the route this provider will be
>>>> asked to 'flush' the response. Will it work for you ?
>>>>
>>>> Sergey
>>>>>
>>>>> Thanks!
>>>>> Ralf
>>>>>
>>>>> -----Original Message-----
>>>>> From: Willem jiang<wi...@gmail.com>
>>>>> Reply-to: users@camel.apache.org
>>>>> To: users@camel.apache.org
>>>>> Subject: Re: RESTful route with Apache CXF
>>>>> Date: Thu, 27 Sep 2012 15:56:17 +0800
>>>>>
>>>>> Hi Ralf,
>>>>>
>>>>> I think you use misused the cxfbean component.
>>>>> cxfbean component is trying to leverage the camel components to
>>>>> provides different transports.
>>>>>
>>>>> It will marshal and unmarshal the request and response out of box.
>>>>>
>>>>> What's you need is camel-cxfrs[1] component, you should be able to get
>>>>> the Java object of PriceReuqestMessage from the message body.
>>>>>
>>>>> [1]http://camel.apache.org/cxfrs.html
>>>>>
>>>>
>>>>
>
>



Re: RESTful route with Apache CXF

Posted by Ralf Steppacher <ra...@derivativepartners.com>.
Sergey,

sorry for the extremely delayed response!
What you suggest would work for me. Though it would be nice if the steps
"restore" and "complete" were implicitly invoked. But I know way too
little about the internal workings of Camel and the route construction
to suggest that this was possible.


Thanks for your help!
Ralf


-----Original Message-----
From: Sergey Beryozkin <sb...@gmail.com>
Reply-to: users@camel.apache.org
To: users@camel.apache.org
Subject: Re: RESTful route with Apache CXF
Date: Wed, 03 Oct 2012 20:43:18 +0100

Sorry for a noise,

I think the route below is not exactly correct, should be something 
along these lines:

<route>
  <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
  <!-- this is invokes a jaxrs bean -->
  <to uri="direct:HelloWorldRestServerEndpoint"/>

  <!-- this method will just get the cached object back into Exchange -->
  <to uri="bean://jaxbProvider?method=restore"/>

  <!-- now do whatever is needed with the bean returned from the service -->

  <!-- finally write to the output stream -->
  <to uri="bean://jaxbProvider?method=complete"/>
  </route>

The 'bean:' parts of the routes can be most likely optimized with a 
custom Processor, and the object properties can be updated on the 
provider in case the intermediate parts of the roots somehow enrich or 
change the object properties.

The provider itself can be written to delegate to JAX-RS Providers to 
make sure it is not bound to XML/JAXB only....

Sergey



On 03/10/12 17:29, Sergey Beryozkin wrote:
> Ralf,
>
> I experimented a bit with the idea of using a two-stage JAX-RS message
> body writer, that seems to work, here is a prototype.
>
> Context:
>
> <bean id="jaxbProvider" class="server.CachingJAXBProvider"/>
>
> <jaxrs:server id="hello_rest"
> address="camel://direct:HelloWorldRestServerEndpoint">
> <jaxrs:serviceBeans>
> <ref bean="hello-world-bean"/>
> </jaxrs:serviceBeans>
> <jaxrs:providers>
> <ref bean="jaxbProvider"/>
> </jaxrs:providers>
> </jaxrs:server>
>
> <bean id="hello-world-bean" class="server.HelloWorldImpl"/>
>
> <camelContext id="camelContext"
> xmlns="http://camel.apache.org/schema/spring" trace="false">
> <route>
> <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
> <!-- this is invokes a jaxrs bean -->
> <to uri="direct:HelloWorldRestServerEndpoint"/>
> <!-- do whatever is needed with the bean returned from the service -->
>
> <!-- write to the output stream -->
> <to uri="bean://jaxbProvider?method=complete"/>
> </route>
> </camelContext>
>
> Provider:
>
> public class CachingJAXBProvider<T> extends JAXBElementProvider<T> {
>
> private T object;
> private Class<?> cls;
> private Type genericType;
> private Annotation[] anns;
> private MediaType m;
> private MultivaluedMap<String, Object> headers;
> private CacheAndWriteOutputStream os;
>
> @Override
> public void writeTo(T obj, Class<?> cls, Type genericType, Annotation[]
> anns,
> MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) {
> this.object = obj;
> this.cls = cls;
> this.genericType = genericType;
> this.anns = anns;
> this.m = m;
> this.headers = headers;
> this.os = new
> CacheAndWriteOutputStream(((CacheAndWriteOutputStream)os).getFlowThroughStream());
>
> }
>
> public Object complete(Object obj) throws IOException {
> super.writeTo(object, cls, genericType, anns, m, headers, os);
> return os.getOut();
> }
>
> }
>
>
> This actually works, I think it looks a bit hacky and I wonder if a
> utility provider like this one can be utilized internally and hidden
> somehow. However I'm quite positive about the fact the process can
> definitely be controlled - I'd like play with JAX-RS 2.0 AsyncResponse
> later on.
>
> When we have oneway invocations, then it is a different scenario.
> Also Christian wrote a demo showing how a custom listener is injected
> into a JAX-RS service bean and then another route starts from this
> listener being notified
>
> Sergey
>
>
> On 03/10/12 12:23, Sergey Beryozkin wrote:
>> Actually, here is the slightly updated code from one of the tests which
>> Willem did:
>>
>> protected RouteBuilder createRouteBuilder() throws Exception {
>> return new RouteBuilder() {
>> public void configure() {
>> final ResponseBuilder builder = Response.ok();
>>
>> from(CXF_RS_ENDPOINT_URI)
>> // should be able to convert to Customer
>> .convertBodyTo(Customer.class)
>> .to("mock:result")
>> // respond with OK
>> .transform(constant(builder.entity(***new Customer()***).build()));
>> };
>> };
>> }
>>
>> Note the cxfrs server endpoint accepts the request, the response object
>> is run through the route and finally it can be set on the builder to do
>> the marshalling done and the response returned.
>>
>> The only thing I could not figure out quickly enough was how to actually
>> get hold of this response object :-)
>>
>> Cheers, Sergey
>>
>>
>> On 01/10/12 11:38, Sergey Beryozkin wrote:
>>> Hi Ralf
>>> On 01/10/12 07:50, Ralf Steppacher wrote:
>>>> Willam,
>>>>
>>>> thanks for the hint. I shall look into camel-cxfrs.
>>>>
>>>> Could you give me a usage example of the cxfbean component? What would
>>>> be a scenario where immediate marshalling to the client-requested
>>>> format
>>>> is desired? Is the idea that all work necessary to produce a meaningful
>>>> response is done in the resource class and the route only consists of
>>>> the cxfbean endpoint?
>>>>
>>>
>>> When you have a JAX-RS annotated bean with @Produces, it is not really
>>> possible to 'delay' marshalling of the response object.
>>>
>>> I think something interesting in this regard can also done with the new
>>> JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request
>>> is accepted, suspended and resumed at some later stage (the end of the
>>> route). This just a theory at the moment though, not sure how it will
>>> can be coordinated with the Camel thread running the whole route
>>>
>>> Perhaps one working option is to register a custom JAX-RS
>>> MessageBodyReader which will simply cache the response object in its
>>> writeTo method and then at the end of the route this provider will be
>>> asked to 'flush' the response. Will it work for you ?
>>>
>>> Sergey
>>>>
>>>> Thanks!
>>>> Ralf
>>>>
>>>> -----Original Message-----
>>>> From: Willem jiang<wi...@gmail.com>
>>>> Reply-to: users@camel.apache.org
>>>> To: users@camel.apache.org
>>>> Subject: Re: RESTful route with Apache CXF
>>>> Date: Thu, 27 Sep 2012 15:56:17 +0800
>>>>
>>>> Hi Ralf,
>>>>
>>>> I think you use misused the cxfbean component.
>>>> cxfbean component is trying to leverage the camel components to
>>>> provides different transports.
>>>>
>>>> It will marshal and unmarshal the request and response out of box.
>>>>
>>>> What's you need is camel-cxfrs[1] component, you should be able to get
>>>> the Java object of PriceReuqestMessage from the message body.
>>>>
>>>> [1]http://camel.apache.org/cxfrs.html
>>>>
>>>
>>>



Re: RESTful route with Apache CXF

Posted by Sergey Beryozkin <sb...@gmail.com>.
Sorry for a noise,

I think the route below is not exactly correct, should be something 
along these lines:

<route>
  <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
  <!-- this is invokes a jaxrs bean -->
  <to uri="direct:HelloWorldRestServerEndpoint"/>

  <!-- this method will just get the cached object back into Exchange -->
  <to uri="bean://jaxbProvider?method=restore"/>

  <!-- now do whatever is needed with the bean returned from the service -->

  <!-- finally write to the output stream -->
  <to uri="bean://jaxbProvider?method=complete"/>
  </route>

The 'bean:' parts of the routes can be most likely optimized with a 
custom Processor, and the object properties can be updated on the 
provider in case the intermediate parts of the roots somehow enrich or 
change the object properties.

The provider itself can be written to delegate to JAX-RS Providers to 
make sure it is not bound to XML/JAXB only....

Sergey



On 03/10/12 17:29, Sergey Beryozkin wrote:
> Ralf,
>
> I experimented a bit with the idea of using a two-stage JAX-RS message
> body writer, that seems to work, here is a prototype.
>
> Context:
>
> <bean id="jaxbProvider" class="server.CachingJAXBProvider"/>
>
> <jaxrs:server id="hello_rest"
> address="camel://direct:HelloWorldRestServerEndpoint">
> <jaxrs:serviceBeans>
> <ref bean="hello-world-bean"/>
> </jaxrs:serviceBeans>
> <jaxrs:providers>
> <ref bean="jaxbProvider"/>
> </jaxrs:providers>
> </jaxrs:server>
>
> <bean id="hello-world-bean" class="server.HelloWorldImpl"/>
>
> <camelContext id="camelContext"
> xmlns="http://camel.apache.org/schema/spring" trace="false">
> <route>
> <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
> <!-- this is invokes a jaxrs bean -->
> <to uri="direct:HelloWorldRestServerEndpoint"/>
> <!-- do whatever is needed with the bean returned from the service -->
>
> <!-- write to the output stream -->
> <to uri="bean://jaxbProvider?method=complete"/>
> </route>
> </camelContext>
>
> Provider:
>
> public class CachingJAXBProvider<T> extends JAXBElementProvider<T> {
>
> private T object;
> private Class<?> cls;
> private Type genericType;
> private Annotation[] anns;
> private MediaType m;
> private MultivaluedMap<String, Object> headers;
> private CacheAndWriteOutputStream os;
>
> @Override
> public void writeTo(T obj, Class<?> cls, Type genericType, Annotation[]
> anns,
> MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) {
> this.object = obj;
> this.cls = cls;
> this.genericType = genericType;
> this.anns = anns;
> this.m = m;
> this.headers = headers;
> this.os = new
> CacheAndWriteOutputStream(((CacheAndWriteOutputStream)os).getFlowThroughStream());
>
> }
>
> public Object complete(Object obj) throws IOException {
> super.writeTo(object, cls, genericType, anns, m, headers, os);
> return os.getOut();
> }
>
> }
>
>
> This actually works, I think it looks a bit hacky and I wonder if a
> utility provider like this one can be utilized internally and hidden
> somehow. However I'm quite positive about the fact the process can
> definitely be controlled - I'd like play with JAX-RS 2.0 AsyncResponse
> later on.
>
> When we have oneway invocations, then it is a different scenario.
> Also Christian wrote a demo showing how a custom listener is injected
> into a JAX-RS service bean and then another route starts from this
> listener being notified
>
> Sergey
>
>
> On 03/10/12 12:23, Sergey Beryozkin wrote:
>> Actually, here is the slightly updated code from one of the tests which
>> Willem did:
>>
>> protected RouteBuilder createRouteBuilder() throws Exception {
>> return new RouteBuilder() {
>> public void configure() {
>> final ResponseBuilder builder = Response.ok();
>>
>> from(CXF_RS_ENDPOINT_URI)
>> // should be able to convert to Customer
>> .convertBodyTo(Customer.class)
>> .to("mock:result")
>> // respond with OK
>> .transform(constant(builder.entity(***new Customer()***).build()));
>> };
>> };
>> }
>>
>> Note the cxfrs server endpoint accepts the request, the response object
>> is run through the route and finally it can be set on the builder to do
>> the marshalling done and the response returned.
>>
>> The only thing I could not figure out quickly enough was how to actually
>> get hold of this response object :-)
>>
>> Cheers, Sergey
>>
>>
>> On 01/10/12 11:38, Sergey Beryozkin wrote:
>>> Hi Ralf
>>> On 01/10/12 07:50, Ralf Steppacher wrote:
>>>> Willam,
>>>>
>>>> thanks for the hint. I shall look into camel-cxfrs.
>>>>
>>>> Could you give me a usage example of the cxfbean component? What would
>>>> be a scenario where immediate marshalling to the client-requested
>>>> format
>>>> is desired? Is the idea that all work necessary to produce a meaningful
>>>> response is done in the resource class and the route only consists of
>>>> the cxfbean endpoint?
>>>>
>>>
>>> When you have a JAX-RS annotated bean with @Produces, it is not really
>>> possible to 'delay' marshalling of the response object.
>>>
>>> I think something interesting in this regard can also done with the new
>>> JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request
>>> is accepted, suspended and resumed at some later stage (the end of the
>>> route). This just a theory at the moment though, not sure how it will
>>> can be coordinated with the Camel thread running the whole route
>>>
>>> Perhaps one working option is to register a custom JAX-RS
>>> MessageBodyReader which will simply cache the response object in its
>>> writeTo method and then at the end of the route this provider will be
>>> asked to 'flush' the response. Will it work for you ?
>>>
>>> Sergey
>>>>
>>>> Thanks!
>>>> Ralf
>>>>
>>>> -----Original Message-----
>>>> From: Willem jiang<wi...@gmail.com>
>>>> Reply-to: users@camel.apache.org
>>>> To: users@camel.apache.org
>>>> Subject: Re: RESTful route with Apache CXF
>>>> Date: Thu, 27 Sep 2012 15:56:17 +0800
>>>>
>>>> Hi Ralf,
>>>>
>>>> I think you use misused the cxfbean component.
>>>> cxfbean component is trying to leverage the camel components to
>>>> provides different transports.
>>>>
>>>> It will marshal and unmarshal the request and response out of box.
>>>>
>>>> What's you need is camel-cxfrs[1] component, you should be able to get
>>>> the Java object of PriceReuqestMessage from the message body.
>>>>
>>>> [1]http://camel.apache.org/cxfrs.html
>>>>
>>>
>>>


-- 
Sergey Beryozkin

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

Blog: http://sberyozkin.blogspot.com

Re: RESTful route with Apache CXF

Posted by Sergey Beryozkin <sb...@gmail.com>.
Ralf,

I experimented a bit with the idea of using a two-stage JAX-RS message 
body writer, that seems to work, here is a prototype.

Context:

<bean id="jaxbProvider" class="server.CachingJAXBProvider"/>

<jaxrs:server id="hello_rest" 
address="camel://direct:HelloWorldRestServerEndpoint">
         <jaxrs:serviceBeans>
             <ref bean="hello-world-bean"/>
         </jaxrs:serviceBeans>
         <jaxrs:providers>
             <ref bean="jaxbProvider"/>
         </jaxrs:providers>
</jaxrs:server>

<bean id="hello-world-bean" class="server.HelloWorldImpl"/>

     <camelContext id="camelContext" 
xmlns="http://camel.apache.org/schema/spring" trace="false">
         <route>
             <from uri="servlet:///HelloWorld?matchOnUriPrefix=true"/>
             <!-- this is invokes a jaxrs bean -->
             <to uri="direct:HelloWorldRestServerEndpoint"/>
             <!-- do whatever is needed with the bean returned from the 
service -->

             <!-- write to the output stream -->
             <to uri="bean://jaxbProvider?method=complete"/>
         </route>
     </camelContext>

Provider:

public class CachingJAXBProvider<T> extends JAXBElementProvider<T> {

	private T object;
	private Class<?> cls;
	private Type genericType;
	private Annotation[] anns;
     private MediaType m;
     private MultivaluedMap<String, Object> headers;
     private CacheAndWriteOutputStream os;

     @Override
     public void writeTo(T obj, Class<?> cls, Type genericType, 
Annotation[] anns,
	        MediaType m, MultivaluedMap<String, Object> headers, 
OutputStream os) {
		this.object = obj;
		this.cls = cls;
		this.genericType = genericType;
	    this.anns = anns;
	    this.m = m;
	    this.headers = headers;
	    this.os = new 
CacheAndWriteOutputStream(((CacheAndWriteOutputStream)os).getFlowThroughStream());
	}
	
	public Object complete(Object obj) throws IOException {
		super.writeTo(object, cls, genericType, anns, m, headers, os);
		return os.getOut();
	}
	
}


This actually works, I think it looks a bit hacky and I wonder if a 
utility provider like this one can be utilized internally and hidden 
somehow. However I'm quite positive about the fact the process can 
definitely be controlled - I'd like play with JAX-RS 2.0 AsyncResponse 
later on.

When we have oneway invocations, then it is a different scenario.
Also Christian wrote a demo showing how a custom listener is injected 
into a JAX-RS service bean and then another route starts from this 
listener being notified

Sergey


On 03/10/12 12:23, Sergey Beryozkin wrote:
> Actually, here is the slightly updated code from one of the tests which
> Willem did:
>
> protected RouteBuilder createRouteBuilder() throws Exception {
> return new RouteBuilder() {
> public void configure() {
> final ResponseBuilder builder = Response.ok();
>
> from(CXF_RS_ENDPOINT_URI)
> // should be able to convert to Customer
> .convertBodyTo(Customer.class)
> .to("mock:result")
> // respond with OK
> .transform(constant(builder.entity(***new Customer()***).build()));
> };
> };
> }
>
> Note the cxfrs server endpoint accepts the request, the response object
> is run through the route and finally it can be set on the builder to do
> the marshalling done and the response returned.
>
> The only thing I could not figure out quickly enough was how to actually
> get hold of this response object :-)
>
> Cheers, Sergey
>
>
> On 01/10/12 11:38, Sergey Beryozkin wrote:
>> Hi Ralf
>> On 01/10/12 07:50, Ralf Steppacher wrote:
>>> Willam,
>>>
>>> thanks for the hint. I shall look into camel-cxfrs.
>>>
>>> Could you give me a usage example of the cxfbean component? What would
>>> be a scenario where immediate marshalling to the client-requested format
>>> is desired? Is the idea that all work necessary to produce a meaningful
>>> response is done in the resource class and the route only consists of
>>> the cxfbean endpoint?
>>>
>>
>> When you have a JAX-RS annotated bean with @Produces, it is not really
>> possible to 'delay' marshalling of the response object.
>>
>> I think something interesting in this regard can also done with the new
>> JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request
>> is accepted, suspended and resumed at some later stage (the end of the
>> route). This just a theory at the moment though, not sure how it will
>> can be coordinated with the Camel thread running the whole route
>>
>> Perhaps one working option is to register a custom JAX-RS
>> MessageBodyReader which will simply cache the response object in its
>> writeTo method and then at the end of the route this provider will be
>> asked to 'flush' the response. Will it work for you ?
>>
>> Sergey
>>>
>>> Thanks!
>>> Ralf
>>>
>>> -----Original Message-----
>>> From: Willem jiang<wi...@gmail.com>
>>> Reply-to: users@camel.apache.org
>>> To: users@camel.apache.org
>>> Subject: Re: RESTful route with Apache CXF
>>> Date: Thu, 27 Sep 2012 15:56:17 +0800
>>>
>>> Hi Ralf,
>>>
>>> I think you use misused the cxfbean component.
>>> cxfbean component is trying to leverage the camel components to
>>> provides different transports.
>>>
>>> It will marshal and unmarshal the request and response out of box.
>>>
>>> What's you need is camel-cxfrs[1] component, you should be able to get
>>> the Java object of PriceReuqestMessage from the message body.
>>>
>>> [1]http://camel.apache.org/cxfrs.html
>>>
>>
>>

Re: RESTful route with Apache CXF

Posted by Sergey Beryozkin <sb...@gmail.com>.
Actually, here is the slightly updated code from one of the tests which 
Willem did:

protected RouteBuilder createRouteBuilder() throws Exception {
         return new RouteBuilder() {
             public void configure() {
                 final ResponseBuilder builder = Response.ok();

                 from(CXF_RS_ENDPOINT_URI)
                     // should be able to convert to Customer
                     .convertBodyTo(Customer.class)
                     .to("mock:result")
                     // respond with OK
                     .transform(constant(builder.entity(***new 
Customer()***).build()));
             };
         };
     }

Note the cxfrs server endpoint accepts the request, the response object 
is run through the route and finally it can be set on the builder to do 
the marshalling done and the response returned.

The only thing I could not figure out quickly enough was how to actually 
get hold of this response object :-)

Cheers, Sergey


On 01/10/12 11:38, Sergey Beryozkin wrote:
> Hi Ralf
> On 01/10/12 07:50, Ralf Steppacher wrote:
>> Willam,
>>
>> thanks for the hint. I shall look into camel-cxfrs.
>>
>> Could you give me a usage example of the cxfbean component? What would
>> be a scenario where immediate marshalling to the client-requested format
>> is desired? Is the idea that all work necessary to produce a meaningful
>> response is done in the resource class and the route only consists of
>> the cxfbean endpoint?
>>
>
> When you have a JAX-RS annotated bean with @Produces, it is not really
> possible to 'delay' marshalling of the response object.
>
> I think something interesting in this regard can also done with the new
> JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request
> is accepted, suspended and resumed at some later stage (the end of the
> route). This just a theory at the moment though, not sure how it will
> can be coordinated with the Camel thread running the whole route
>
> Perhaps one working option is to register a custom JAX-RS
> MessageBodyReader which will simply cache the response object in its
> writeTo method and then at the end of the route this provider will be
> asked to 'flush' the response. Will it work for you ?
>
> Sergey
>>
>> Thanks!
>> Ralf
>>
>> -----Original Message-----
>> From: Willem jiang<wi...@gmail.com>
>> Reply-to: users@camel.apache.org
>> To: users@camel.apache.org
>> Subject: Re: RESTful route with Apache CXF
>> Date: Thu, 27 Sep 2012 15:56:17 +0800
>>
>> Hi Ralf,
>>
>> I think you use misused the cxfbean component.
>> cxfbean component is trying to leverage the camel components to
>> provides different transports.
>>
>> It will marshal and unmarshal the request and response out of box.
>>
>> What's you need is camel-cxfrs[1] component, you should be able to get
>> the Java object of PriceReuqestMessage from the message body.
>>
>> [1]http://camel.apache.org/cxfrs.html
>>
>
>

Re: RESTful route with Apache CXF

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Ralf
On 01/10/12 07:50, Ralf Steppacher wrote:
> Willam,
>
> thanks for the hint. I shall look into camel-cxfrs.
>
> Could you give me a usage example of the cxfbean component? What would
> be a scenario where immediate marshalling to the client-requested format
> is desired? Is the idea that all work necessary to produce a meaningful
> response is done in the resource class and the route only consists of
> the cxfbean endpoint?
>

When you have a JAX-RS annotated bean with @Produces, it is not really 
possible to 'delay' marshalling of the response object.

I think something interesting in this regard can also done with the new 
JAX-RS 2.0 AsyncResponse: say at the top of the route the JAX-RS request 
is accepted, suspended and resumed at some later stage (the end of the 
route). This just a theory at the moment though, not sure how it will 
can be coordinated with the Camel thread running the whole route

Perhaps one working option is to register a custom JAX-RS 
MessageBodyReader which will simply cache the response object in its 
writeTo method and then at the end of the route this provider will be 
asked to 'flush' the response. Will it work for you ?

Sergey
>
> Thanks!
> Ralf
>
> -----Original Message-----
> From: Willem jiang<wi...@gmail.com>
> Reply-to: users@camel.apache.org
> To: users@camel.apache.org
> Subject: Re: RESTful route with Apache CXF
> Date: Thu, 27 Sep 2012 15:56:17 +0800
>
> Hi Ralf,
>
> I think you use misused the cxfbean component.
> cxfbean component is trying to leverage the camel components to provides different transports.
>
> It will marshal and unmarshal the request and response out of box.
>
> What's you need is camel-cxfrs[1] component, you should be able to get the Java object of PriceReuqestMessage from the message body.
>
> [1]http://camel.apache.org/cxfrs.html
>



Re: RESTful route with Apache CXF

Posted by Ralf Steppacher <ra...@derivativepartners.com>.
Willam,

thanks for the hint. I shall look into camel-cxfrs.

Could you give me a usage example of the cxfbean component? What would
be a scenario where immediate marshalling to the client-requested format
is desired? Is the idea that all work necessary to produce a meaningful
response is done in the resource class and the route only consists of
the cxfbean endpoint?


Thanks!
Ralf

-----Original Message-----
From: Willem jiang <wi...@gmail.com>
Reply-to: users@camel.apache.org
To: users@camel.apache.org
Subject: Re: RESTful route with Apache CXF
Date: Thu, 27 Sep 2012 15:56:17 +0800

Hi Ralf,

I think you use misused the cxfbean component.
cxfbean component is trying to leverage the camel components to provides different transports.

It will marshal and unmarshal the request and response out of box.

What's you need is camel-cxfrs[1] component, you should be able to get the Java object of PriceReuqestMessage from the message body.

[1]http://camel.apache.org/cxfrs.html 


Re: RESTful route with Apache CXF

Posted by Willem jiang <wi...@gmail.com>.
Hi Ralf,

I think you use misused the cxfbean component.
cxfbean component is trying to leverage the camel components to provides different transports.

It will marshal and unmarshal the request and response out of box.

What's you need is camel-cxfrs[1] component, you should be able to get the Java object of PriceReuqestMessage from the message body.

[1]http://camel.apache.org/cxfrs.html 

-- 
Willem Jiang

Red Hat, Inc.
FuseSource is now part of Red Hat
Web: http://www.fusesource.com | http://www.redhat.com
Blog: http://willemjiang.blogspot.com (http://willemjiang.blogspot.com/) (English)
          http://jnn.javaeye.com (http://jnn.javaeye.com/) (Chinese)
Twitter: willemjiang 
Weibo: willemjiang



On Friday, September 7, 2012 at 10:35 PM, Ralf Steppacher wrote:

> Hello all,
> 
> a quick question about using RESTful endpoints:
> Given the route and resource definition below, I end up with the JSON
> representation of the PriceRequestMessage in the exchange body, not the
> Java object of type PriceRequestMessage. Is there a way to keep the
> object as it was created by the nameValueProvider and passed into
> getIndicativePrice(PRM prm) in the exchange body and only marshal the
> object to the format requested by the client at the very end of the
> route?
> 
> @POST
> @Path("/price")
> @Consumes("application/x-www-form-urlencoded")
> @Produces("application/json")
> public PriceRequestMessage getIndicativePrice(PriceRequestMessage prm) {
> return prm;
> }
> 
> <camel:route id="rest.route.request.price">
> <camel:from ref="jettyEndpoint" />
> <camel:to
> uri="cxfbean:pricingResource?providers=#jsonJacksonProvider,#nameValueProvider" />
> <camel:enrich ref="mq.queue.pricerequest" />
> </camel:route>
> 
> 
> Thanks!
> Ralf