camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: Confused with REST API consumer with CXF(RS)
Date Tue, 06 Nov 2012 18:08:12 GMT
On 06/11/12 17:42, Martin Stiborsk√Ĺ wrote:
> Hello guys!
> I need a help, again…This time about REST and CXF. I've moved from restlet
> component to CXF and it raised quite a lot of questions, it was easier with
> Restlet, but now I have to deal with CXF.
>
> At least, I have a working "proof of concept" of the REST API with CXF in
> Camel, that works, but, it's not looking "nice and clean" for me, so I have
> few questions, if all this is really ok and that is the "recommended" or
> something like this :)
>
> First, I have declared a "face" of the REST API:
>
> public class DemoServer {
>
>      @GET
>      @Path("/hellodemo/{hello}")
>      @Produces("text/plain")
>      public Response demoHello(@PathParam("hello") String hello) {
>          return null;
>      }
>
>      @GET
>      @Path("/{foo}/bar")
>      @Produces("text/plain")
>      public Response fooHello(@PathParam("foo") String foo) {
>          return null;
>      }
> }
>
> Then, I've registered this "DemoServer" as "cxf:rsServer" in blueprint.xml:
>
> <camel-cxf:rsServer id="demoServer" address="${server.cxfrest.base}/demo/"
>                          serviceClass="com.my.example.DemoServer"/>
>
> And then, finally, the Camel route:
>
> from("cxfrs:bean:demoServer")
>                  .choice()
>
> .when(header(CxfConstants.OPERATION_NAME).isEqualTo("demoHello"))
>                          .to("bean:demoBean")
>
> .when(header(CxfConstants.OPERATION_NAME).isEqualTo("fooHello"))
>                          .to("bean:fooBean")
>                      .otherwise()
>                          .to("bean:anotherBean");
>
> Now, questions :)
>
> First of all, is that really correct? It should be like that? Well, I'm
> fine with that, but few things looks weird to me.
>
> My intention is to have REST API on the consumer endpoint side, in the
> middle is some processing, based on inputs from the REST requests, and on
> the produce endpoint side, there is almost all the time HTTP reponse with
> some content back to browser (JSON data, usually).
>
> So, for example, the implementation of "DemoServer" looks weird, I don't
> like the "return null" there. Yes it works like it should, like I need, but
> this looks odd.

Agreed. I was writing some test few weeks ago and it took me awhile 
before I understood how it worked, and I'll need to refresh my memory 
again next time again I'm sure :-).

As far as I recall, this 'face' is only used to get the JAX-RS runtime 
prepare all the parameters as per the specific signature.

I've experimented a bit with using jaxrs:endpoint as a consumer 
directly. It worked quite well. All you have to do is to create a custom 
MessageBodyWriter which will cache the response object in its 
writeTo(..., OutputStream os), if any,

and then at the end of the route, will be asked to finally write it into 
the output stream using the references saved at the time writeTo is called.

Thus you can have DemoService implemented as a regular JAX-RS endpoint 
and get the response object manipulated further in the route and finally 
serialized as needed, with custom MBR taking care of it. It may look 
like this:

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 OutputStream 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 = os;
	}
	
	public Object complete(Object obj) throws IOException {
		super.writeTo(object, cls, genericType, anns, m, headers, os);
		return os;
	}
	
}


You can also have the in parameters made available to other camel 
routes, example. Christian wrote a demo where an interface like

public interface BookListener {

     void onBook(Book book);

}

is injected, the service implementation calls BookListener.onBook() 
which triggers another route

HTH, Sergey

>
> Then, in the route definition, there is the content based router, this
> choice()/when() things, because I need to differentiate each actions from
> "DemoServer" - correct?
> What I'd like to see, is ability to define a separate route for each method
> in the "DemoServer". Again, it works, but I'm not sure about pros/cons too
> much here :)
> With Restlet, I've had there separate route for each kind of REST requests,
> it was easy to have like that.
>
> So, maybe it's just wrong, maybe not, that's why I'm asking :)
>
> Thank you guys, for any hint.
>
>

Mime
View raw message