MDW Camel Integration

Introduction to Apache Camel

Apache Camel is a powerful open source integration framework based on known Enterprise Integration Patterns with powerful Bean Integration.Camel lets you create the Enterprise Integration Patterns to implement routing and mediation rules in either a Java based Domain Specific Language (or Fluent API), via Spring based Xml Configuration files or via the Scala DSL.

Apache Camel uses URIs so that it can be easily work directly with any kind of Transport or messaging model such as HTTP, ActiveMQ, JMS, JBI, SCA, MINA or CXF, as well as pluggable Components and Data Format options. Apache Camel is a small library which has minimal dependencies for easy embedding in any Java application. Apache Camel lets you work with the same API regardless which kind of Transport used, so once you learn the API you will be able to interact with all the Components that is provided out-of-the-box.

Apache Camel has powerful Bean Binding and integrated seamless with popular frameworks such as Spring,Blueprint and Guice.

Apache Camel has extensive Testing support allowing you to easily unit test your routes.

Apache Camel can be used as a routing and mediation engine for the following projects:

Routes and Java DSL

A route is the step-by-step movement of a Message from an input queue, through arbitrary types of decision making (such as filters and routers) to a destination queue (if any). Camel provides two ways for an application developer to specify routes. One way is to specify route information in an XML file.The other way is through what Camel calls a Java DSL (domain-specific language).

CamelContext

A CamelContext object represents the Camel runtime system. You typically have one CamelContext object in an application. Basically a Camel Context will hold the camel routes which you declare and you can have multiple camel routes defined in your spring bean file.

Endpoint

The term endpoint is often used when talking about inter-process communication. For example,in client-server communication, the client is one endpoint and the server is the other endpoint. Depending on the context, an endpoint might refer to an address, such as a host:port pair for TCP-based communication, or it might refer to a software entity that is contactable at that address.

