Mulesoft:Flow Execution Time

Mulesoft application is based on flows. Every flow has their own execution time. We can calculate this flow execution is couple of ways. But Mulesoft provides one of the easy way to calculate this flow execution time by using interceptor . Timer interceptor (<timer-interceptor/>) is one of the mule interceptor to calculate Mulesoft flow execution time.

Here is flow diagram for timer-interceptor

muleTimerInterceptorFlow

Here is code for timer-interceptor to implement in your application


<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"       xmlns:spring="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-current.xsdhttp://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">

<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" basePath="/demo" doc:name="HTTP Listener Configuration"/>

<flow name="muleTimerInterceptorFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>               <timer-interceptor/>
     <set-payload doc:name="Set Payload" value="Hello World"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
</mule>

 <timer-interceptor/> tag display time in milliseconds.

You can customize flow execution time to replace <timer-interceptor/>  with  <custom-interceptor>.
In this custom interceptor you need to mention your custom interceptor java class.

<custom-interceptor class=”com.vanrish.interceptor.TimerInterceptor” />

Here is flow diagram for custom timer-interceptor

muleTimerCustomInterceptorFlow

Here is mule-config.xml  code for custom timer-interceptor


<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"       xmlns:spring="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-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">

<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" basePath="/demo" doc:name="HTTP Listener Configuration"/>

<flow name="muleTimerInterceptorFlow">

<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>

 <custom-interceptor class="com.vanrish.interceptor.TimerInterceptor" />

<set-payload doc:name="Set Payload" value="Hello World"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
</mule>

Java TimerInterceptor  code for custom timer-interceptor tag


package com.vanrish.interceptor;

 

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.interceptor.Interceptor;
import org.mule.processor.AbstractInterceptingMessageProcessor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* <code>TimerInterceptor</code> simply times and displays the time taken to
* process an event.

*/

public class TimerInterceptor extends AbstractInterceptingMessageProcessor

implements Interceptor {

/**

* logger used by this class

*/

private static Log logger = LogFactory.getLog(TimerInterceptor.class);

public MuleEvent process(MuleEvent event) throws MuleException {
long startTime = System.currentTimeMillis();
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date stdate = new Date();
String start = dateFormat.format(stdate);
System.out.println(start);

MuleEvent resultEvent = processNext(event);

Date enddate = new Date();
String end = dateFormat.format(enddate);

if (logger.isInfoEnabled()) {

long executionTime = System.currentTimeMillis() - startTime;
            logger.info("Custom Timer : "+resultEvent.getFlowConstruct().getName() + " Start at "+start+" and end at "+end +" it took " + executionTime + "ms to process event ["                   + resultEvent.getId() + "]");
}
return resultEvent;
}
}

Mulesoft Polling : A New Perspective

Mulesoft polling is one of the most important features in Mulesoft. If you are dealing with large set of data or asynchronous workflow, polling architect is one of the best options to manage this scenario.
There are two options to configure Mulesoft poll scheduling.

  1. Fixed frequency scheduler – you can define polling time in frequency, start delay and time unit. This is one of the simplest ways to define your polling.
  2. Cron scheduler – Cron scheduler gives ability to use expression language and manage complex scheduling polling.

There is no relationship between two polling. This was challenge for me to get the relationship between two polling so that I can manage my data more efficiently.

Mulesoft gives couple of options to set up relationship between two polls.

Watermark – In polling there is always challenge to process newly created data and keep persist pointer for processed data to avoid duplicate processing. Mulesoft allows us as Watermark to persist this pointer in objectstore. Mule sets a watermark to a default value the first time the flow runs, then uses it as necessary when running a query or making an outbound request. Based on flow Mule may update the original value of the watermark or maintain the original value.
Here is simple flow to show how to implement watermark for poll

Poll Watermark Flow Diagram
poll-watermark

Here is code for this flow


<?xml version="1.0" encoding="UTF-8"?>
  <mule xmlns:schedulers="http://www.mulesoft.org/schema/mule/schedulers" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
   xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
   xmlns:spring="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
   http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
   http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
   http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
   http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
   http://www.mulesoft.org/schema/mule/schedulers http://www.mulesoft.org/schema/mule/schedulers/current/mule-schedulers.xsd">
  <spring:beans>
     <spring:bean id="dataSourceBean" name="dataSource_Bean" class="org.apache.commons.dbcp.BasicDataSource">
       <spring:property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
       <spring:property name="username" value="********"/>
       <spring:property name="password" value="********* "/>
       <spring:property name="url" value="jdbc:jtds:sqlserver://localhost:60520;Instance=CRM;DatabaseName=vanrish;domain=man;integrated security=false"/>
    </spring:bean>
 </spring:beans>
  <db:generic-config name="Generic_Database_Configuration" dataSource-ref="dataSourceBean" doc:name="Generic Database Configuration" >
     <reconnect-forever frequency="30000"/>
  </db:generic-config>
