Proxy Web Services request with JBoss Fuse

In this tutorial we will learn how to provide a Web service facade using a Came blueprint project which proxies request to a legacy web service.

This is the second tutorial about Camel and Web services – here you can read the first part: Proxy Web Services request with Camel  where we have covered this scenario:

The scenario we will discuss in this tutorial is the same, just we will turn the project in a blueprint project and deploy it on JBoss Fuse 6.Here is the blueprint for our project:

<?xml version="1.0" encoding="UTF-8"?> <blueprint     xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:camelcxf="http://camel.apache.org/schema/blueprint/cxf"     xmlns:cxf="http://cxf.apache.org/blueprint/core"     xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd              http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd              http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd              http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">    <cxf:bus><!-- interceptor per request/response del ws/rest -->     <cxf:features>       <cxf:logging limit="1024"/>     </cxf:features>   </cxf:bus>   <bean id="beanAdapter" class="com.sample.source.ws.BeanAdapter"/>    <!-- WEB SERVICE FACADE -->   <camelcxf:cxfEndpoint id="input-cxf" address="http://localhost:9080/example-input-cxf/"                         serviceClass="com.sample.source.ws.FuseExampleCXF"/>    <!-- TARGET WEB SERVICE -->   <camelcxf:cxfEndpoint id="SimpleWebSevice"         address="http://localhost:8080/webserviceslegacy/LegacyWebServiceImpl"                      wsdlURL="http://localhost:8080/webserviceslegacy/LegacyWebServiceImpl?wsdl"                                         serviceClass="com.sample.target.ws.LegacyWebService" />     <camelContext id="example-cxf" xmlns="http://camel.apache.org/schema/blueprint">     <route id="input-cxf">       <from uri="cxf:bean:input-cxf"/>       <transform>         <simple>           ${in.body[0]}         </simple>       </transform>       <log message="Message input: ${in.body}"/>       <transform>                 <method bean="beanAdapter" method="transform"  />       </transform>                    <removeHeaders pattern="*"/>         <to uri="cxf:bean:SimpleWebSevice" />       </route>   </camelContext>  </blueprint> 

So, the first Web service (input-cxf) is just a Contract exposed through the Camel route. It just contains an interface definition or a WSDL. In our case, it is composed of a Web interface:

package com.sample.source.ws;

import com.sample.source.bean.Wrapper;
import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface FuseExampleCXF {
  @WebMethod
  int count(Wrapper wrapper);
}

This Web service has the count method which receives as input a Wrapper Object. The use case is providing a compatibility facade to Web service clients that use this interface and adapt the parameter using a Bean Transformation. The class which is in charge to perform the transformation is the com.sample.source.ws.BeanAdapter class which follows here:

package com.sample.source.ws;

import com.sample.target.bean.Struct;
import com.sample.source.bean.Wrapper;
import org.apache.camel.Exchange;

public class BeanAdapter {
  public Struct transform(Wrapper input) {
    Struct struct = new Struct();
    struct.setX(input.getA());
    struct.setY(input.getB());
    return struct;
  }
}

This class will be in charge to transform the Wrapper class from the incoming Web service into the Struct class which is expected by the target Web service:

package com.sample.target.ws;

import com.sample.target.bean.Struct;
import javax.jws.*;

@WebService
public interface LegacyWebService {
  @WebMethod
  public int callStruct(@WebParam(name = "total") Struct s);
}

The Web service is deployed on an external middleware, such as JBoss EAP with the following implementation:

package com.sample.target.ws;

import com.sample.target.bean.Struct;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;

@WebService
public class LegacyWebServiceImpl implements LegacyWebService {
  @WebMethod
  public int callStruct(@WebParam(name = "struct") Struct s) {
    System.out.println("Invoked Web service with " + s.getX() + " and " + s.getY());
    return s.getX() + s.getY();
  }
}

In order to build the OSGI bundle you can use the following pom.xml :