Camel provides out-of-the-box support for endpoints implemented with many different communication technologies. Here are some examples of the Camelsupported endpoint technologies.

  • A JMS queue.
  • A web service.
  • A file. A file may sound like an unlikely type of endpoint, until you realize that in some systems one application might write information to a file and, later, another application might read that file.
  • An FTP server.
  • An email address. A client can send a message to an email address, and a server can read an incoming message from a mail server.
  • A POJO (plain old Java object).


  • To get more details on Apache Camel See this link

    How to integrate MDW with Camel


    During build time we need to add dependencies to the maven pom.xml file for mdw-camel. Additionally you can also add whichever Apache Camel features you want to use like camel-core,camel-spring,camel-cxf shown in the snippet below.
    <dependency>
    <groupId>com.centurylink.mdw</groupId>
    <artifactId>mdw-camel</artifactId>
    <version>${mdw.version}</version>
    </dependency>
    <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-core</artifactId>
    <version>1.5.0</version>
    </dependency>
    <dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-spring</artifactId>
    <version>1.5.0</version>
    </dependency>
    
    To install in runtime container like ServiceMix/Fuse use below command :
    feature:install mdw-camel
    
    MDW war for Tomcat container includes camel feature so no additional steps are needed

    Configure Spring

    The Spring config file is placed under META-INF/spring as this is the default location. First we will need to do the standard schema declarations in the top. In the bundle-context.xml we have to use spring beans as the default bean: namespace and springs context:. For configuring ActiveMQ we can use broker: and for Camel of course camel:.

    We choose to integrate Camel in the Spring XML file so we add the camel namespace and the schema location like this:
    xmlns:camel="http://camel.apache.org/schema/spring"
    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
    
    Notice that we don't use version numbers for the camel-spring schema.

    Dependency Injection

    (src/main/resources/META-INF/spring/bundle-context.xml)

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
      <!-- regular spring configuration file defining the beans for this bundle. The configuration of OSGi definitions can be kept in a separate configuration file so that this file can easily be used for integration testing outside of an OSGi environment -->
    
      <bean id="mdwCamelActivityProvider"  class="com.centurylink.mdw.workflow.provider.ActivityProviderBean" />
    

    OSGI Injection

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:osgi="http://www.springframework.org/schema/osgi"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd
     http://www.springframework.org/schema/osgi
     http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd">
    
      <osgi:service ref="mdwCamelActivityProvider">
        <osgi:interfaces>
          <value>com.centurylink.mdw.common.provider.ActivityProvider</value>
        </osgi:interfaces>
        <osgi:service-properties>
          <entry key="alias" value="mdwCamelActivities"/>
        </osgi:service-properties>
      </osgi:service>
    
    The xml tag osgi:service will help to register our OSGI service top of the OSGI server and will publish the interfaces as available for another bundles who would like to use them.

    Defining Camel Context

    Below snippet shows how to define your Camel Context which is the standard Camel syntax and this basically holds all the camel routes you declare.Multiple Camel routes can be declared in context xml file.
    <camel:camelContext xmlns="http://camel.apache.org/schema/spring" xmlns:foo="http://centurylink.com/foo">
    <!-- launch a process -->
    <route>
          <from uri="file:data/inbox"/>
          <!-- no namespace -->
          <filter>
            <xpath>/Order</xpath>
            <to uri="mdw:process?name=CamelDemoProcess&masterRequestId=${Order/orderNumber/node()}"/>
          </filter>
    </route>
    </camel:camelContext>
    

    Apache Camel File Component

    The File component provides access to file systems, allowing files to be processed by any other Camel Components or messages from other components to be saved to disk.

    Define MDW Camel Component

    In order to support MDW you need MDW Camel component which gives you the ability to have MDW uri syntax (mdw:) to use as endpoints in your spring bean file(bundle-context.xml). Below is the snippet to define MDW Camel Component :
      <!-- MDW camel component -->
      <bean id="mdw" class="com.centurylink.mdw.camel.MdwComponent">
        <property name="namespaces">
          <map>
            <entry key="foo" value="http://centurylink.com/foo" />
          </map>
        </property>
      </bean>
    

    Using Camel to supplement existing MDW external event handler capability


    One of the main reason of using Camel Vs MDW is to supplement the existing MDW external event handler capability.
    As we know in case of external event handlers we register xpath message pattern and whenever some document comes in as part of the request and it matches the x path expression, we need to either launch a process ,notify a process,etc.
    Camel provides mechanism to do exactly the same thing plus they do have a lot of additional capabilities which you will see later.

    In the MDW 5.2 sandbox environment(mdw/mdw) look into workflow package "Camel Demo" which contains processes and assets that illustrates the above functionality.
    Or you can discover and import com.centurylink.mdw.demo.camel and com.centurylink.mdw.camel project for mdw-camel examples.


    Camel Protocol support

    Another biggest value of using Camel Vs MDW is Camel supports quite a number of protocols and transports from which MDW supports only few of them.
    For more details on Apache Camel transports see this link


    Using Camel Routes to launch MDW process


    The below code snippet uses Camel File Component and illustrates that whenever something comes in to your file system then based on the document message pattern i.e if the top element is /Order then you are launching a process.You can also pass additional parameters which are required to launch a process. In below snippet ${Order/orderNumber/node()} will be replaced with the data from the incoming document.
    <from uri="file:data/inbox"/>
    <!-- no namespace -->
    <filter>
       <xpath>/Order</xpath>
       <to uri="mdw:process?name=CamelDemoProcess&masterRequestId=${Order/orderNumber/node()}"/>
    </filter>
    

    XML with namespace

    The below code snippet illustrates that whenever any document (whose namespace top element is /foo:Order ) comes in to your file system then you are launching a process. Please note that the namespace needs to be registered in Camel Context as shown below.
    <camel:camelContext xmlns="http://camel.apache.org/schema/spring" xmlns:foo="http://centurylink.com/foo">
    
    <from uri="file:data/inbox"/>
    <!-- with namespace:
    prefix for filtering xpath is declared in camelContext above;
    prefix for masterRequestId xpath is declared in mdw-process bean below -->
    <filter>
    <xpath>/foo:Order</xpath>
    <to uri="mdw:process?name=CamelDemoProcess&masterRequestId=${/foo:Order/foo:orderNumber/node()}"/>
    </filter>
    

    Using Camel Routes to launch Service Process

    Below code snippet illustrates how to use Camel Routes to launch Service Process.
    <filter>
    <xpath>/GetEmployee</xpath>
    <to uri="mdw:process?name=FindEmployee&masterRequestId=${GetEmployee/sapId/node()}"/>
    </filter>
    


    Using Camel Routes to launch process using Custom Handler


    Below code snippet illustrates how to use Camel Routes to launch process using custom handler.
    <filter>
    <xpath>/DesignOrder[@product='Ethernet']</xpath>
    <to uri="mdw:process?name=Design%20Order&handlerClass=com.centurylink.mdwcamel.process.MyProcessLaunchHandler"
    pattern="InOut"/>
    </filter>
    


    Using Camel Routes to notify in-flight process


    There are various scenarios where MDW process instance will be waiting to get notified. With MDW we use external event handlers whereas with Camel we can use mdw:notify syntax to perform exactly the same behaviour.
    Below code snippet illustrates example of route-based notify.
    <filter>
    <xpath>/OrderUpdate</xpath>
    <to uri="mdw:notify?eventId=${/OrderUpdate/orderNumber/node()}"/>
    </filter>
    

    Below code snippet illustrates example of notifying in-flight process using custom handler.
    <filter>
    <xpath>/DesignOrderUpdate</xpath>
    <to uri="mdw:notify?handlerClass=com.centurylink.mdwcamel.event.MyNotifyHandler"/>
    </filter>
    

    Camel Routes As a Dynamic Workflow Asset


    At any point of time MDW Camel Route can be defined as a Dynamic Workflow Asset . Ex : Employee.wsdl (In the MDW 5.2 sandbox environment(mdw/mdw) look into workflow package "MDW Testing") is a dynamic webservice asset exposed through its wsdl which means we can change the wsdl any time without doing another deployment. Another example is OrderContext.spring as a dynamic asset in com.centurylink.mdw.demo.camel package

    Configuring Camel Routes as Dynamic Workfow Assets

    To illustrate this capability of configuring Camel Routes as dynamic workflow assets see section "Register Your Service through a Camel Route"


    You can hook up any other Camel endpoint to launch MDW process like cxf endpoint defined below:

    <!-- CXF Web Service Route to MDW Process Launch -->
    <route>
       <from uri="cxf:bean:employee-ws?dataFormat=PAYLOAD" /> <!-- specify MasterRequestID SOAP header -->
       <to uri="mdw:process?name=FindEmployee" pattern="InOut" />
    </route>
    

    CXF Endpoint needs to be defined in your bundle-context.xml file as shown below.Here we are exposing service as a cxf webservice.
    <!-- CXF Endpoint -->
      <cxf:cxfEndpoint
        id="employee-ws"
        address="http://localhost:8282/CXF/SOAP/Employee"
        endpointName="mdw:soap"
        serviceName="mdw:EmployeeService"
        wsdlURL="http://localhost:8181/MDWWeb/SOAP/Employee.wsdl"
        xmlns:mdw="http://mdw-servicemix.centurylink.com" />
    

    Using Camel Routes to handle SOAP/REST requests

    Below code snippet illustrates that whenever any SOAP/REST request comes in and matches /GetEmployee then launch FindEmployee process.
    The routes declared here tells the MDW Camel component to register a SOAP-based/REST-based web service and launch FindEmployee process when invoked.
    In order for the "mdw:" URI pattern to be supported, the MDW Component bean must be declared which you have already seen in previous section (Define MDW Camel Component).
    Please notice that with the "from" URI in an MDW Camel route you will have the option of specifying a specific endpoint URL path(SOAP/GetEmployee or REST/GetEmployee), in contrast to the standard MDW External Event handler which all use the same endpoint.
        <!-- MDW Web Service (SOAP) -->
        <route>
          <from uri="mdw:SOAP/GetEmployee"/> <!-- specify MasterRequestID SOAP or HTTP header -->
          <to uri="mdw:process?name=FindEmployee" pattern="InOut" />
        </route>
        <!-- MDW Web Service (REST) -->
        <route>
          <from uri="mdw:REST/GetEmployee"/> <!-- specify MasterRequestID HTTP header -->
          <to uri="mdw:process?name=FindEmployee" pattern="InOut" />
        </route>
    


    Camel Adapter Activity

    You can also use MDW workflow to launch a Camel route. If you are using Camel Route inside a workflow process then you must define it as a Workflow Asset.
    Ex : Look into the "Invoke Camel Route" process in Camel Demo package (MDW 5.2 sandbox environment mdw/mdw or import com.centurylink.mdw.demo.camel and com.centurylink.mdw.camel package)
    This process basically launches Camel Route from MDW process,this goes to the routing and at the end the end result will populate as part of the response variable.
    In this example the process uses Asset driven(MyCamelRoute.xml) activity defined as part of the Camel Route Adapter activity.

    Please note that the syntax "<from uri="mdw:workflow/this"/>" used in MyCamelRoute.xml means the instance of workflow which is running(i.e. instance of Invoke Camel Route process)

    NOTE:

    With respect to MDW , Camel Route is a good substitute for external event handler but it is not a good substitute for workflow because it does not really accomplish the needs defined for BPM/workflows.Also it is not user friendly.