<flow name="poll-watermarking" processingStrategy="synchronous">
  <poll doc:name="Poll">
    <schedulers:cron-scheduler expression="0 22 12 * * ?"/>
    <watermark variable="serialNumber" default-expression="0" selector="LAST" selector-expression="#[payload.serialNumber]"/>
    <db:select config-ref="Generic_Database_Configuration" doc:name="Select Database">
       <db:dynamic-query><![CDATA[SELECT
MessageId, MessageType,SerialNumber,CreatedOn  FROM Message where SerialNumber  > #[Integer.parseInt(flowVars['serialNumber'])] order by SerialNumber asc]]></db:dynamic-query>
    </db:select>
 </poll>
   <logger message="#[flowVars['serialNumber']] == Hello this is Loggin Message == #[payload]" level="INFO" doc:name="Logger"/>
  </flow>
</mule>

Idempotent Filter – Idempotent filter is another way in Mule we can keep track between two polling. This filter ensures that only unique messages are received by a service by checking the unique ID of the incoming message. This filter also store unique id/pointer in objectstore in mule.
Here is simple flow to use Idempotent Filter

Poll Idempotent Filter flow Diagram
poll-idempotent

idempotent-objectStore

Here is code

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:schedulers="http://www.mulesoft.org/schema/mule/schedulers" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:db="http://www.mulesoft.org/schema/mule/db"
  xmlns:cassandradb="http://www.mulesoft.org/schema/mule/cassandradb" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
  xmlns:spring="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.mulesoft.org/schema/mule/db http://www.mulesoft.org/schema/mule/db/current/mule-db.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
  http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
  http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
  http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
  http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
  http://www.mulesoft.org/schema/mule/schedulers http://www.mulesoft.org/schema/mule/schedulers/current/mule-schedulers.xsd">
    <spring:beans>
      <spring:bean id="dataSourceBean" name="dataSource_Bean" class="org.apache.commons.dbcp.BasicDataSource">
        <spring:property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
        <spring:property name="username" value="*******"/>
        <spring:property name="password" value="********"/>
        <spring:property name="url" value="jdbc:jtds:sqlserver://localhost:60520;Instance=CRM;DatabaseName=vanrish;domain=man;integrated security=false"/>
      </spring:bean>
    </spring:beans>
    <db:generic-config name="Generic_Database_Configuration" dataSource-ref="dataSourceBean" doc:name="Generic Database Configuration" >
      <reconnect-forever frequency="30000"/>
    </db:generic-config>
    <flow name="poll-idempotent" processingStrategy="synchronous">
      <poll doc:name="Poll">
        <fixed-frequency-scheduler frequency="10000"/>
        <db:select config-ref="Generic_Database_Configuration" doc:name="Select Database">
          <db:dynamic-query><![CDATA[SELECT  MessageId, MessageType,SerialNumber,CreatedOn  FROM Message order by SerialNumber asc]]></db:dynamic-query>
        </db:select>
      </poll>
      <foreach doc:name="For Each">
        <idempotent-message-filter idExpression="#[payload.SerialNumber]" doc:name="Idempotent Message">
          <in-memory-store entryTTL="120000" expirationInterval="1800000"/>
        </idempotent-message-filter>
        <logger message="#[payload.SerialNumber] == Hello this is Loggin Message == #[payload]" level="INFO" doc:name="Logger"/>
      </foreach>
    </flow>
  </mule>

MuleSoft Security – Encryption

Security is about protecting your assets. These assets could be anything in company. Please refer to my previous blog about  what-is-security.

Mulesoft provides security suite to protect company assets. This suite of security features provides various methods for applying security to Mule Service-Oriented Architecture (SOA) implementations and Web services. Mulesoft security suits are available in enterprise version of Mulesoft.

In this blog I am showing, how to use Encryption and Decryption from Mulesoft Security suits. Mule can encrypt an entire payload or several fields of data within a message. This encryption prevents unauthorized access of data like password, SSN, credit card… etc. and moves this data between systems securely.

Mule Message Encryption processor changes the payload or Message so that it becomes unreadable by unauthorized entities. Mule Encryption processor encrypts the payload using one of the following three Encryption Strategies

1) JCE Encrypter — encrypts stream, byte[] or string
2) XML Encrypter — encrypts string, encrypts individual fields using xpath expressions.
3) PGP Encrypter — encrypts stream, byte[] or string, applies tighter security (relative to JCE and XML), increases processing load (relative to JCE and XML)

Encryption-Decryption Flow Diagram
securitydemoproject
Encryption Connector Configuration
In my example I am using Jce Encrypter. I am setting value for key and keypassword
encryption_connector
Here is full code of this implementation


