Bridging MSMQ with JMS using FUSE-ESB4
This is a small tutorial showing how to create an OSGi based project to be deployed into FUSE-ESB4.
In particular, using a real use case, I'd like to show how to use some tools that accelerate the building of OSGi based applications ready to be deployed into FUSE-ESB4.
I'm assuming a basic knowledge of FUSE-MediationRouter and Maven.
For this tutorial we need a Windows machine since we are going to use a Camel component which uses a native library for accessing the MSMQ broker.
This is the list of the tools we are going to use:
- Maven
- pax-construct, this is a nice collection of scripts that allows to create maven based projects specially tailored for OSGi
- MSMQ, we assume that you have MSMQ up and running on your machine
- FUSE-ESB4, install the product with the installer that you can find here
Now that we have all the needed tools ready, let's start:
- First, we have to download and install the camel-msmq component from the Progress open source subversion repository, https://projects.open.iona.com/projects/svn/iona/camel/trunk/components/camel-msmq, so please, using any svn client you like check out the source code and after reading the provided README file do a mvn install.
- Now go in the FUSE-ESB4 installation directory and type: bin\servicemix.bat this will start the container together with the console shell.
- From the console shell we have to install two OSGi bundles needed for our example, so in the console type:
- osgi install -s mvn:org.apache.camel/camel-jms/1.4.4.0-fuse
- osgi install -s mvn:org.apache.camel/camel-msmq/1.x-fuse-SNAPSHOT
The two commands above installed the jms and the msmqm camel components to be used for implementing the bridge.
- Now we are ready to build our Camel based JMS to MSMQ bridge. I suggest you to put the directory where the pax-construct scripts reside in your command PATH, then start to type:
- pax-create-project -g com.progress.ps.fuse.demos -a camel-spring-osgi-jms-msmsq-bridge
- cd camel-spring-osgi-jms-msmsq-bridge
- pax-add-repository -i open.iona.m2 -u http://repo.open.iona.com/maven2
- pax-add-repository -i open.iona.m2-snapshot -u http://repo.open.iona.com/maven2-snapshot
- pax-create-bundle -p com.progress.ps.fuse.demos.jms_msmq_bridge.routes -n jms-msmq-bridge-routes
What we did so far, it was to create a parent maven project, camel-spring-osgi-jms-msmsq-bridge, we added the Progress open source maven repositories and, finally, we created a maven project jms-msmq-bridge-routes where we are going to define the routes.
The pax-create-bundle creates a maven project which uses the maven-bundle-plugin for packaging the application in a bundle.
From now on we are going to work under the jms-msmq-bridge-routes project directory:
- add these two dependencies to the pom.xml under jms-msmq-bridge-routes project:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>1.4.4.0-fuse</version> </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-msmq</artifactId> <version>1.x-fuse-SNAPSHOT</version> </dependency> - remove all the generated classes and add this class:
package com.progress.ps.fuse.demos.jms_msmq_bridge.routes.internal; import java.nio.ByteBuffer; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.msmq.MsmqConstants; public class MyRouteBuilder extends RouteBuilder { public void configure() throws Exception { // From msmq to jms from("timer:myTimerEvent?fixedRate=true&period=200").setBody( constant("Message from msmq to jms")).to( "msmq:DIRECT=OS:localhost\\private$\\msmq-jms"); from("msmq:DIRECT=OS:localhost\\private$\\msmq-jms").process( new Processor() { public void process(Exchange exc) throws Exception { int size = ((Long) exc.getIn().getHeader( MsmqConstants.BODY_SIZE)).intValue(); ByteBuffer buffer = (ByteBuffer) exc.getIn().getBody(); exc.getIn().setBody( buffer.asCharBuffer().subSequence(0, size / 2) .toString()); } }).to("jms:msmq-jms"); from("jms:msmq-jms").to("log:msmq-jms"); // From jms to msmq from("timer:myTimerEvent?fixedRate=true&period=200").setBody( constant("Message from jms to msmq")).to("jms:jms-msmq"); from("jms:jms-msmq").to("msmq:DIRECT=OS:localhost\\private$\\jms-msmq"); from("msmq:DIRECT=OS:localhost\\private$\\jms-msmq").process(new Processor() { public void process(Exchange exc) throws Exception { int size = ((Long) exc.getIn().getHeader( MsmqConstants.BODY_SIZE)).intValue(); ByteBuffer buffer = (ByteBuffer) exc.getIn().getBody(); exc.getIn().setBody( buffer.asCharBuffer().subSequence(0, size / 2) .toString()); } }).to("log:jms-msmq"); } }In the class above you can see the definition of four routes that simulates the traffic of messages from JMS to MSMQ and vice versa.
- Create, under MSMQ, two private queues called respectively jms-msmq and msmq-jms.
- Modify the osgi.bnd file for instructing the maven-bundle-plugin to put the right information in the bundle's manifest:
#----------------------------------------------------------------- # Use this file to add customized Bnd instructions for the bundle #----------------------------------------------------------------- Import-Package: org.apache.activemq, org.apache.camel, org.apache.camel.builder, org.apache.camel.model, org.apache.camel.component.jms
- Under src/main/resources create a folder META-INF/spring and put there the following xml file, beans.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" xmlns:osgi="http://activemq.apache.org/camel/schema/osgi" xmlns:osgix="http://www.springframework.org/schema/osgi-compendium" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd http://activemq.apache.org/camel/schema/osgi http://activemq.apache.org/camel/schema/osgi/camel-osgi.xsd http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd"> <osgi:camelContext xmlns="http://activemq.apache.org/camel/schema/spring"> <package>com.progress.ps.fuse.demos.jms_msmq_bridge.routes.internals</package> </osgi:camelContext> <bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory"> <bean class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://localhost:61616" /> </bean> </property> </bean> </beans> - Now, type mvn install and under the target directory you'll have the bundle jms-msmq-bridge-routes-1.0-SNAPSHOT.jar ready to be deployed
- Copy the file above into: <fuse-esb install dir>/deploy
- On the console, if you type: log d you should see something like this:
16:43:15,533 | INFO | nerContainer-389 | msmq-jms | rg. apache.camel.processor.Logger 87 | Exchange[BodyType:String, Body:Message from msmq to jms] 16:43:15,603 | INFO | pool-28-thread-1 | jms-msmq | rg. apache.camel.processor.Logger 87 | Exchange[BodyType:String, Body:Message from jms to msmq] 16:43:15,714 | INFO | nerContainer-390 | msmq-jms | rg. apache.camel.processor.Logger 87 | Exchange[BodyType:String, Body:Message from msmq to jms] 16:43:15,784 | INFO | pool-28-thread-1 | jms-msmq | rg. apache.camel.processor.Logger 87 | Exchange[BodyType:String, Body:Message from jms to msmq]
that would mean that the messages are flowing from MSMQ and JMS.
Using the jconsole you can also check the various information published bu FUSE-ESB4.
This is a simple example that could be used as a starting point for building something more complex. Pax-construct provides also a pax-wrapper script that creates a maven project for transforming into an OSGi bundle a third party library.
So, starting from a parent project, using the pax-construct scripts, you can add additional sub-projects for osgi-fying third party libraries and building new bundles, then from the parent project, typing mvn install, you can build your OSGi application together with all its dependencies.
