Friday, April 11, 2008

Using Apache ServiceMix - ESB with spring


Apache ServiceMix is an open source ESB (Enterprise Service Bus) that combines the functionality of a Service Oriented Architecture (SOA) and an Event Driven Architecture (EDA) to create an agile, enterprise ESB.

Apache ServiceMix is an open source distributed ESB built from the ground up on the Java Business Integration (JBI) specification JSR 208 and released under the Apache license. The goal of JBI is to allow components and services to be integrated in a vendor independent way, allowing users and vendors to plug and play.

Features:

ServiceMix is lightweight and easily embeddable, has integrated Spring support and can be run at the edge of the network (inside a client or server), as a standalone ESB provider or as a service within another ESB. You can use ServiceMix in Java SE or a Java EE application server.

ServiceMix uses ActiveMQ to provide remoting, clustering, reliability and distributed failover.

ServiceMix is completely integrated into Apache Geronimo, which allows you to deploy JBI components and services directly into Geronimo. ServiceMix is being JBI certified as part of the Geronimo project.

Other J2EE application servers ServiceMix has been integrated with include JBoss, JOnAS with more to follow.

ServiceMix includes a complete JBI container supporting all parts of the JBI specification including:
* Normalized Message Service and Router
* JBI Management MBeans
* Ant Tasks for management and installation of components
* full support for the JBI deployment units with hot-deployment of JBI components
ServiceMix also provides a simple to use Client API for working with JBI components and services.

How to use?

JBI components can be created extending servicemix's implementation classes.This is required because only then can you will be able to use the plug-&-play component,which is our purpose to use servicemix ESB.

You can develop Binding components which can receive data through HTTP and Files.Servicemix has already provided specific classes so you can deal with http request,input folder.
HTTP - org.apache.servicemix.components.http.HttpConnector.
File - org.apache.servicemix.components.file.FilePoller
So your class will use the HTTP request/file to fetch data and will make an javax.jbi.messaging.NormalizedMessage class object.

This NormalizedMessage object will be then given to javax.jbi.messaging.MessageExchange implementation (InOnly or InOut) and MessageExchange will be then routed to the next component configured as service endpoint in application context xml file.

application context xml code:
<sm:activationSpec componentName="myfilePoller" service="foo:myfilePoller" destinationService="foo:myDrool">
<sm:component>
<bean class="test.my.file.MyFilePoller">
<property name="workManager" ref="workManager" />
<property name="file" value="C:/inbox" />
<property name="period" value="120000" />
<property name="deleteFile" value="true" />
</bean>
</sm:component>
</sm:activationSpec>

<sm:activationSpec componentName="myDrool" service="foo:myDrool">
<sm:component>
<bean class="org.apache.servicemix.components.drools.DroolsComponent">
<property name="ruleBaseResource" value="classpath:myRule1.xml" />
</bean>
</sm:component>
</sm:activationSpec>
Here MyFilePoller is the class which will poll files from 'C:/inbox' folder. And make messaging as we discussed above.'myDrool' is its destination component which is an drools component.

Drools is like dynamic routing.We just need to make rules in xml file and that xml will be loaded automtically if its configured in applicationContext file as above. Its jar must be in 'lib' dir of the server.

Below is the drools xml which declares the rule base on which the NormalizedMessage will be routed to appropriate destination component.

NormalizedMessage can contain data and properties.We can read its property in XML rule base.And based on particular property, we can route the message.

Check the xml below.

myRule1.xml:
<rule-set name="cheese rules"
xmlns="http://drools.org/rules"
xmlns:java="http://drools.org/semantics/java">
<application-data identifier="jbi">org.apache.servicemix.components.drools.JbiHelper</application-data>
<application-data identifier="context">javax.jbi.component.ComponentContext</application-data>
<application-data identifier="deliveryChannel">javax.jbi.messaging.DeliveryChannel</application-data>
<rule name="Rule for componentOne">
<parameter identifier="exchange">
<class>javax.jbi.messaging.MessageExchange</class>
</parameter>
<java:condition>"TRUE".equalsIgnoreCase(exchange.getMessage("in").getProperty("isForComponentOne").toString()) == true</java:condition>
<java:consequence>
jbi.forwardToService("http://servicemix.apache.org/demo/", "componentOne");
</java:consequence>
</rule>
<rule name="Rule for anotherComponent">
<parameter identifier="exchange">
<class>javax.jbi.messaging.MessageExchange</class>
</parameter>
<java:condition>"TRUE".equalsIgnoreCase(exchange.getMessage("in").getProperty("isForComponentOne").toString()) == false</java:condition>
<java:consequence>
jbi.forwardToService("http://servicemix.apache.org/demo/", "anotherComponent");
</java:consequence>
</rule>
</rule-set>
This will route the message to 'componentOne' if the property tested in condition is true and toward 'anotherComponent' otherwise.Both components also will be specified in applicationcontext xml file.

This is how routing does work.Now we will talk about how each component get notified of message transfered.

Every intemediate component in servicemix will create new message and Exchange,pass it to next component after finishing its processing and send notification to the previous component.

code:
getDeliveryChannel().send(newExchange);
done(exchange);
At last, we now talk about the service endpoint, which has opposite task compared to binding components.

BindingComponents takes in and creates messages, Service endpoints throw out the messages and finishes the process.

we have 3 to 4 different outbidding components here and its having some classes already provided.
File - org.apache.servicemix.components.file.FileWriter
FTP - org.apache.servicemix.components.net.FTPSender
HTTP - org.apache.servicemix.components.util.OutBinding ( i have used this becasue in http, we will jsut send data to some URL or so and then processing is finished.)
Mail/SMTP - org.apache.servicemix.components.email.MimeMailSender
This is how we can use servicemix. You can add different components as per your needs at any place in the whole flow and define the path in xml applicationContext and Rule base files.

The changes or additions afterward will require some small changes only. You need to define new properties in NormalizedMessage and based on that property you can create new RuleBase files. And using drools, create new routing path for new feature.

Its very easy to use though feels very tricky and complex in the beggining.

we Will discuss more. :)

1 Comment:

Hardik said...

But how to deploy a component in a servicemix-web.war. Can you tell how to make a sample with jboss and servicemix.