<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:encryption="http://www.mulesoft.org/schema/mule/encryption" 
xmlns:http="http://www.mulesoft.org/schema/mule/http" 
xmlns="http://www.mulesoft.org/schema/mule/core" 
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"       
xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.7.0"       
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-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/encryption http://www.mulesoft.org/schema/mule/encryption/current/mule-encryption.xsd">

  <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" basePath="/demo" doc:name="HTTP Listener Configuration"/>
  <encryption:config name="Encryption" doc:name="Encryption">
    <encryption:jce-encrypter-config key="8aVrj8x8IevyeaD=" keyPassword="0Zb+smauaT8v6hRiFGJDnakwlS/YC2u="/>    </encryption:config>

  <flow name="securitydemoprojectFlow">

    <http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>

    <set-payload value="Hello World" doc:name="Set Payload"/>

    <encryption:encrypt config-ref="Encryption" doc:name="Encryption" using="JCE_ENCRYPTER">

      <encryption:jce-encrypter key="8aVrj8x8IevyeaD=" algorithm="AES" encryptionMode="CBC" keyPassword="0Zb+smauaT8v6hRiFGJDnakwlS/YC2u="/>

    </encryption:encrypt>

    <logger message=" Encrypted Message ==#[payload]" level="INFO" doc:name="Logger"/>

    <encryption:decrypt config-ref="Encryption" doc:name="Decryption" using="JCE_ENCRYPTER">

      <encryption:jce-encrypter key="8aVrj8x8IevyeaD=" keyPassword="0Zb+smauaT8v6hRiFGJDnakwlS/YC2u=" algorithm="AES" encryptionMode="CBC"/>

    </encryption:decrypt>
  </flow>
</mule>

Mulesoft Parallel processing-2 (Splitter,Collection Splitter, Chunk Splitter)

I described in my previous blog about parallel processing, in this blog also I am continuing my previous blog but adding new flavor of parallel processing in Mulesoft.
Splitter flow control splits a message into separate fragments and then sends these fragments parallel and concurrent to the next message processor in the flow. Segments are identified based on an expression parameter, usually written in Mule Expression Language (MEL), but other formats can be employed also. There are three ways we can spilt Mulesoft message.

Splitter — Splitter can split all types of data like Object, XML, JSON, and Payload based on MEL (Mule expression language) and processes each split into individual thread. .

Collection Splitter – If input type is collection, then collection splitter split data based on collection and process each element in individual thread.

Chunk Splitter – Chunk of splitter spilts message into chunk of bytes based on user input and processes each chunk of bytes in individual thread.

Since Collection splitter is one of the most usable splitter in Mulesoft. So I am showing example about Collection splitter.
In this example HasMap is coming as payload. Collection Splitter splits HasMap into different threads (limiting max 50 threads) and processes these threads in parallel.

 Flow diagrame to implement parallel processing through Mulesoft Collection Splitter
splitter

Mulesoft code for parallel processing (Splitter)

<flow name="Vanrish-processFlow" processingStrategy="allow50Threads">

    <logger message="*** Starting Vanrish-processFlow ***" category="edi-vanrish-process" level="INFO" doc:name="Flow Start Log"/>

    <set-payload value="#[map-payload:processing]" doc:name="Payload Processing"/>
    <set-variable variableName="numberOfMessages" value="#[payload.entrySet().size()]" doc:name="Variable"/>
    <logger message="Processing #[flowVars['numberOfMessages']] entities" level="INFO" doc:name="logger-status go to database"/>
    <splitter doc:name="Collection Splitter" expression="#[payload.entrySet()]"/>
    <vm:outbound-endpoint exchange-pattern="one-way" path="VanrishVM" doc:name="VM"/>

    <logger message="*** Ending Vanrish-processFlow ***" category="edi-Vanrish-process" level="INFO" doc:name="Flow End Log"/>
</flow>

<flow name="Vanrish_Splitter_Demo" processingStrategy="allow50Threads">
    <vm:inbound-endpoint exchange-pattern="one-way" path="VanrishVM" doc:name="VM"/>
    <logger message="Company Canonical Start Time -&gt; #[server.dateTime]" level="INFO" doc:name="Company Logger"/>
    <flow-ref name="vanrishMsgPrivateFlow" doc:name="companyMsgPrivateFlow"/>
</flow>

Java Profiler is to show how Mulesoft Splitter splits collection message into multiple threads and process data
splitter-profiler

Mulesoft Parallel processing (Scatter-Gather)

There is always a bottleneck of application when application is being read or written to multiple sources. Application always takes more time to process.
Parallel processing techniques can help reduce the time it takes to process a solution and make application fast.

So what is parallel processing?
   Parallel processing is a form of process in which many process are carried out simultaneously, operating on the principle that large problems can often be divided into smaller ones, which are then solved at the same time

Mule introduces Scatter-Gather processor to implement parallel processing.  <All> message processor replaced by scatter-Gather in Mule 3.5 version with more feature. Scatter-Gather router sends a message for concurrent processing to all configured routes. It uses a thread pool to concurrently execute all routes. This means that the total time the caller thread needs to be waiting for routes to respond is no longer the sum of all route’s time, but just the longest of them. If there are no failures, Mule aggregates the results from each of the routes into a message collection. If any exception comes during Scatter-Gather process it throws a CompositeRoutingException, which maps each exception to its corresponding route.

 Flow diagrame to implement parallel processing for mule application

scatter-gather

Mule code for parallel processing (scatter-Gather)

