Orchestration on Talend ESB using Apache Camel & Apache CXF

Orchestration is a key feature of every modern ESB. According to wikipedia, the definition goes:

Orchestration is the automated arrangement, coordination, and management of computer systems, middleware, and services


When we are talking about SOA, Orchestration means usually to simplify multiple webservice calls  which may or may not depend on each other  behind an easy-to-use facade. Since the CXF Example Catalog purely focuses on the technical side, not on high level patterns, I decided to create a simple, sequential showcase on my own.



The service we want to build exposes a facade. For a given IP Address, a “localized” price will be returned. In the background, the route calls one service to find the location for a given IP and another for the currency for said location. This is just a basic example to illustrate how orchestration can be achieved.



The implementation is based on Apache Camel, Apache CXF and Spring. Apache CXF offers a wide range of webservice-related functionality and is fully integrated (There is a Camel-CXF Component) into Apache Camel. There are also alternative Camel Modules, which usually are not that feature-rich in comparison to Apache CXF (See: http://camel.apache.org/spring-web-services.html, http://camel.apache.org/restlet.html and http://camel.apache.org/rest.html).

The initial boilerplate was taken from the Camel-Examples on Github.

Lets have a look into the code: beans.xml

<cxf:cxfEndpoint id="targetGeoIpService" address="http://www.webservicex.net/geoipservice.asmx"
        endpointName="s:GeoIPServiceSoap" serviceName="s:GeoIPService"
        wsdlURL="wsdl/geoipservice.wsdl" serviceClass="net.wsip.GeoIPServiceSoap"
            <entry key="dataFormat" value="POJO" />
            <bean class="org.apache.cxf.transport.common.gzip.GZIPFeature" />

For every webserice which we have to consume during our orchestration case, we define a target endpoint in spring. Later on, in our route-definition, we then reference said service:

<camelContext xmlns="http://camel.apache.org/schema/spring">
            <from uri="cxf:bean:proxyLocalizedPriceService" /> <!-- Definition of Provider-Endpoint (inbound) -->
            <process ref="pGeoPrice2GeoIP" /> <!-- Transformation (see further details below) -->
            <to uri="cxf:bean:targetGeoIpService" /> <!-- Definition of Consumer Endpoint (GeoIpService, outbound) -->
            <process ref="pGeoIP2Country" /> <!-- Transformation (see further details below) -->
            <to uri="cxf:bean:targetCountryService" /> <!-- Definition of Consumer Endpoint (CountryService, outbound) -->
            <process ref="pCountry2GeoPriceResponse" /> <!-- Transformation to LocalizedPriceService Response) -->

Between the endpoints we transform the message so that target endpoint understands it. Last but not least, we do a transformation in the expected response format. Camel handles everything else for us.

Lets have a look into camel processors:

The Processor interface is used to implement consumers of message exchanges or to implement a Message Translator

The transformation is fairly simple. As one can see in the GeoIP2Country class:

public class GeoIP2Country implements Processor {
       public void process(Exchange ex) throws Exception {
           MessageContentsList msgList = (MessageContentsList) ex.getIn().getBody();
           GeoIP geoIPs = (GeoIP) msgList.get(0); // Get GeoIP Object (which was returned by previous call)
           ex.getIn().setHeader(CxfConstants.OPERATION_NAME, "GetCurrencyByCountry"); // What operation to call on next endpoint
           ex.getIn().setHeader(CxfConstants.OPERATION_NAMESPACE, "http://www.webserviceX.NET"); // Update Namespace to match expected.

           String geoIP = geoIPs.getCountryName(); // Define expected (by next endpoint) payload 

The operation which we call on the “Country” webservice only expects a single parameter; The country name. This means we need to extract the returned country which was returned by the previous webservice call and put it into the message body.

For details, I highly recommend the offical documentation.


The route is tested and built for the – at the time of this writing – most recent Talend ESB (6.1.1) version. Talend ESB is a Karaf based OSGi Container with a bunch of pre-installed packages. After successfull deployment, the the webservice will be provided on the preconfigured Talend ESB CXF Endpoint. (Default is 8040)


Since it is required to access and interpret the payload of every involved service, the java sources need to be generated out of the pre existing WSDL File. To see how this can be done, have a look into the projects pom file.


my learnings during this proof of concept are the following:

  • If you run into issues regarding namespaces, try to use the -xjc-npa argument. I personally had the problem that elementFormDefault was not adhered.
  • Always use one seperate java package per WSDL. Even if the WSDL uses the same namspace. This can be accomplished using the -p argument:

The full projects is available on github: https://github.com/aymenfurter/camel-cxf-osgi-orchestration. If you have any questions or for the case you run into any issues, let me know in the comments or on twitter.