Camel cxfrs proxy response

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Camel cxfrs proxy response

hoomanb
This post was updated on .
Hi,

I have exposed a cxfrs endpoint as my proxy rest service, once getting the request I'm calling two soap web services and getting the respond back from those service, in this process I'm using camel aggregator to aggregate the response results coming back from the soap calls, now up to here everything works as expected, the issue I'm facing is I have problem returning the response back to the rest client, so here's my route config:

<cxf:rsServer id="rsServer" address="http://localhost:9002/route"
                serviceClass="com.MyController"
                loggingFeatureEnabled="true" loggingSizeLimit="20">
                <cxf:providers>
                        <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
                </cxf:providers>
        </cxf:rsServer>

<bean id="requestProcessing" class="com.RequestProcessing" />

<camelContext trace="true" xmlns="http://camel.apache.org/schema/blueprint">
         <routeBuilder ref="requestProcessing" />
</camelContext>

Here's com.MyController:

@GET
        @Path("/{objectId}")
        @Produces(MediaType.APPLICATION_JSON)
        public List<MyObjectList> getMyObject(@PathParam("objectId") String objectId) {
                return null;

        }

and here's the RequestProcessing class:

from(Constants.REST_ENDPOINT)
                .routeId(getClass().getName())
                .log("Entering the route...")
                .process(new EndpointProcessorManager())
                .removeHeaders("CamelHttp*")
                .multicast()
                .parallelProcessing()
                .to(Constants.DIRECT_ENDPOINT_ONE)
                .to(Constants.DIRECT_ENDPOINT_TWO);

from(Constants.DIRECT_ENDPOINT_ONE).process(new AddingOperationNameAndOperationNameSpace_FIRST_ENDPOINT()).to(FIRST_SOAP_ENDPOINT).to(Constants.DIRECT_AGGREGATE_ENDPOINT);
from(Constants.DIRECT_ENDPOINT_TWO).process(new AddingOperationNameAndOperationNameSpace_SECOND_ENDPOINT()).to(SECOND_SOAP_ENDPOINT).to(Constants.DIRECT_AGGREGATE_ENDPOINT);

from(Constants.DIRECT_AGGREGATE_ENDPOINT)
                .aggregate(constant(true), new GroupedExchangeAggregationStrategy())
                .completionSize(2)
                 setBody(exchangeProperty(Exchange.GROUPED_EXCHANGE))
                .process(new FinalTestProcessor())                                                                   [1]
                .bean(new ProcessJsonResponse(), "processBody")                                           [2]
                .marshal(new JsonDataFormat(JsonLibrary.Jackson));

so in line [1] FinalTestProcessor processes the results from the web service calls to extract the desired result as a list of objects say for example: exchange.getIn().setBody(MyObjectList) .
in line [2] I'm basically returning this result list as follows:

return Response.status(Status.OK).entity(MyObjectList).build();

With this config all the calls and everything works but I can't seem to get the json respond that I need back to the REST caller.

Any help would be appreciated on this.
Reply | Threaded
Open this post in threaded view
|

Re: Camel cxfrs proxy response

Sergey Beryozkin
Hi

May be following this thread:

http://camel.465427.n5.nabble.com/How-to-access-payload-from-REST-404-reply-in-cxfrs-td5773325.html

can help ?

Cheers, Sergey

On 07/12/15 07:31, hoomanb wrote:

> Hi,
>
> I have exposed a cxfrs endpoint as my proxy rest service, once getting the
> request I'm calling two soap web services and getting the respond back from
> those service, in this process I'm using camel aggregator to aggregate the
> response results coming back from the soap calls, now up to here everything
> works as expected, the issue I'm facing is I have problem returning the
> response back to the rest client, so here's my route config:
>
> <cxf:rsServer id="rsServer" address="http://localhost:9002/route"
> serviceClass="com.MyController"
> loggingFeatureEnabled="true" loggingSizeLimit="20">
> <cxf:providers>
> <bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
> </cxf:providers>
> </cxf:rsServer>
>
> <bean id="requestProcessing" class="com.RequestProcessing" />
>
> <camelContext trace="true" xmlns="http://camel.apache.org/schema/blueprint">
>           <routeBuilder ref="requestProcessing" />
> </camelContext>
>
> Here's com.MyController:
>
> @GET
> @Path("/{objectId}")
> @Produces(MediaType.APPLICATION_JSON)
> public List<MyObjectList> getMyObject(@PathParam("objectId") String
> objectId) {
> return null;
>
> }
>
> and here's the RequestProcessing class:
>
> from(Constants.REST_ENDPOINT)
> .routeId(getClass().getName())
> .log("Entering the route...")
> .process(new EndpointProcessorManager())
> .removeHeaders("CamelHttp*")
> .multicast()
> .parallelProcessing()
> .to(Constants.DIRECT_ENDPOINT_ONE)
> .to(Constants.DIRECT_ENDPOINT_TWO);
>
> from(Constants.DIRECT_ENDPOINT_ONE).process(new
> SupplierEnricherProcessor()).to(FIRST_SOAP_ENDPOINT).to(Constants.DIRECT_AGGREGATE_ENDPOINT);
> from(Constants.DIRECT_ENDPOINT_TWO).process(new
> GenericNAICSEnricherProcessor()).to(SECOND_SOAP_ENDPOINT).to(Constants.DIRECT_AGGREGATE_ENDPOINT);
>
> from(Constants.DIRECT_AGGREGATE_ENDPOINT)
> .aggregate(constant(true), new GroupedExchangeAggregationStrategy())
> .completionSize(2)
>                   setBody(exchangeProperty(Exchange.GROUPED_EXCHANGE))
> .process(new FinalTestProcessor())
> [1]
> .bean(new ProcessJsonResponse(), "processBody")
> [2]
> .marshal(new JsonDataFormat(JsonLibrary.Jackson));
>
> so in line [1] FinalTestProcessor processes the results from the web service
> calls to extract the desired result as a list of objects say for example:
> exchange.getIn().setBody(MyObjectList) .
> in line [2] I'm basically returning this result list as follows:
>
> return Response.status(Status.OK).entity(MyObjectList).build();
>
> With this config all the calls and everything works but I can't seem to get
> the json respond that I need back to the REST caller.
>
> Any help would be appreciated on this.
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-cxfrs-proxy-response-tp5774775.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>


--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/
Reply | Threaded
Open this post in threaded view
|

Re: Camel cxfrs proxy response

hoomanb
Hi Sergey,

Thanks for your reply on this, on the link that you have mentioned the solution appears to be setting the Response return type for the the controller, however this doesn't seem to work in my case. In

.bean(new ProcessJsonResponse(), "processBody")

I'm basically returning the result as Response object:

return Response.status(Status.OK).entity(MyObjectList).build();

additionally I thought I might change the return type of my controller as well:

@GET
        @Path("/{objectId}")
        @Produces(MediaType.APPLICATION_JSON)
        public Response getMyObject(@PathParam("objectId") String objectId) {
                return null;

        }

I'm receiving the 200 Response back but the result is null. When I debug this in unit test I'll see this:

Response.status(Status.OK).entity(MyObjectList).build();

contains the result. Deploying the solution into fuse and hitting the REST service only seems to return headers:

12:20:20,663 | INFO  | qtp790919676-179 | LoggingOutInterceptor            | 118 - org.apache.cxf.cxf-core - xxx | Outbound Message
---------------------------
ID: 4
Response-Code: 200
Content-Type:
Headers: {operationNamespace=[xxx], Host=[localhost:9002], breadcrumbId=[ID-xxx-50363-1449711439513-3-1], User-Agent=[curl/7.27.0], objectId=[xxx], X-Powered-By=[ASP.NET], Server=[Microsoft-IIS/7.0], Cache-Control=[private, max-age=0], X-AspNet-Version=[4.0.30319], ResponseContext=[{xxx, org.apache.cxf.service.model.MessageInfo=[MessageInfo OUTPUT: {xxx], schema-validation-enabled=NONE, org.apache.cxf.client=true, org.apache.cxf.message.inbound=true, org.apache.cxf.message.Message.PROTOCOL_HEADERS={Cache-Control=[private, max-age=0], Content-Length=[1559], content-type=[text/xml; charset=utf-8], Date=[Thu, 10 Dec 2015 02:20:15 GMT], Server=[Microsoft-IIS/7.0], X-AspNet-Version=[4.0.30319], X-Powered-By=[ASP.NET]}, org.apache.cxf.interceptor.LoggingMessage.ID=6, javax.xml.ws.wsdl.service={xxx, org.apache.cxf.binding.soap.SoapVersion=org.apache.cxf.binding.soap.Soap11@62090db0, org.apache.cxf.message.Message.ENCODING=UTF-8, javax.xml.ws.wsdl.interface={xxx, javax.xml.ws.wsdl.operation={xxx}xxx, javax.xml.ws.wsdl.description=xxx?wsdl, org.apache.cxf.service.model.BindingMessageInfo=org.apache.cxf.service.model.BindingMessageInfo@138eb4b0, Content-Type=text/xml; charset=utf-8, org.apache.cxf.headers.Header.list=[], org.apache.cxf.message.Message.RESPONSE_CODE=200}], Date=[Thu, 10 Dec 2015 02:20:15 GMT], SOAPAction=[xxx], Accept=[application/json], org.apache.cxf.headers.Header.list=[[]], Content-Length=[0]}

please correct me if I misunderstood you.

Thanks
Hooman
Reply | Threaded
Open this post in threaded view
|

Re: Camel cxfrs proxy response

Sergey Beryozkin
Hi

Unfortunately I'm very busy right now with the other project so I can't
help with investigating, can you please get Camel source and trace what
is happening ?
It looks like the body is consumed somehow after a CXFRS call returns,
may be the stream is cached, etc... Let us know if you can get to the
bottom of it...
The only comment I can make is that in newer Camel releases one does not
have to type no-op method implementations and having the interface or
even or CXF specific model is sufficient, with RST DSL work pending to
be completed a bit later on. This is not relevant to this issue though...

Thanks, Sergey

On 10/12/15 02:46, hoomanb wrote:

> Hi Sergey,
>
> Thanks for your reply on this, on the link that you have mentioned the
> solution appears to be setting the Response return type for the the
> controller, however this doesn't seem to work in my case. In
>
> .bean(new ProcessJsonResponse(), "processBody")
>
> I'm basically returning the result as Response object:
>
> return Response.status(Status.OK).entity(MyObjectList).build();
>
> additionally I thought I might change the return type of my controller as
> well:
>
> @GET
>          @Path("/{objectId}")
>          @Produces(MediaType.APPLICATION_JSON)
>          public Response getMyObject(@PathParam("objectId") String objectId)
> {
>                  return null;
>
>          }
>
> I'm receiving the 200 Response back but the result is null. When I debug
> this in unit test I'll see this:
>
> Response.status(Status.OK).entity(MyObjectList).build();
>
> contains the result. Deploying the solution into fuse and hitting the REST
> service only seems to return headers:
>
> 12:20:20,663 | INFO  | qtp790919676-179 | LoggingOutInterceptor            |
> 118 - org.apache.cxf.cxf-core - xxx | Outbound Message
> ---------------------------
> ID: 4
> Response-Code: 200
> Content-Type:
> Headers: {operationNamespace=[xxx], Host=[localhost:9002],
> breadcrumbId=[ID-xxx-50363-1449711439513-3-1], User-Agent=[curl/7.27.0],
> objectId=[xxx], X-Powered-By=[ASP.NET], Server=[Microsoft-IIS/7.0],
> Cache-Control=[private, max-age=0], X-AspNet-Version=[4.0.30319],
> ResponseContext=[{xxx, org.apache.cxf.service.model.MessageInfo=[MessageInfo
> OUTPUT: {xxx], schema-validation-enabled=NONE, org.apache.cxf.client=true,
> org.apache.cxf.message.inbound=true,
> org.apache.cxf.message.Message.PROTOCOL_HEADERS={Cache-Control=[private,
> max-age=0], Content-Length=[1559], content-type=[text/xml; charset=utf-8],
> Date=[Thu, 10 Dec 2015 02:20:15 GMT], Server=[Microsoft-IIS/7.0],
> X-AspNet-Version=[4.0.30319], X-Powered-By=[ASP.NET]},
> org.apache.cxf.interceptor.LoggingMessage.ID=6,
> javax.xml.ws.wsdl.service={xxx,
> org.apache.cxf.binding.soap.SoapVersion=org.apache.cxf.binding.soap.Soap11@62090db0,
> org.apache.cxf.message.Message.ENCODING=UTF-8,
> javax.xml.ws.wsdl.interface={xxx, javax.xml.ws.wsdl.operation={xxx}xxx,
> javax.xml.ws.wsdl.description=xxx?wsdl,
> org.apache.cxf.service.model.BindingMessageInfo=org.apache.cxf.service.model.BindingMessageInfo@138eb4b0,
> Content-Type=text/xml; charset=utf-8, org.apache.cxf.headers.Header.list=[],
> org.apache.cxf.message.Message.RESPONSE_CODE=200}], Date=[Thu, 10 Dec 2015
> 02:20:15 GMT], SOAPAction=[xxx], Accept=[application/json],
> org.apache.cxf.headers.Header.list=[[]], Content-Length=[0]}
>
> please correct me if I misunderstood you.
>
> Thanks
> Hooman
>
>
>
>
> --
> View this message in context: http://camel.465427.n5.nabble.com/Camel-cxfrs-proxy-response-tp5774775p5774883.html
> Sent from the Camel - Users mailing list archive at Nabble.com.
>


--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/
Reply | Threaded
Open this post in threaded view
|

Re: Camel cxfrs proxy response

hoomanb
Thanks Sergey,

I did further digging into this and it turns out that using aggregate to aggregate all the results creates a new exchange, so that's why the result of the response was null, so I modified the route and pretty much used the GroupedExchangeAggregationStrategy logic so the route becomes like the following:

from(Constants.REST_ENDPOINT)
                .routeId(getClass().getName())
                .log("Entering the route...")
                .removeHeaders("CamelHttp*")
                .to(Constants.DIRECT_ENDPOINT_ONE)
                .to(Constants.DIRECT_ENDPOINT_TWO);

from(Constants.DIRECT_ENDPOINT_ONE).process(new AddingOperationNameAndOperationNameSpace_FIRST_ENDPOINT()).to(FIRST_SOAP_ENDPOINT)
.process(new FirstResultHolder()).to(Constants.DIRECT_AGGREGATE_ENDPOINT);

from(Constants.DIRECT_ENDPOINT_TWO).process(new AddingOperationNameAndOperationNameSpace_SECOND_ENDPOINT())
.process(new SecondResultHolder()).to(Constants.DIRECT_AGGREGATE_ENDPOINT);

from(Constants.DIRECT_AGGREGATE_ENDPOINT)
.process(new ResultExtractorProcessor())
.bean(new ProcessJsonResponse(), "processBody");

and the key is FirstResultHolder and ResultExtractorProcessor where I hold the exchange result coming from the web services as an Exchange property and process the result as a Json.

This seems to work however there's a bit of latency involves as it does not use the parallel processing.