<custom-transformer class="com.vanrish.transformer.GenerateMessageTransformer" doc:name="Java Transformer"/>
  <scatter-gather doc:name="Scatter-Gather">
    <processor-chain>
      <expression-filter expression="#[flowVars.COM != null]" doc:name="Expression Filter"/>
      <set-payload value="#[flowVars.COM]" doc:name="Set Payload"/>
      <logger message="Msg =&gt; #[payload.message]" level="DEBUG" doc:name="Msg Log"/>
      <custom-transformer class="com. vanrish.transformer.ComTransformer" doc:name="Java Transformer"/>    
    </processor-chain>
    <processor-chain>
      <expression-filter expression="#[flowVars.CON != null]" doc:name="CON Expression Filter"/>
      <set-payload value="#[flowVars.CON]" doc:name="Set Payload"/>
      <logger message="Msg =&gt; #[payload.message]" level="DEBUG" doc:name="Msg Log"/>
      <custom-transformer class="com.vanrish. transformer.ConTransformer" doc:name="Java Transformer"/>    
    </processor-chain>
    <processor-chain>
      <expression-filter expression="#[flowVars.CBA != null]" doc:name="CBA Expression Filter"/>
      <set-payload value="#[flowVars.CBA]" doc:name="Set Payload"/>
      <logger message="Msg =&gt; #[payload.message]" level="DEBUG" doc:name="Msg Log"/>
      <custom-transformer class="com. vanrish.transformer.CbaTransformer" doc:name="Java Transformer"/>    
    </processor-chain>
    <processor-chain&gt
      <expression-filter expression="#[flowVars.IDF != null]" doc:name="IDF Expression Filter"/>
      <set-payload value="#[flowVars.IDF]" doc:name="Set Payload"/>
      <logger message="IDF =&gt; #[payload.message]" level="DEBUG" doc:name="Msg Log"/>
      <custom-transformer class="com. vanrish.transformer.IdfTransformer" doc:name="Java Transformer"/>
    </processor-chain>
    <processor-chain>
      <expression-filter expression="#[flowVars.CCI != null]" doc:name="Expression Filter"/>
      <set-payload value="#[flowVars.CCI]" doc:name="Set Payload"/>
      <logger message="#[payload.message]" level="DEBUG" doc:name="Msg Log"/>
      <custom-transformer class="com. vanrish.transformer.CciTransformer" doc:name="Java Transformer"/>    
    </processor-chain>
  </scatter-gather>
  <choice doc:name="Choice">
    <when expression="#[payload is List]">
      <logger level="INFO" message="i am list" doc:name="Logger"/>
      <expression-component doc:name="Company Msg Exp"><![CDATA[payload=app.dserializeObjectToXML(message.payload[0]));]]></expression-component>
    </when>
    <otherwise>
      <logger message="CompanyMsg class" level="INFO" doc:name="Logger"/>
      <expression-component doc:name="Company Msg Exp"><![CDATA[payload=app.dserializeObjectToXML(message.payload));]]></expression-component>
    </otherwise>
   </choice>
  <set-variable variableName="messageType" value="Company" doc:name="Variable"/>

Mulesoft integration with MongoDB (NOSQL)

Mulesoft with MongoDB is one of the best combinations for big data processing.  MongoDB is leading open source NoSQL database and Mule Soft is leading open source ESB.  This blog is dedicated to integration of Mulesoft with MongoDB .

Installation and configuration of MongoDB

Install MongoDB in your system. I am using window installation of mongoDB. I installed mongoDB 3.0 in my C:\ MongoDB folder. I created data folder to store MongoDB data in C:\data.
start MongoDB server with command

> \MongoDB\Server\3.0\bin\mongod.exe" --dbpath  \ data

MongoDB server started in port –27017 and userId—admin

Now download test data from MongoDB website
 https://raw.githubusercontent.com/mongodb/docs-assets/primer-dataset/dataset.json 
save this to a file named primer-dataset.json.

Import this data into MongoDB with test instance
>  mongoimport --db test --collection restaurants --drop --file \temp\primer-dataset.json
Start mongo editor to test loaded data  
 > MongoDB\Server\3.0\bin\mongo.exe
Run this command to test your database is configured
 > db.restaurants.find().count() 
This will return result.

Configuration of MongoDB connector in Mulesoft

Now configure MongoDB connection in Mule. I am using Mule 3.7
I created small Mule flow to work with MongoDB integration with Mule. This flow getting http request to get data from MongoDB and sending those data in json object.

managoDBFlow

MongoDB connection configuration screenshot
mangoConfig

Now we have restaurants collection in MongoDB , So I use collection  as restaurants.To execute condition query I am using operation – Find object using query map

In Query Attributes I am using  — Create Object manuallybuilder

Here is full code of this implementation

       <?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:mongo="http://www.mulesoft.org/schema/mule/mongo" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
	xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.7.0"
	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-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/current/mule-mongo.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd">
    <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" basePath="/mongo" doc:name="HTTP Listener Configuration"/>
    <mongo:config name="Mongo_DB" database="test" doc:name="Mongo DB" username="admin"/>
    <flow name="mongodbprojectFlow">
        <http:listener config-ref="HTTP_Listener_Configuration" path="/mongoproject" doc:name="HTTP"/>
        <logger message="This is Http Request and Response" level="INFO" doc:name="Logger"/>
        <mongo:find-objects-using-query-map config-ref="Mongo_DB" doc:name="Mongo DB" collection="restaurants" >
        	<mongo:query-attributes>                
            	<mongo:query-attribute key="restaurant_id">40360045</mongo:query-attribute>
        	</mongo:query-attributes>
        	<mongo:fields>
            	<mongo:field>name</mongo:field>
            	<mongo:field>cuisine</mongo:field>
            	<mongo:field>borough</mongo:field>
        </mongo:fields>
        </mongo:find-objects-using-query-map>
        <mongo:mongo-collection-to-json doc:name="Mongo DB"/>
        <json:object-to-json-transformer doc:name="Object to JSON"/>
    </flow>
