camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: RESTful route with Apache CXF
Date Wed, 03 Oct 2012 16:29:57 GMT
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<willem.jiang@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
>>>
>>
>>

Mime
View raw message