I have made up my mind to get rid of WSO2 ESB at my office. It is clumsy, buggy, hard to test, no body wants to work on it and the documentation is horrible. I looked at various alternative and Apache Camel was free and easy to set up and work with me.

To cut the story short, I was able to run most of the example but was struggling with CXF to call a third party service hosted at a random url. The documentation on the website is focused on exposing web service built in Camel. I was finally able to figure this out with a couple of slide show on slideshare.

Here’s the scenario: I have a third party webservice hosted on the web which gives you the the conversion rate between two currencies. I am going to call this web service and log the response.

As usual I will start from scratch. My webservice is hosted at this url –http://www.webservicex.net/CurrencyConvertor.asmx?WSDL. This webservice exposes a operation called – “ConversionRate”.

I am using Fuse Ide(free – Developer version) but you can use Intellij Or Eclipse.

Prerequisites – Must have Maven.

Step 1: Create a new Camel-Spring project.

Step 2:  Add the following dependencies in your pom.xml. “camel-cxf”

<scope><dependency>

      <groupId>org.apache.camel</groupId>

      <artifactId>camel-cxf</artifactId>

      <version>2.10.0.redhat-60024</version>

    </dependency></scope>

My pom.xml looks like this –

<!–?xml version=”1.0″ encoding=”UTF-8″?>

xmlns=”http://maven.apache.org/POM/4.0.0&#8243; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&#8221;>

 

  4.0.0

 

  com.mycompany

  camel-spring

  jar

  1.0.0-SNAPSHOT

  A Camel Spring Route

  http://www.myorganization.org

 

    UTF-8

    UTF-8

 

 

   

      release.fusesource.org

      FuseSource Release Repository

      http://repo.fusesource.com/nexus/content/repositories/releases

     

        false

     

     

        true

     

   

   

      snapshot.fusesource.org

      FuseSource Snapshot Repository

      http://repo.fusesource.com/nexus/content/repositories/snapshots

     

        true

     

     

        false

     

   

 

 

   

      release.fusesource.org

      FuseSource Release Repository

      http://repo.fusesource.com/nexus/content/repositories/releases

     

        false

     

     

        true

     

   

   

      snapshot.fusesource.org

      FuseSource Snapshot Repository

      http://repo.fusesource.com/nexus/content/repositories/snapshots

     

        true

     

     

        false

     

     

 

 

 

   

      org.apache.camel

      camel-core

      2.10.0.redhat-60024

   

   

      org.apache.camel

      camel-spring

      2.10.0.redhat-60024

   

    <!– logging –>

   

      org.slf4j

      slf4j-api

      1.6.6

   

   

      org.slf4j

      slf4j-log4j12

      1.6.6

   

   

      log4j

      log4j

      1.2.17

   

    <!– testing –>

   

      org.apache.camel

      camel-test-spring

      2.10.0.redhat-60024

      test

   

      org.apache.camel

      camel-cxf

      2.10.0.redhat-60024

   

 

 

    install

   

     

        org.apache.maven.plugins

        maven-compiler-plugin

        2.5.1

       

          1.6

          1.6

       

     

     

        org.apache.maven.plugins

        maven-resources-plugin

        2.4.3

       

          UTF-8

       

     

      <!– allows the route to be ran via ‘mvn camel:run’ –>

     

        org.apache.camel

        camel-maven-plugin

        2.10.0.redhat-60024

     

   

 

Step 2: Under src/main.resources/META-INF folder(if not there then create one) create file called camel-context.xml.  Your camel file should like this –

<?xml version=”1.0″ encoding=”UTF-8″?>

xmlns=”http://www.springframework.org/schema/beans&#8221;

        xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;

        xmlns:cxf=”http://camel.apache.org/schema/cxf&#8221;

        xsi:schemaLocation=”

        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

        http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd

        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd&#8221;>

  cxfEndpoint id=”wsdlEndpoint”

                     address=”http://www.webservicex.net/CurrencyConvertor.asmx&#8221;

                     endpointName=”c:SOAPOverHTTP”

                     serviceName=”c:CurrencyConvertor”

                     xmlns:s=”http://www.webserviceX.NET&#8221;/>

  

 

 

        here is a sample which processes the input files

         (leaving them in place – see the ‘noop’ flag)

         then performs content based routing on the message using XPath

        src/data/order?noop=true”/>

       

        wsdl&serviceName={http://www.webserviceX.NET/}CurrencyConvertor&portName={http://www.webserviceX.NET/}CurrencyConvertorSoap&dataFormat=MESSAGE&#8221;/>

         

   

 

Step 4: Place the payload or input data xml in src/data/input/order.xml. The order.xml should like this –

   soapenv:Header/

   soapenv:Body

      web:ConversionRate

         web:FromCurrencyAUD/web:FromCurrency

         web:ToCurrencyUSD/web:ToCurrency

      /web:ConversionRate

   <!–soapenv:Body>–>

<!–soapenv:Envelope>–>

That’s it!!!!

The interesting part is all in the camel-context.xml. Here’s what is happening in this file

src/data/order?noop=true”/>

This line reads the file order.xml. The option noop=true makes the file to be read again and again. By default this values is false. If this value is false, then after one read, camel marks it as read and when you run the example for second time, it will not read this file.

This line will simply log the contents of order.xml.

serviceName={http://www.webserviceX.NET/}CurrencyConvertor&portName={http://www.webserviceX.NET/}CurrencyConvertorSoap&dataFormat=MESSAGE&#8221;/>

 This line tells cxf component that it needs to call the webservice –  http://www.webservicex.net/CurrencyConvertor.asmx?wsdl

-URL – is the url of the wsdl http://www.webservicex.net/CurrencyConvertor.asmx?wsdl

  • serviceName – is the name of the service. Remember it is the name of teh service not the oepration!! The value between {} is the namespace. If you do not want to write {http://….} then add another tag xmlns   – {http://www.webserviceX.NET/}CurrencyConvertor. 
  • portName – is the name of the port.

portName={http://www.webserviceX.NET/}CurrencyConvertorSoap. This is again preceded by {http://…} which is the namespace value. This value is defined in the wsdl as –wsdl:port name=&#8221;CurrencyConvertorSoap&#8221; binding=&#8221;tns:CurrencyConvertorSoap&#8221;

The last piece is dataFormat  – dataFormat=MESSAGE. This tells that the body is of type message.

Part 2 – In production you would want to avoid writing cxf in the above format as it is prone to error because the string value is very long and difficult to test independently and cannot be reused if you want to call the service in another route. So the best way is to define this as cxf endpoint. All you need to do is slighly modify the camel-context.xml. 

  1. Add this(be sure to remove the earlier version of <to uri=”cxf….”)

  1. Define the cxf endpoint called wsdlEndpoint (You call it whatever you want).

cxfEndpoint id=”wsdlEndpoint”

                     address=”http://www.webservicex.net/CurrencyConvertor.asmx&#8221;

                     endpointName=”c:SOAPOverHTTP”

                     serviceName=”c:CurrencyConvertor”

                     xmlns:s=”http://www.webserviceX.NET&#8221;/>

That’s it.

Now just run the app. This will print the following-

[ead #0 – file://src/data/order] route1                         INFO

soapenv:Header/

soapenv:Body

web:ConversionRate

web:FromCurrencyAUD/web:FromCurrency

web:ToCurrencyUSD/web:ToCurrency

/web:ConversionRate

<!–soapenv:Body>–>

<!–soapenv:Envelope>–>

[           default-workqueue-1] route1                         INFO  0.8951

~~~~ Enjoy Cameling ….