Invoking a rest service passing dynamic key value parameters using cxf-rs components - apache-camel

I have to create a Fuse service which would in-turn invoke a REST service exposed by an external service provider. Fuse service will be receiving request in XML format and converting to a query string before invoking the REST service.
Sample request XML for Fuse service -
<CustomerDetails>
<CustomerName>ABC</CustomerName>
<CustomerAge>28</CustomerAge>
<CustomerName>DEF</CustomerName>
<CustomerAge>54</CustomerAge>
<CustomerDetails>
The REST service consumes request in key value params and responds back in XML format.
sample URL:
https://www.customer.com/cust/api/v1/store/abc.xml?Customername=ABC&Customerage=28&Customername=DEF&customerage=54)
I have tried searching a lot but couldn't find any tutorial in the net.
Can someone please provide suggestions on how to implement the fuse service using cxf-rs components (preferably Spring DSL camel configuration )
Thanks in advance..

If you just want to turn the XML request to the url parameter, you can just use jaxb data format to unmarshal the request and use a bean object to setup the URI request parameters. You don't need to use camel-cxf component.
from("direct:start").unmarshal(jaxb).process(new Processor() {
public void process(Exchange exchange) throws Exception {
// get the request object
CustomerDetail request = exchange.getIn().getBody();
// Just mapping the request object into a query parameters.
String query = requestToParameter(request);
exchange.getIn().setHeader(Exchange.HTTP_QUERY, query);
// to remove the body, so http endpoint can send the request with Get Method
exchange.getIn().setBody(null);
}).to("https://www.customer.com/cust/api/v1/store/abc.xml");

Related

Intercept routes without tracing

The application I'm working on is a middleware app that allows routing among tons of applications (mostly SOAP services).
We encountered saturation because of the automatic logs generated by Camel.
The log volume was reduced with the new interceptors. However, if a service is called inside a current route, all I got is the Request Body from the SendToEndpoint interceptor.
Given that all service calls in the application was made that way, I can not change the current routes.
Old interceptors:
getContext().setTracing(true); // <--- trace every step of all routes
interceptFrom().to("log:example");
configureRoutes() {
// route logic
}
New interceptors:
getContext().setTracing(false);
interceptFrom("cxf:*").to("log:example");
interceptSendToEndpoint("cxf:*").to("log:example");
configureRoutes() {
// route logic
}
Example of a route :
from("scheduler endpoint")
.to("DAO method to find the case from database")
.process(//First processor to call the SOAP service)
.to("SOAP endpoint")
.convertBodyTo(SOAP ResponseBody.class) <-- convert the MessageContentsList to SOAP response body generated from the WSDL
.process(//Second processor to check if the response code is OK in the SOAP response body);
How can I implement an interceptor that allows to log also the SOAP response body ?
Thank you for your help.
I dislike to use interceptors to this porpoise, I suggest you to use the EventNotifier interface, you just need to declare it as a bean in camel context and override the notify method.
See: https://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/spi/EventNotifier.html
Here is an usage example: http://camel.apache.org/eventnotifier-to-log-details-about-all-sent-exchanges.html
Note: Camel has some events that you can uss like: CamelContextCreated, ExchangeCreatedEvent, ExchangeSendingEvent, ExchangeSentEvent, ExchangeCompletedEvent, ExchangeFailedEvent, etc.

Intercepting cxf web service header with Apache Camel (Java DSL)

I created a web service client to handle cxf soap web services with apache camel.
String serviceUri = "cxf:http://localhost:10000/myservice?serviceClass=" +
MyRequest.class.getCanonicalName();
from(uri).to("mock:xyz");
The web service receives the soap call but throws an exception since the request requires a handling for wss.
org.apache.cxf.binding.soap.SoapFault: MustUnderstand headers: [{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}Security] are not understood.
The reason is, that the service requires ws security, which can be seen by lloking at the request.
<SOAP-ENV:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" SOAP-ENV:mustUnderstand="1">
I found out that I need to implement an interceptor to handle header properties.
My questions:
How can I add an interceptor to handle the header attributes with Camel Java-DSL?
Will this be sufficient to get rid of the SOAP Fault?
You can do it through
cxfEndpointConfigurer option #see: Camel-CXF configuration
(I use Spring (it is much easier)), but I guess for DSL URI will look like:
String serviceUri = "cxf:http://localhost:10000/myservice?serviceClass=" +
MyRequest.class.getCanonicalName() +
"&cxfEndpointConfigurer="+ MyConfigurer.class.getCanonicalName();
by implementing org.apache.camel.component.cxf.CxfEndpointConfigurer you have ability to add an Interceptor inside configureServer method
server.getEndpoint().getInInterceptors().add(new MyJAASLoginInterceptor());
if you run your Camel in container with JAAS (like JBOSS) you can use extension from
org.apache.cxf.interceptor.security.JAASLoginInterceptor
with needed callback handler.
Simple example which validates user/password from WSS header against JBOSS users:
public class MyJAASLoginInterceptor extends javax.security.auth.callback.JAASLoginInterceptor {
#Override
protected CallbackHandler getCallbackHandler(String name, String password) {
return new org.apache.cxf.interceptor.security.NamePasswordCallbackHandler(name, password, "setCredential");
}
}

camel invoke third party webservice

I am new to the Fuse-camel,cxf.
i wan to invoke third party webservice. i don't want to use wsld2java or serviceclass. I have a wsdl.
Here is the requirement to make generic webservice call
json request data-->generate soap request --> cxf:endpoint in PAYLOAD format-->soap response -->json response data to client.
1 . how do i convert json to soaprequest(xml) and vice-versa ( Marshall-format-soapjxab is expecting jaxb annotated classes)
2.how do I call in soap in payload mode..
any help (link/example) is greatly appreciated.
Thanks,
Narendra
You can use Camel CXFRS to set up rest endpoints.
On parsing the JSON, set the values to JAXB annotated POJO's.
Then use ProducerTemplate to send SOAP request to third party service.
On receiving the response you can unmarshal it, either using JAXB unmarshaller in java code or incase of DSL use Camel JAXB DataFormat
Route the response to the client by setting the content in camel exchange.

Http request and response lost after receiving Response from Web Service?

I have an Apache camel application which talks with a web service. This is purely a integration(mediation) application. We take REST request and transform it to a SOAP message (using VM templates) and call the web service. Receive response from web service, transform it to JSON and send back to our client.
REST ---->transform to SOAP req (Velocity template) ---->call WS ---->receive response---->transform into JSON---->return response to caller.
We are using servlet endpoint to receive request from our client. We can obtain HttpSession object from exchange before calling web service as follows :
HttpServletRequest req = exchange.getIn().getBody(HttpServletRequest.class);
HttpSession session = req.getSession();
However, the problem is that I cannot obtain HTTPSession from exchange after receiving response from web service. If I check the Exchange object in debug mode, the Exchange.getIn() is of type DefaultMessage rather than HttpMessage. That is the reason I think I loose Request and response objects.
I tried setting the exchange pattern to InOut but that doesn’t help.
The only solution I could find is to store the original body of the in message in a header or a property and retrieve it at the end. But I think there must be a better solution that this.
Could anybody help please?
Note: We need HttpSession so that we can store corresponding session information like session id created on WS for the session created by our request. We cannot pass session information created on WS to our callers, and need a place on our application to hold this mapping info. HttpSession serves this requirement. Is there any better way?
You can store the http session as an exchange property, camel copy these properties across the exchanges, so you can access it in the route when you need.

Route Webservice response to a POJO without implementing any camel specific interface

I am routing my webservice request to a bean which sends the response back to the service.
<camel:from uri="cxf:bean:authTest" />
<camel:to uri="bean:routeExitResponseProcessor"/>
Now in the bean class I have to implement Processor interface, access the Exchange object , call the implementation method and then send the response back to the client by setting the response object to exchange's body.
Can I get rid of all the Camel specific java code and configure everything in my applicationContext.xml?
If you use the bean component you do not have to implement the Processor interface.
If your class simply has one public method then it will be called and camel will try to convert the incoming body to your parameter and process the return as new body.
Try with a method like:
WebServiceResult myMethod(WebServiceInput input) {...}
Where the Parameters are those generated from the wsdl.
Christian

Resources