</mule>

REST API Descriptive Language (API DL)

Rest (Representational State Transfer) webservice style is getting widespread acceptance across the Web fraternity. Industries and software communities are looking alternative to SOAP and WSDL based webservice. To compete with SOAP and WSDL based webservice REST need to support Descriptive Language based API.

Webservices APIs that follow and apply to the REST architectural constraints are called RESTful APIs. API descriptive language need to include blueprint of service, contract of service, metadata of service and documentation of service.

Many REST API descriptive language (API DL) are available today. Here I am discussing top 3 active API DL available for REST.

restapi

RAML — RAML is sponsored by MuleSoft. RAML Built on broadly used standards such as YAML and JSON, written in CoffeeScript, and can be used as a node.js. This is one of the very famous API DL and widely use with MuleSoft ESB. RAML support blueprint and contract of service design before you start your original coding. RAML API design approach is top-down. Writing spec for RAML is simple, human readable format.

SWAGGER – Sawwagger is sponsored by couple of companies like Apigee, Reverb and supported  with a large number active developer communities. Swaager format is based on JSON but they also support YAML. Swagger right now doesn’t support design before code. SWAGGER API design approach is bottom-up. Writing spec for SWAGGER  looks incomplete.

API Blueprint – API blueprint is sponsored by Apiary.API blueprint is based on Markdown. Markdown is a text-to-HTML conversion tool for web writers. There is no active developer community support for API Blueprint. API Blueprint right now doesn’t support design before code and its design approach is top-down. Writing spec for API Blueprint is simple and easy.

New Feature of Mule ESB 3.6 released and Anypoint studio

Mule ESB is one of the leading open sources ESB in market. Mule ESB product is maturing every day. Recently it released new version of Mule 3.6 and Anypoint studio January 2015 to support development for Mule 3.6 released. This release of mule adopts design-first and resource based approach. With this release user can quickly connect and design API based on a new HTTP connector.anypoint-platform-release
Here is quick view of some of enhancement with Mule 3.6
1. New Http connector – New http connector is more resource centric, simpler to use and allow using RAML specs.
2. Shared Resources – New released support shared resources allow to share connector across multiple project and application. This is managed by new project inside Mule editor called Domain.
3. Continuous Integration enhancement — This release features a powerful new agent that provides access to MuleSoft’s runtime API for integrating with existing continuous integration processes and SDLC tools like Jenkins
4. New Support for Microsoft – Sharepoint and Dynamics CRM are two new connectors to integrate with Microsoft services.
5. AMQP 0.9 connector – This connector is now officially part of Mule soft connector. It is built on top of the previously-available community AMQP transport, and includes support for multi-channel receivers

Integration of JBPM and spring with Mule ESB

Mule, JBPM and spring framework is one of the best combinations to implement SOA framework. These combinations are very famous among open source and easy to implement. Integration among this technology is always a challenge. I am adding some integration bullet point to make this integration easy.
These file are involved to integration among JBPM, spring and Mule ESB.
1) ApplicationContext.xml – spring framework
2) mule-config.xml – Mule ESB
3) jbpm.cfg.xml – JBPM file
4) All library for spring, JBPM and Mule ESB jar file
mule-config.xml
Add these lines into mule-config.xml file

  1. <mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
  2. ..... xmlns:bpm="http://www.mulesource.org/schema/mule/bpm/2.2" xmlns:spring-context="http://www.springframework.org/schema/context" xmlns:spring="http://www.springframework.org/schema/beans" ... >
  3. <spring:beans> <spring:import resource="applicationContext.xml"/> </spring:beans> <spring:bean id="jbpm-ref" parent="jbpm" />
  4. <bpm:connector name="jBpmConnector" bpms-ref="jbpm-ref" allowGlobalReceiver="true" allowGlobalDispatcher="true" processIdField="requestId"> <custom-exception-strategy class="com.vanrish.exception.ApplicationExceptionStrategy"/> <!—This is custom exception class based on your business logic -->< </bpm:connector>

applicationContext.xml
This is spring specific file. So we are defining jbpm specific configuration to call from mule.


    <bean id="jbpm" class="org.mule.transport.bpm.jbpm.JbpmImpl" destroy-method="destroy"> <property name="configuration"> <value>classpath:jbpm.cfg.xml</value> </property> property name="processDefinitionsResources"> <list> <value>classpath:verifyAge.xml</value> ..... <!-- Define JBPM specific process file --> </list> </property> <property name="createSchema"> <value>false</value> </property> </bean>

Webservice Spring WS-Security