<project 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/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>      <groupId>it.fuse.demo</groupId>     <artifactId>fuse-demo</artifactId>     <packaging>bundle</packaging>     <name>Fuse :: Demo</name>     <version>0.0.3-SNAPSHOT</version>      <properties>         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>         <maven.compiler.target>1.7</maven.compiler.target>         <maven.compiler.source>1.7</maven.compiler.source>          <camel.version>2.15.1.redhat-620133</camel.version>         <fabric8.version>1.2.0.redhat-133</fabric8.version>         <karaf.enterprise.version>2.4.0.redhat-620133</karaf.enterprise.version>         <jboss.fuse.bom.version>6.2.0.redhat-133</jboss.fuse.bom.version>         <maven.bundle.plugin.version>2.5.3</maven.bundle.plugin.version>     </properties>     <dependencyManagement>         <dependencies>             <dependency>                 <groupId>org.jboss.fuse.bom</groupId>                 <artifactId>jboss-fuse-parent</artifactId>                 <version>${jboss.fuse.bom.version}</version>                 <type>pom</type>                 <scope>import</scope>             </dependency>         </dependencies>     </dependencyManagement>        <dependencies>         <dependency>             <groupId>org.apache.camel</groupId>             <artifactId>camel-blueprint</artifactId>         </dependency>          <dependency>             <groupId>org.apache.camel</groupId>             <artifactId>camel-cxf</artifactId>         </dependency>          <dependency>             <groupId>org.apache.servicemix.specs</groupId>             <artifactId>org.apache.servicemix.specs.jaxws-api-2.2</artifactId>         </dependency>          <dependency>             <groupId>org.apache.cxf</groupId>             <artifactId>cxf-rt-frontend-jaxrs</artifactId>         </dependency>           <dependency>             <groupId>org.slf4j</groupId>             <artifactId>slf4j-api</artifactId>         </dependency>         <dependency>             <groupId>org.slf4j</groupId>             <artifactId>slf4j-log4j12</artifactId>             <scope>test</scope>         </dependency>     </dependencies>      <build>         <plugins>             <plugin>                 <groupId>org.apache.felix</groupId>                 <artifactId>maven-bundle-plugin</artifactId>                 <extensions>true</extensions>             </plugin>         </plugins>     </build>        <repositories>         <repository>             <id>fuse-public-repository</id>             <name>FuseSource Community Release Repository</name>             <url>https://repo.fusesource.com/nexus/content/groups/public</url>             <snapshots>                 <enabled>false</enabled>             </snapshots>             <releases>                 <enabled>true</enabled>                 <updatePolicy>never</updatePolicy>             </releases>         </repository>     </repositories> </project> 

Now from the Karaf command line, install at first the features required to provision the bundle:

JBossFuse:karaf@root> features:install cxf JBossFuse:karaf@root> features:install camel-jaxb JBossFuse:karaf@root> features:install camel-blueprint JBossFuse:karaf@root> features:install camel-cxf 

Next, install the bundle on JBoss Fuse with:

JBossFuse:karaf@root> osgi:install -s mvn:org.apache.camel/fuse-demo/0.0.3-SNAPSHOT 

That’s all. Verify with any Web service client that the Web service available on http://localhost:9080/example-input-cxf/ correctly responds and the route camel forwards the call to the target Web service.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.source.sample.com/">    <soapenv:Header/>    <soapenv:Body>       <ws:count>          <!--Optional:-->          <arg0>             <a>1</a>             <b>2</b>          </arg0>       </ws:count>    </soapenv:Body> </soapenv:Envelope> 

You should expect as return a response with the sum of the two parameters of the Wrapper object:

<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       
   <soap:Body>
             
      <ns2:countResponse xmlns:ns2="http://ws.source.sample.com/">
                   
         <return>3</return>
                
      </ns2:countResponse>
          
   </soap:Body>
    
</soap:Envelope>