In the first post on this topic I will be walking you through a simple example that takes an existing Spring Integration application and shows how to use the Esper wire tap to send messages passing over a Spring Integration channel into Esper.
In the next post in the series I will show how you can hook Spring Integration into Esper to have events trigger the creation of Spring Integration messages.
Our sample application consists of a Spring Integration message pipeline that is connected to a HR system. Whenever the HR process successfully hires a new employee at our fictitious company the HR system creates a notification message that allows other systems to take appropriate actions to deal with the new hire.
To hide the fact that we are using Spring Integration from the HR system we use a Spring Integration gateway which is injected into the HR system. The SI gateway creates a proxy implementation of the configured interface, shown below, which is then injected into HR System.
For testing purposes we expose the HR system as a JMX bean with the two methods we use to instruct HR to hire new developers or lawyers exposed as managed operations.
Then simply add the MBean export to the configuration file.
The OpenCredo Esper Extension project provides a namespace for configuring the wire tap. All that is required is to use the wire-tap element from the si-esper namespace. An example of the esper wire tap is shown below:
Here we have configured a wire tap to publish an event to Esper each time a message is sent to the confirmedEmployeesChannel channel. By setting send-context to false the published event will simply be the payload of the Spring Integration message, in this case an instance of EmployeeConfirmation. If send-context is set to true, the default, then additional context such as the channel and the sourceId will be included in the event published to Esper.
That’s all that is required to make the data passing available through Spring Integration channels available to Esper.
In the next post I will show how to then use Esper to query that flow of data allowing us to better understand what is happening at runtime and to alert us to interesting conditions in our application. The next post will also include the runnable source code for the example.
]]>
Little time to blog lately but hopefully I will be getting some more time as of mid November. Having started OpenCredo in conjunction with Russ Miles and Gary Levy earlier in the year we have seen fantastic growth in our first six months. Thankfully things are now starting to settle down after the initial crazy days. Over the next few months we are expecting to find time to deliver some interesting open source projects which combine some of our main company interests of integration, messaging and cloud computing. Watch this space.
In addition I have been working on the upcoming Spring Integration in Action with the other Spring Integration committers. A first view of the book is now available through the Manning early access program here. Feedback through the Manning forum would be much appreciated.
]]>The first thing you need to decide is where you are going to have your shared repository which will be populated by Maven and used by dm Server to resolve dependencies. You can configure dm Server to use the default Maven repository under your home directory, however for reasons of clarity I prefer to maintain a separate repository. So, assuming you have downloaded dm Server and unzipped it, the first thing you will need to do is modify the provisioning configuration in DM_SERVER/config/server.config. By default there is no section for provisioning here with convention being used, so after the osgiConsole section define a section as below.
To test this we will create a simple project which uses Apache Commons lang StrSubstitor class to print the simple message given as an example in the Javadoc for commons lang “You are running with java.version = ${java.version} and os.name = ${os.name}.”)
To create the sample Maven project we can use the Maven archetype plugin so go to the command prompt in the directory where you want to create the test project.
Ok, so now we need to open up the pom.xml that has been created for use by the archetype plugin, so change directory to mavenDmHello and open pom.xml in your preferred text editor. After the URL element and before the dependency element add in the below xml fragment to allow Maven to resolve dependencies from the SpringSource Enterprise Bundle Repository, which you can browse here http://www.springsource.com/repository.
To declare the dependency on Apache Commons Lang we are adding the version from the SpringSource repository to ensure we get an OSGi compatible jar, hence the non-standard artifactId.
In order to tell Maven to use the non-standard local repository location we could configure the location in our global settings.xml. However, since this will effect all our maven projects, for the moment we will set up a separate settings.xml file. In the root of the created project create a file called settings.xml with the content below.
To tell Maven about our new settings.xml we pass the -s so running mvn -s./settings.xml install will download our dependency on Commons Lang into our new repository. Maven will of course download a whole host of other things as well.
Next we will create a class in our project which makes use of StrSubstitor to make sure everything is working as expected. So create a greeter class as below.
We can then use the standard mechanism to have an instance of our Greeter class created at runtime. So under src/main/resources create a directory structure META-INF/spring and inside the spring directory create a file called greeter.xml as below.
The next thing we need to do is provide an OSGi compatible manifest importing the org.apache.commons.lang.text.StrSubstitutor. Because Maven will auto generate a manifest we also need to configure the maven-jar-plugin to use our provided manifest. We do this by adding the build section as below to our pom.xml.
Then create the MANIFEST.MF in the META-INF directory as below. We declare our import of the commons lang package containing the StrSubstitutor
Now start up the dm Server using the script under DM_SERVER/bin. Run mvn install again to create a jar containing our new manifest. Then simply copy the jar created in the maven target directory to the DM_SERVER/pickup. You should see dm Server output as below.
[2009-03-08 20:39:22.735] fs-watcher
[2009-03-08 20:39:23.504] fs-watcher
A tail of the serviceability log DM_SERVER//serviceability/trace/mavenDmHello-1/trace.log will show something similar to below, showing that we are successfully using Maven to populate the repository for use with dm Server.
[2009-03-08 20:39:23.482] server-dm-4 amework.beans.factory.support.DefaultListableBeanFactory.unknown I Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@65d0e7e9: defining beans [greeter]; root of factory hierarchy
[2009-03-08 20:39:23.493] server-dm-4 System.out I You are running with java.version = 1.6.0_07 and os.name = Mac OS X.
So now we have dependencies working with Maven however we are still creating the manifest by hand. The SpringSource Maven bundlor plugin can be used to help with that and I will be posting an example using that soon.
]]>The example is that of a simple message flow which first receives a LoanApplication from a JMS queue. The loan application is then routed based on simple business rules to either a quote generating service or to a rejection queue for processing later. I will start off with a detailed walk through of the example application so if you just want to get the code up and running you can skip through to the getting it running section towards the bottom.
Loan application message flow
The configuration for the demo1 project can be found under src/main/resources. The loanquote-context.xml first defines an inbound JMS channel adapter. The fact that we are using a JMS channel adapter rather than a JMS gateway indicates that we are doing one way communication. If we were participating in a request response scenario we would want to use one of the provided gateways instead. The inbound adapter means we are receiving from JMS and placing an instance of org.springframework.integration.core.Message on the configured channel. Spring Integration also provides an outbound gateway to take a Spring Integration message from a Spring Integration channel and send that to a JMS destination. JMS gateways also come in both inbound and outbound versions.
JMS Inbound channel adapter
The JMS inbound adapter is configured very simply in this case with a reference to a JMS connection factory, the name of a JMS destination and the name of the Spring Integration channel on which received messages will be placed. Our connection factory is a Spring bean defined elsewhere. In this case we are using the ActiveMQ configuration below.
ActiveMQ connection factory
The next step in our flow is to route according to the credit rating which is already available in the LoanApplication. To do that we use a simple router implementation as below. Note that rather than accepting an instance of org.springframework.integration.core.Message the router accepts an instance of LoanApplication which is the payload of the message. This makes the router easier to unit test by decoupling it from messaging. The router in this case is simply returning a String channel name which will then be resolved to a channel instance by the framework. The default strategy, which will be used here, is to look for a Spring bean in the application context with an id matching the String returned by the router. This strategy is as with most things in Spring Integration pluggable if required.
Credit Checking Router
In order to connect the router into our integration application we simply declare the POJO router as a Spring bean and reference this from our router element. Our router element requires a reference to the channel from which messages will be received, a reference to the POJO router bean and the name of the method to invoke when a message is received. We also need to declare the two channels which our router will route to. Here the quote channel will be of the default DirectChannel type. This means that a call to send on this channel will dispatch the message to any consumer(s). In the case of rejected applications we are going to queue those up and process them later so we declare a queue element as a child of channel. This means that the reject channel will be an instance of QueueChannel and calls to send will not result in any message dispatch. The consumer responsible for processing rejections will need to come looking for our rejected loan applications by polling the queue.
Router configuration
Our quote service is very simple in this case. If you have the good or great credit rating to get past our router then we are simply going to quote our standard fixed rate of 20% APR, sign of the times I’m afraid. Our service activator is again very testable and decoupled from the messaging framework, the LoanApplication is the payload of the message received from the input channel and the returned Quote becomes the payload of the message sent to our output channel.
Quote Service
Hooking our quote service in is then just a case of declaring a service activator with a ref to the bean, the input and output channels. For the purposes of the demo we are then simply printing our quotes to standard out using a provided stream channel adapter.
Loan Quote Service Activator
Since the projects are using Maven, if you don’t have a Maven plugin already installed in Eclipse I would recommend installing Q4E from here.
You can then import the projects from the zip using File-> Import -> General -> Import existing projects into workspace and navigate to the archive.
We sometimes get questions on the Spring Integration forum about starting up and deploying a Spring Integration application. The short answer is that all you need is a JRE, since Spring Integration is designed to be lightweight and it does not require an application server to run. In the case of the demo the application is started using a main method. In this case however since we are using JMS you will need a broker. I used ActiveMQ 5.2 which you can download here. Simply unzip it and run activemq-admin start from the bin directory. You should then be able to browse to http://localhost:8161/admin/queueGraph.jsp and see a number of example destinations. Start the LoanApplicationGenerator by running the main method. So Run As-> Java Application if you are using Eclipse. Refreshing the ActiveMQ console should now show you that we have a build up of loan applications on our newApplication JMS queue. To start our loan quote application simply run the LoanQuoteStarter class in the demo project, the code of which is shown below. This creates our Spring application context and since our beans are lifecycle aware the application will immediately start processing loan applications.
Startup class for loan processing application
You should now see console output as below.
Applicant name:Sue rating: GOOD amount:79053.0 years:8 quoted rate : 20.0
Applicant name:Greg rating: GOOD amount:47561.0 years:1 quoted rate : 20.0
Applicant name:Simon rating: GREAT amount:41472.0 years:7 quoted rate : 20.0
Applicant name:John rating: GOOD amount:19438.0 years:1 quoted rate : 20.0
Applicant name:Emma rating: GREAT amount:66612.0 years:3 quoted rate : 20.0
Applicant name:Bob rating: GOOD amount:80851.0 years:0 quoted rate : 20.0
Applicant name:Greg rating: GOOD amount:19175.0 years:9 quoted rate : 20.0
Applicant name:John rating: GOOD amount:18578.0 years:2 quoted rate : 20.0
Applicant name:Simon rating: GOOD amount:64692.0 years:4 quoted rate : 20.0
The next post will be based on demo number two from my talk which will show how we can break up an application such as the example loan quote application into OSGi bundles, and in doing so we will create a more modular, testable and flexible application.
]]>Over the next few months I will also be putting out a number of blogs on topics I have been meaning to write something on for some time. Most of these will probably relate to Spring Integration since that is definitely what I am most excited about right now although the ability of Grails to make web development with Java exciting and fast paced is also up there for me.
Certainly the first few blogs will be follow-ups to the well received London Spring User Group talk on Spring Integration I delivered on the 12th of February at Skills Matter. The video of that talk can be found on the Skills Matter website here. Thanks to Skills Matter for hosting yet another great community event and to Cake Solutions for providing the organisation and the generous post-talk beer for everyone at the Crown. In the next few days I will be putting up the code from the samples in that talk along with a walk through of the unsuccessful Spring Integration with OSGi demo running on the SpringSource dm Server.
]]>