My previous blog I explain some SOA concept. Now  In this blog I am jumping to some practical and explaining how to setup some basic web services with Spring framework and how to implement some security with web Services. To run this example  you need JDK 1.5+ and spring framework 3.0+I created some basic configuration. Here are list.
1. applicationContext-service.xml — It has some basic configuration of web service in spring
2. HelloWorldWS.java — This class is exposing webservice
3. HelloWorldServiceHandler.java — This class is monitoring incoming request and outgoing message. Here we implement WS-security.
4. HelloWorldManager.java — This class  is interface for business implementation.
5. HelloWorldManagerImpl.java— This class has business implementation.Now lets start how I implemented this web service. here are codes.
1. applicationContext-service.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
  5. xmlns:ws="http://jax-ws.dev.java.net/spring/core"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8. http://jax-ws.dev.java.net/spring/core
  9. http://jax-ws.dev.java.net/spring/core.xsd
  10. http://jax-ws.dev.java.net/spring/servlet
  11. http://jax-ws.dev.java.net/spring/servlet.xsd">
  12. <bean id="constantMap" />
  13. <ws:service id="SOAPservice" bean="#helloWorldWS">
  14. <ws:handlers>
  15. <ref bean="helloWorldHandler" />
  16. </ws:handlers>
  17. </ws:service>
  18. <wss:bindings id="jaxWs">
  19. <wss:bindings>
  20. <wss:binding url="/webservices/HelloWorldService">
  21. <wss:service>
  22. <ref bean="SOAPservice"/>
  23. </wss:service>
  24. </wss:binding>
  25. </wss:bindings>
  26. </wss:bindings>
  27. <bean id="helloWorldHandler">
  28. <property name="constantMap" ref="constantMap" />
  29. </bean>
  30. <!-- Injecting DAO Object -->
  31. <bean id="helloWorldManager">
  32. <property name="target">
  33. <bean>
  34. <property name="userDAO"><ref bean="userDAO"/></property>
  35. </bean>
  36. </property>
  37. </bean>
  38. <bean id="helloWorldWS">
  39. <property name="helloWorldManager"><ref bean="helloWorldManager"/></property>
  40. </bean>
  41. </beans>
