A Morsel Of Code

One byte at a time

Apache Camel : How to call java webservice

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. 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.

There are two ways to call this webservice, a) Using

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”

<dependency>

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

      <artifactId>camel-cxf</artifactId>

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

    </dependency>

My pom.xml looks like this -

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

xmlns=”http://maven.apache.org/POM/4.0.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd”>

 

  <modelVersion>4.0.0</modelVersion>

 

  <groupId>com.mycompany</groupId>

  <artifactId>camel-spring</artifactId>

  <packaging>jar</packaging>

  <version>1.0.0-SNAPSHOT</version>

  <name>A Camel Spring Route</name>

  <url>http://www.myorganization.org</url>

  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

  </properties>

  <repositories>

    <repository>

      <id>release.fusesource.org</id>

      FuseSource Release Repository

      <url>http://repo.fusesource.com/nexus/content/repositories/releases</url>

      <snapshots>

        <enabled>false</enabled>

      </snapshots>

      <releases>

        <enabled>true</enabled>

      </releases>

    </repository>

    <repository>

      <id>snapshot.fusesource.org</id>

      FuseSource Snapshot Repository

      <url>http://repo.fusesource.com/nexus/content/repositories/snapshots</url>

      <snapshots>

        <enabled>true</enabled>

      </snapshots>

      <releases>

        <enabled>false</enabled>

      </releases>

    </repository>

  </repositories>

  <pluginRepositories>

    <pluginRepository>

      <id>release.fusesource.org</id>

      FuseSource Release Repository

      <url>http://repo.fusesource.com/nexus/content/repositories/releases</url>

      <snapshots>

        <enabled>false</enabled>

      </snapshots>

      <releases>

        <enabled>true</enabled>

      </releases>

    </pluginRepository>

    <pluginRepository>

      <id>snapshot.fusesource.org</id>

      FuseSource Snapshot Repository

      <url>http://repo.fusesource.com/nexus/content/repositories/snapshots</url>

      <snapshots>

        <enabled>true</enabled>

      </snapshots>

      <releases>

        <enabled>false</enabled>

      </releases>

    </pluginRepository>  

  </pluginRepositories>

 

  <dependencies>

    <dependency>

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

      <artifactId>camel-core</artifactId>

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

    </dependency>

    <dependency>

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

      <artifactId>camel-spring</artifactId>

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

    </dependency>

    <!– logging –>

    <dependency>

      <groupId>org.slf4j</groupId>

      <artifactId>slf4j-api</artifactId>

      <version>1.6.6</version>

    </dependency>

    <dependency>

      <groupId>org.slf4j</groupId>

      <artifactId>slf4j-log4j12</artifactId>

      <version>1.6.6</version>

    </dependency>

    <dependency>

      <groupId>log4j</groupId>

      <artifactId>log4j</artifactId>

      <version>1.2.17</version>

    </dependency>

    <!– testing –>

    <dependency>

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

      <artifactId>camel-test-spring</artifactId>

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

      <scope>test</scope>

    </dependency>

<dependency>

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

      <artifactId>camel-cxf</artifactId>

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

    </dependency>

  </dependencies>

  <build>

    <defaultGoal>install</defaultGoal>

    <plugins>

      <plugin>

        <groupId>org.apache.maven.plugins</groupId>

        <artifactId>maven-compiler-plugin</artifactId>

        <version>2.5.1</version>

        <configuration>

          <source>1.6</source>

          <target>1.6</target>

        </configuration>

      </plugin>

      <plugin>

        <groupId>org.apache.maven.plugins</groupId>

        <artifactId>maven-resources-plugin</artifactId>

        <version>2.4.3</version>

        <configuration>

          <encoding>UTF-8</encoding>

        </configuration>

      </plugin>

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

      <plugin>

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

        <artifactId>camel-maven-plugin</artifactId>

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

      </plugin>

    </plugins>

  </build>

</project>

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”

        xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”

        xmlns:cxf=”http://camel.apache.org/schema/cxf”

        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”>

  <cxf:cxfEndpoint id=”wsdlEndpoint”

                     address=”http://www.webservicex.net/CurrencyConvertor.asmx”

                     endpointName=”c:SOAPOverHTTP”

                     serviceName=”c:CurrencyConvertor”

                     xmlns:s=”http://www.webserviceX.NET”/>

  

  <camelContext xmlns=”http://camel.apache.org/schema/spring”>

  <route>

        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</description>

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

        <log message=”${body}”/>

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

         <log message=”${body}”/>

    </route>

</camelContext>

 

</beans>

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

<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:web=”http://www.webserviceX.NET/”>

   <soapenv:Header/>

   <soapenv:Body>

      <web:ConversionRate>

         <web:FromCurrency>AUD</web:FromCurrency>

         <web:ToCurrency>USD</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.

<log message=”${body}”/>

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

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

 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=”CurrencyConvertorSoap” binding=”tns:CurrencyConvertorSoap”>

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….”)

<to uri=”cxf:bean:wsdlEndpoint?dataFormat=MESSAGE”/>

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

<cxf:cxfEndpoint id=”wsdlEndpoint”

                     address=”http://www.webservicex.net/CurrencyConvertor.asmx”

                     endpointName=”c:SOAPOverHTTP”

                     serviceName=”c:CurrencyConvertor”

                     xmlns:s=”http://www.webserviceX.NET”/>

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:FromCurrency>AUD</web:FromCurrency>

<web:ToCurrency>USD</web:ToCurrency>

</web:ConversionRate>

<!–soapenv:Body>–>

<!–soapenv:Envelope>–>

[           default-workqueue-1] route1                         INFO  0.8951

~~~~ Enjoy Cameling ….

2 comments for “Apache Camel : How to call java webservice

  1. January 23, 2014 at 12:18 pm

    code is not readable. use SyntaxHighlighter

    • January 24, 2014 at 1:32 am

      Sorry.. I am porting my blog to wordpress.org and will fix it after the port.

Drop a line or say Hi!