Mediate 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:

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

Advertisement

Cookie Alert