2. HelloWorldWS.java

  1. package com.vanrish.service;
  2. import javax.annotation.Resource;
  3. import javax.jws.WebMethod;
  4. import javax.jws.WebParam;
  5. import javax.jws.WebResult;
  6. import javax.jws.WebService;
  7. import javax.jws.soap.SOAPBinding;
  8. import javax.xml.ws.WebServiceContext;
  9. import com.vanrish.service.HelloWorldManager;
  10. import com.vanrish.xml.schema.PeopleInfoRequest;
  11. import com.vanrish.xml.schema.PeopleInfoResponse;
  12. @WebService (targetNamespace="http://www.vanrish.com/helloWorldService",serviceName = "HelloWorldService")
  13. @SOAPBinding(style=SOAPBinding.Style.DOCUMENT, use=SOAPBinding.Use.LITERAL, parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
  14. public class HelloWorldWS {
  15. private HelloWorldManager helloWorldManager;
  16. @Resource
  17. WebServiceContext context;
  18. @WebMethod(exclude=true)
  19. public void setHelloWorldManager(HelloWorldManager helloWorldManager) {
  20. this.helloWorldManager = helloWorldManager;
  21. }
  22. @WebMethod(operationName = "getPeopleInfo")
  23. @WebResult(name = "PeopleInfo", partName = "PeopleInfo")
  24. public PeopleInfoResponse getPeopleInfo(@WebParam(name = "PeopleInfoRequest", partName = "PeopleInfoRequest",targetNamespace="http://www.vanrish.com/helloWorldService") PeopleInfoRequest peopleInfoRequest) throws Exception {
  25. return helloWorldManager.getPeopleInfo(peopleInfoRequest);
  26. }
  27. }
3. HelloWorldServiceHandler.java
  1. package com.vanrish.service.handler;
  2. import java.io.ByteArrayOutputStream;
  3. import java.util.Iterator;
  4. import java.util.Map;
  5. import java.util.Set;
  6. import javax.xml.namespace.QName;
  7. import javax.xml.soap.SOAPElement;
  8. import javax.xml.soap.SOAPEnvelope;
  9. import javax.xml.soap.SOAPHeader;
  10. import javax.xml.soap.SOAPMessage;
  11. import javax.xml.soap.SOAPPart;
  12. import javax.xml.ws.handler.MessageContext;
  13. import javax.xml.ws.handler.soap.SOAPHandler;
  14. import javax.xml.ws.handler.soap.SOAPMessageContext;
  15. import javax.xml.soap.Name;
  16. import org.apache.commons.logging.Log;
  17. import org.apache.commons.logging.LogFactory;

  18. public class HelloWorldServiceHandler implements SOAPHandler {

  19. private static final Log log = LogFactory.getLog(HelloWorldServiceHandler.class);
  20. /** The Constant USERNAME_TOKEN_STRING. */
  21. private static final String USERNAME_TOKEN_STRING = "UsernameToken";
  22. /** The Constant USERNAME_STRING. */
  23. private static final String USERNAME_STRING = "Username";
  24. /** The Constant PASSWORD_STRING. */
  25. private static final String PASSWORD_STRING = "Password";
  26. private Map constantMap;

  27. public Set getHeaders() {
  28. return null;
  29. }
  30. public void close(MessageContext context) {
  31. }
  32. public boolean handleFault(SOAPMessageContext context) {
  33. logToSystemOut(context);
  34. return true;
  35. }
  36. public boolean handleMessage(SOAPMessageContext context) {
  37. Boolean outboundProperty = (Boolean) context
  38. .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  39. boolean isSoapRequestHandle = false;
  40. if (outboundProperty.booleanValue()) {
  41. isSoapRequestHandle = true;
  42. /* ************************************************************************
  43. * If you are manupulating outgoing header then you need to add this code
  44. *
  45. **************************************************************************
  46. * try { SOAPMessage message = context.getMessage();
  47. *
  48. * SOAPPart sp = message.getSOAPPart();
  49. *
  50. * SOAPEnvelope envelope = sp.getEnvelope();
  51. *
  52. * SOAPHeader header = envelope.addHeader();
  53. *
  54. * SOAPElement security = header.addChildElement("Security", "wsse",
  55. * "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
  56. * );
  57. *
  58. * SOAPElement usernameToken =
  59. * security.addChildElement("UsernameToken", "wsse");
  60. * usernameToken.addAttribute(new QName("xmlns:wsu"),
  61. * "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  62. * );
  63. *
  64. * SOAPElement username = usernameToken.addChildElement("Username",
  65. * "wsse"); username.addTextNode("TestUser");
  66. *
  67. * SOAPElement password = usernameToken.addChildElement("Password",
  68. * "wsse"); password.setAttribute("Type",
  69. * "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"
  70. * ); password.addTextNode("TestPassword");
  71. *
  72. * //Print out the outbound SOAP message to System.out
  73. * message.writeTo(System.out); System.out.println("");
  74. *
  75. *
  76. *
  77. * }catch (Exception e) { e.printStackTrace();
  78. *
  79. * }
  80. */
  81. } else {
  82. try {

  83. SOAPMessage message = context.getMessage();
  84. SOAPPart sp = message.getSOAPPart();
  85. SOAPEnvelope envelope = sp.getEnvelope();
  86. SOAPHeader sh = envelope.getHeader();
  87. isSoapRequestHandle = processSOAPHeader(sh);
  88. message.writeTo(System.out);
  89. if (!isSoapRequestHandle) {

  90. SOAPElement errorMessage = sh.addChildElement(
  91. "errorMessage", "error",
  92. "http://vanrish.com/helloService/error");
  93. SOAPElement error = errorMessage.addChildElement("error");
  94. error.addTextNode("Authentication Failed !!!");
  95. }
  96. } catch (Exception e) {
  97. e.printStackTrace();
  98. }
  99. }
  100. logToSystemOut(context);
  101. return isSoapRequestHandle;
  102. }
  103. private void logToSystemOut(SOAPMessageContext smc) {
  104. Boolean outboundProperty = (Boolean) smc
  105. .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  106. if (outboundProperty.booleanValue()) {
  107. log.debug("\nOutgoing message:");
  108. } else {
  109. log.debug("\nIncoming message:");
  110. }
  111. SOAPMessage message = smc.getMessage();
  112. try {
  113. log.debug(handleRequestAndResponse(message));
  114. } catch (Exception e) {
  115. System.out.println("Exception in handler: " + e);
  116. }
  117. }
  118. private String handleRequestAndResponse(SOAPMessage msg) {
  119. ByteArrayOutputStream obj = new ByteArrayOutputStream();
  120. try {
  121. msg.writeTo(obj);
  122. return obj.toString();
  123. } catch (Exception ex) {
  124. obj = null;
  125. ex.printStackTrace();
  126. }
  127. return "";
  128. }
  129. private boolean processSOAPHeader(SOAPHeader sh) {
  130. boolean authenticated = false;
  131. // look for authentication header element inside the HEADER block
  132. Iterator childElems = sh.getChildElements();
  133. SOAPElement child = extractUserNameInfo(childElems);
  134. if (child != null) {
  135. // call method to perform authentication
  136. authenticated = authenticateRequest(child);
  137. }
  138. return authenticated;
  139. }
  140. private SOAPElement extractUserNameInfo(Iterator childElems) {
  141. SOAPElement child = null;
  142. Name sName;
  143. // iterate through child elements
  144. while (childElems.hasNext()) {
  145. Object elem = childElems.next();

  146. if (elem instanceof SOAPElement) {
  147. // Get child element and its name
  148. child = (SOAPElement) elem;
  149. sName = child.getElementName();
  150. // Check whether there is a UserNameToken element
  151. if (!USERNAME_TOKEN_STRING.equalsIgnoreCase(sName
  152. .getLocalName())) {
  153. if (child.getChildElements().hasNext()) { // TODO check
  154. logic
  155. return extractUserNameInfo(child.getChildElements());
  156. }
  157. }
  158. }
  159. }
  160. return child;
  161. }
  162. private boolean authenticateRequest(SOAPElement element) {
  163. boolean authenticated = false;
  164. // variable for user name and password
  165. String userName = null;
  166. String password = null;
  167. Name sName;
  168. // get an iterator on child elements of SOAP element
  169. Iterator childElems = element.getChildElements();
  170. SOAPElement child;
  171. // loop through child elements
  172. while (childElems.hasNext()) {
  173. // get next child element
  174. Object elem = childElems.next();
  175. if (elem instanceof SOAPElement) {
  176. child = (SOAPElement) elem;
  177. // get the name of SOAP element
  178. sName = child.getElementName();
  179. // get the value of username element
  180. if (USERNAME_STRING.equalsIgnoreCase(sName.getLocalName())) {
  181. userName = child.getValue();
  182. } else if (PASSWORD_STRING.equalsIgnoreCase(sName
  183. .getLocalName())) {
  184. // get the value of password element
  185. password = child.getValue();
  186. }
  187. if (userName != null && password != null) {
  188. authenticated = getUserAuth(userName, password);
  189. break;
  190. }
  191. }
  192. }
  193. if (userName == null || password == null) {
  194. log.warn("Username or password is empty. userName : [" + userName
  195. + "], password : [" + password + "]");
  196. }
  197. return authenticated;
  198. }
  199. public Map getConstantMap() {
  200. return constantMap;
  201. }
  202. public void setConstantMap(Map constantMap) {
  203. this.constantMap = constantMap;
  204. }
  205. private boolean getUserAuth(String username, String password) {
  206. //Constant Map populated with database information
  207. String dbUserId = (String) constantMap.get("useIdFormDatabase");
  208. String dbPassword = (String) constantMap
  209. .get("passwordFormDatabase");
  210. if (dbUserId.equalsIgnoreCase(username) && dbPassword.equals(password)) {
  211. return true;
  212. }
  213. return false;
  214. }
  215. }
4. HelloWorldManager.java —
  1. package com.vanrish.service;
  2. import com.vanrish.xml.schema.PeopleInfoRequest;
  3. import com.vanrish.xml.schema.PeopleInfoResponse;
  4. public interface HelloWorldManager {
  5. public PeopleInfoResponse getPeopleInfo(PeopleInfoRequest peopleInfoRequest) throws Exception;
  6. }
5. HelloWorldManagerImpl.java —
  1. package com.vanrish.service.impl;
  2. import java.math.BigDecimal;
  3. import java.math.BigInteger;
  4. import java.util.ArrayList;
  5. import java.util.Calendar;
  6. import java.util.Date;
  7. import java.util.GregorianCalendar;
  8. import java.util.Iterator;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.Set;
  12. import javax.xml.datatype.DatatypeConfigurationException;
  13. import javax.xml.datatype.DatatypeConstants;
  14. import javax.xml.datatype.DatatypeFactory;
  15. import javax.xml.datatype.XMLGregorianCalendar;
  16. import org.apache.commons.logging.Log;
  17. import org.apache.commons.logging.LogFactory;
  18. import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
  19. import com.vanrish.dao.UserDAO;
  20. import com.vanrish.model.PeopleVO;
  21. import com.vanrish.service.HelloWorldManager;
  22. import com.vanrish.xml.schema.ObjectFactory;
  23. import com.vanrish.xml.schema.Person;
  24. import com.vanrish.xml.schema.PeopleInfoRequest;
  25. import com.vanrish.xml.schema.PeopleInfoResponse;
  26. public class HelloWorldManagerImpl implements HelloWorldManager {
  27. private UserDAO userDAO;
  28. public PeopleInfoResponse getPeopleInfo(PeopleInfoRequest peopleInfoRequest) throws Exception {
  29. ObjectFactory factory = new ObjectFactory();
  30. PeopleInfoResponse peopleInfoResponse = factory.createPeopleInfoResponse();
  31. PeopleVO peopleVO = new PeopleVO();
  32. peopleVO.setPeopleId(peopleInfoRequest.getPeopleId());
  33. peopleVO = userDAO.getPeopleInfo(peopleVO);
  34. Person person = factory.createPerson();
  35. person.setFirstName(peopleVO.getFirstName());
  36. person.setLastName(peopleVO.getLastName());
  37. person.setType(peopleVO.getPeopleType());
  38. person.setCreateDate(getXmlDate(peopleVO.getCreateDate()));
  39. peopleInfoResponse.setPerson(person);
  40. peopleInfoResponse.setMessage(SUCCESS_MESSAGE);
  41. peopleInfoResponse.setSuccess(true);
  42. return peopleInfoResponse;
  43. }
  44. private XMLGregorianCalendar getXmlDate(Date date) {
  45. try {
  46. GregorianCalendar cal = new GregorianCalendar();
  47. cal.setTime(date);
  48. XMLGregorianCalendar gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
  49. gc.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
  50. gc.setTime(DatatypeConstants.FIELD_UNDEFINED,
  51. DatatypeConstants.FIELD_UNDEFINED,
  52. DatatypeConstants.FIELD_UNDEFINED);
  53. return gc;
  54. } catch (DatatypeConfigurationException e) {
  55. log.warn("Cannot format expxiration date: " + date);
  56. return null;
  57. }catch(Exception ex){
  58. log.warn("Cannot format expxiration date: " + ex);
  59. return null;
  60. }
  61. }
  62. public void setUserDAO(UserDAO userDAO) {
  63. this.userDAO = userDAO;
  64. }
  65. }