The proxying of requests through to backend services is a common use case for Camel. Decoupling the web service client from the backend service allows you to more easily move or change the backend, as you only need to update the proxy code, as opposed to all of the client systems that would otherwise use the backend directly. This technique is known as endpoint virtualization.
A proxy may also be used to impose a security or auditing layer, for use cases such as exposing the original service to new types of clients, for example, ones external to your company.
This recipe will show you the basics of creating a simple web service proxy in Camel.
This recipe assumes that you have a project with JAX-WS artifacts created as described in the Generating the service stubs from a WSDL recipe. To use the generated API, you need to include a dependency to that project in your build:
<dependency> <groupId>org.camelcookbook.examples</groupId> <artifactId>ws-payments-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
This recipe's example is based on paymentService.wsdl
. For this example, we are assuming that the proxy and backend service have identical WSDL interfaces. If they were different, you would need to generate the JAX-WS artifacts for both WSDLs in separate projects.
All source files for this recipe are located in the ws-camel-routes
project in the camel-cookbook-web-services
module. The Java code for this recipe is located in the org.camelcookbook.ws.proxy
package. The Spring XML files are located under src/main/resources/META-INF/spring
and prefixed with proxy
.
There are two main steps to this recipe: configure the frontend and backend Camel CXF endpoints, and specify a route from one to the other.
In the XML DSL, within the Spring beans
element, configure two cxfEndpoint
s; one for the frontend proxy, and the other for the backend service:
<cxf:cxfEndpoint id="paymentServiceProxy" address="http://host1:port1/paymentService" serviceClass="org.camelcookbook.ws.payment_service.Payment"/> <cxf:cxfEndpoint id="paymentServiceBackend" address="http://host2:port2/paymentService" serviceClass="org.camelcookbook.ws.payment_service.Payment"/>
In the Java DSL, we create endpoint URI strings for each of the endpoints:
final String paymentServiceProxyUri = "cxf:http://host1:port1/paymentService" + "?serviceClass=" + Payment.class.getCanonicalName()); final String paymentServiceBackendUri = "cxf:http://host2:port2/paymentService" + "?serviceClass=" + Payment.class.getCanonicalName());
In the XML DSL, this is defined as:
<route id="wsProxy"> <from uri= "cxf:bean:paymentServiceProxy?dataFormat=PAYLOAD"/> <log message="request = ${body}"/> <to uri= "cxf:bean:paymentServiceBackend?dataFormat=PAYLOAD"/> <log message="response = ${body}"/> </route>
In the Java DSL, the same route is expressed as:
from(paymentServiceProxyUri + "&dataFormat=PAYLOAD") .id("wsProxy") .log("request = ${body}") .to(paymentServiceBackendUri + "&dataFormat=PAYLOAD") .log("response = ${body}");
This recipe is effectively combining two previous recipes; the Invoking a remote web service from Camel recipe, and the Implementing a web service with a Camel route recipe into one with the difference being that the Camel route does not process the message, but rather relays it to the backend service.
Our recipe's example assumes that both frontend and backend services have identical WSDL interfaces. If they are different, you can update the endpoint configuration appropriately, specifically setting the serviceClass
option to reference the correct JAX-WS WebService
artifact. You can then perform any necessary transformations of the body in your proxy Camel route in order to bridge the two interfaces.
You may also need to remove or modify certain exchange headers, as headers set by Camel CXF from the consuming (from
) endpoint may interfere with the behavior of the producing endpoint by overriding the default behavior specified by the endpoint URI. For example, if your backend has a different operation name from that of the proxy web service, you would need to update the operationName
header before invoking the backend service.
You can explicitly add an Error Handler to allow you to specify redelivery settings. Redelivery can be useful to deal with situations such as your backend service becoming temporarily unavailable due to normal maintenance or an upgrade. Camel can attempt to redeliver the message after a delay providing the appearance of continuous availability.
3.144.19.243