Friday, January 25, 2008

ServiceMix: The Use Case and What You Need to Implement It

Okay, so I have some basic understanding of what the JBI Components are and how to package them up. Now, can I actually do anything. We'll see. First I'll lay out a use case. Then I'll try to implement it.

The Use Case
An external system sends a message in on a JMS queue and waits for a response on a temporary JMS queue. The message gets routed to Service 1(S1) which does some processing. The output from S1 then gets routed to to Service 2(S2). Then the output from S2 then gets routed to to Service 3(S3). Then, finally, the output for S3 gets routed back to the external system via a temporary JMS queue.



Okay so looking at this it looks like a match for the Static Routing Slip Enterprise Integration Pattern(EIP). It appears that Camel is the preferred EIP implementation but it does not yet support the Static Routing Slip pattern while servicemix-eip does so we'll go with it.

The Components
The next question is what components do we actually need? Lets go throught the use case and make a list:
  • A JMS Service Unit(SU) to act as a Binding Component(BC) and provide the protocol translation required to get the message on to the Normalized Message Router(NMR). We'll use servicemix-jms.
  • A Static Routng Slip SU to control the flow of our message through the NMR. To do this we'll use the Service Engine(SE) servicemix-eip.
  • A SU for each of our services (S1, S2 and S3). If we were going to talk to real external services we would need a BC SU for each that described the protocol for communication with each of the services. In this case, however, we are going to keep it simple just to demonstrate what we want to accomplish. We will use a simple POJO implementation. Our POJO will simply append some text to the input message to demonstrate that the message has been acted upon by each service in order. The POJOs will be SE components. No BC component is needed for them because they are hosted on the NMR.
  • Finally there will be a Service Assembly (SA) which pulls all this together into a deployable unit.
Configuration Strategy
Now how do we need configure ServiceMix? Well there's the old static method using servicemix.xml and the new JBI method. The JBI method has several advantages. First, each SA is independent and hot deployable. An other is that the JBI method seems far more JBI compliant. Finally, it seems that the static method, while not deprecated, is certainly falling from favor. We'll go with the new JBI strategy.

Get The Stuff
Okay, we're clicking along pretty good here but hold on. We need a few things before we move any further. We need, if we haven't already, to download and install:

Let's Get Started

ServiceMix comes with a number of Maven archetypes which automatically construct the structure of the various types of ServiceMix projects you may need to work with. This is what the Fuse version of Eclipse is doing under the cover when you're clicking through the tutorial. Doing it this way, however, forced me to realize what was happening instead of just going along for the ride. I guess its a question of learning styles and what works for you. At any rate this worked for me (or at least I think it did).

We're going to be working from the command line. For me that means a Linux shell. If you're on windows it should be rather easy to adjust.

Housekeeping
- Create a directory
tpurcell@tpurcell:/data> mkdir mySmTest
- Add Maven to our path
tpurcell@tpurcell:/data> export PATH=/data/apache-maven-2.0.8/bin/:$PATH
- Add ServiceMix to our path
tpurcell@tpurcell:/data> export PATH=/data/apache-servicemix-3.2.1/bin/:$PATH

Create Our SU Projects
- We need to create the SU project for our JMS SU using the Maven archetype for the servicemix-jms BC.
tpurcell@tpurcell:/data/mySmTest> smx-arch su jms-consumer -DgroupId=com.chariotsolutions -DartifactId=myJmsSu
- Now our Static Routng Slip SU. We're going to use the using the Maven archetype for the Service Engine(SE) servicemix-eip
tpurcell@tpurcell:/data/mySmTest> smx-arch su eip -DgroupId=com.chariotsolutions -DartifactId=myStaticRoutingSlip
- Next we create a SU for each of our POJO services using the Maven archetype for the servicemix-bean SE
tpurcell@tpurcell:/data/mySmTest> smx-arch su bean -DgroupId=com.chariotsolutions -DartifactId=myS1Pojo
tpurcell@tpurcell:/data/mySmTest> smx-arch su bean -DgroupId=com.chariotsolutions -DartifactId=myS2Pojo
tpurcell@tpurcell:/data/mySmTest> smx-arch su bean -DgroupId=com.chariotsolutions -DartifactId=myS3Pojo
Okay this is where we are at. We found the JBI components, BCs and SEs, we need to perform tasks. They need to be configured to behave so we wrap their configuration into SUs. We just created all SU projects for each of our JBI Components so we have a place to define and build their configuration. But we still have to be pull them all together into a SA so they can be deployed. So...

Create Our SA Project
- Finally we create our SA:
tpurcell@tpurcell:/data/mySmTest> smx-arch sa -DgroupId=com.chariotsolutions -DartifactId=mySa
What Have We Got?
We have a directory structure with some template Java classes and XML files and it all looks like this:
-myJmsSu/
--pom.xml
--src/
---main/
----resources/
-----xbean.xml
-myS1Pojo/
--pom.xml
--src/
---main/
----java/
-----com/
------chariotsolutions/
-------MyBean.java
----resources/
-----xbean.xml
-myS2Pojo/
--pom.xml
--src/
---main/
----java/
-----com/
------chariotsolutions/
-------MyBean.java
----resources/
-----xbean.xml
-myS3Pojo/
--pom.xml
--src/
---main/
----java/
-----com/
------chariotsolutions/
-------MyBean.java
----resources/
-----xbean.xml
-mySa/
--pom.xml
-myStaticRoutingSlip/
--pom.xml
--src/
---main/
----resources/
-----xbean.xml

This gives us a structure for the required components but now we have to configure and package them in order to create a solution for our use case. We'll tackle that next.

8 comments:

Anonymous said...

This didn't work for me.
When I run the smx-arch commands I
get the following error:

Invalid task 'com.chariotsolutions': you must specify a valid lifecycle phase, or a goal in the format plugin:goal...

Anonymous said...

I should have mentioned that I am
running on Windows XP in my
previous comment.

Tom Purcell said...

Are you sure you have both Maven and Servicemix on our PATH? Also make sure you typed the command correctly. For instance:
smx-arch su bean -DgroupId=com.chariotsolutions -DartifactId=myS1Pojo

Do you have all the -'s and ='s and check the character case?

They're the only things I can see that cause a problem. Give me more details and I'll try to help.

Anonymous said...

Doesn't work for me either. Works when using the way they do it in the official ServiceMix tutorials (sorry for blogger.com formatting the text in an ugly way):

mvn archetype:create -DarchetypeArtifactId=servicemix-jms-consumer-service-unit -DarchetypeGroupId=org.apache.servicemix.tooling -DartifactId=myJmsSu
mvn archetype:create -DarchetypeArtifactId=servicemix-eip-service-unit -DarchetypeGroupId=org.apache.servicemix.tooling -DartifactId=myStaticRoutingSlip
mvn archetype:create -DarchetypeArtifactId=servicemix-bean-service-unit -DarchetypeGroupId=org.apache.servicemix.tooling -DartifactId=myS1Pojo
mvn archetype:create -DarchetypeArtifactId=servicemix-bean-service-unit -DarchetypeGroupId=org.apache.servicemix.tooling -DartifactId=myS2Pojo
mvn archetype:create -DarchetypeArtifactId=servicemix-bean-service-unit -DarchetypeGroupId=org.apache.servicemix.tooling -DartifactId=myS3Pojo
mvn archetype:create -DarchetypeArtifactId=servicemix-service-assembly -DarchetypeGroupId=org.apache.servicemix.tooling -DartifactId=mySa

Tom Purcell said...

I just tried and both ways worked for me. Could you provide more info (version of SMX and Maven, actual message, what's your $PATH look like)?

Robert said...

Hi,
the command works with quotation marks:
smx-arch su jms-consumer "-DgroupId=de.mms" "-DartifactId=jms_consumer_su"

at least on my Windows box.

Tom Purcell said...

Thanks you, Robert. It may sound odd but I have very limited access to windows and do all my work in Linux. Thanks for figuring this out.

Imad Bougataya said...

I tried both ways and got the same result in terms of directory structure. The Maven way of generating the structure has the advantage of regrouping all the sub-projects in one: jms, eip, and beans are configured as modules of mySmTest. I think it makes more sense from an organisationnal point of vue