Messaging
Messaging means, such behavior like this:
a message producer writes a message into the message channel, and a message receiver will consume the message from the message channel asynchronously.
In many messaging systems, MQ based message broker is used.
GigaSpaces has such feature of messaging, called messaging grid.
GigaSpaces also supprts JMS implementation, which means that GigaSpaces can be used to transport JMS messages.
For instance, an application in a messaging system has connections with MQ to send JMS messages.
But with some reasons for accepting massive transactions or the requirement of low latency, GigaSpaces can be used instead of MQ.
The JMS source codes in that application do not have to be modified, because GigaSpaces in this case is used as message bus with JMS implementation.
In the next sections, I will show an example which is run with Active MQ and with GigaSpaces without source code modification.
Pipeline Overview
- Client Service writes order request into the jms queue with the address 'jms://queue.stage.0'.
- Account Service will consume the order, process it and write the processed order into 'jms://queue.stage.1'.
- Like Account Service, Inventory Service and Shipping Service will do the same, that is, consume, process, and write.
In the above figure, Messsage Bus can be considered as MQ or Space of GigaSpaces.
Required Softwares
In pipeline example, the following softwares listing below are used:
Spring Framework is popular enterprise development framework, and it has such characteristic of Dependency Injection(IOC), AOP, and Service Abstraction.
Mule is EIP(Enterprise Integration Patterns) based open-source ESB(Enterprise Service Bus) Framework. Mule supports a lot of protocols / transports to integrate other enterprise applications very easily.
Component
In Mule, the component is a POJO which is responsible for business logic.
As you can see in the example source code, there is no codes for the underlying connectivity to JMS in the components. It has the advantages of the feature of loosely-coupled and reusable components.
With Mule, the connectivity is seperated from the business logic(components). The connectivity can be freely configured in the xml and changed without affecting the components.
A component can be exposed as a service with the combination of connectivity.
Thus service consists of in/out bound(Connectivity) and component.
Note that component can be exposed as a lot of different services, because even if component is responsible just for the same business logic, different connectors can be used in in/out bounds.
Here is source snippet of component:
package com.ktf.khub.samples.grid.messaging.pipeline.service; import com.ktf.khub.samples.grid.messaging.pipeline.domain.Order; public class OrderAccountingProcessorService implements OrderProcessor { public Order process(Order order) { System.out.println("processing order " + order); order.setPhase(new Integer(order.getPhase().intValue() + 1)); return order; } }
In/Out bound
In Mule, In/Out bound refers to the connectivity. In our example, JMS is used to transport the messages.
The following shows in/out bound configuration in mule:
<inbound> <inbound-endpoint ref="queueStage0" transformer-refs="JMSMessageToObject" /> </inbound> ... <outbound> <outbound-pass-through-router> <outbound-endpoint ref="queueStage1" transformer-refs="ObjectToJMSMessage" /> </outbound-pass-through-router> </outbound>
Service
As mentioned, in mule, a service is composed of in/out bounds and component.
A service can be accessed via a lot of different protocols, even though the business logic is the same.
The mule configuration for a service is like this:
<service name="orderAccountingService"> <inbound> <inbound-endpoint ref="queueStage0" transformer-refs="JMSMessageToObject" /> </inbound> <component class="com.ktf.khub.samples.grid.messaging.pipeline.service.OrderAccountingProcessorService" /> <outbound> <outbound-pass-through-router> <outbound-endpoint ref="queueStage1" transformer-refs="ObjectToJMSMessage" /> </outbound-pass-through-router> </outbound> </service>
As you see, inbound, component, outbout elements reside in service element.
- From inbound, the incoming request is consumed.
- In component, the incoming request is processed.
- After processing, write the response to the outbound.
In the above, component element can have a reference to a spring bean to which such facade implementation is injected.
The mule service is like a small application. With the combination of the multiple mule services, messages can be routed between applications with very ease.
Run Pipeline example with Active MQ
To run pipeline example, first download pipeline.zip.
After unzipping pipeline.zip, the structure of pipline looks like this:
<pipeline>
|
+ -- bin: executable files.
|
+ -- lib
| |
+ + -- gigaspaces: GigaSpaces 6.5 libraries.
| |
+ + -- mule: Mule 2.0 libraries.
| |
+ + -- spring: Spring 2.5.x libraries.
|
+ -- src
|
+ -- main
|
+ -- java: Java Source.
|
+ -- resources
|
+ -- META-INF
|
+ -- spring: Spring XMLs.
Note that in <pipeline>/lib, all the required libraries should be copied for GigaSpaces, Mule, Spring.
Before running example, some modification is required.
Open <pipeline>/bin/set-env.bat, modify the following lines:
rem ===================================================
rem set the GigaSpaces home.
rem ===================================================
@set JSHOMEDIR="D:\project\action-khub-samples\apps\3rd-parties\giga-spaces\GigaSpacesXAP6.5M8"
set the correct GigaSpaces installation directory.
And open <pipeline>/bin/start-activemq.bat, modify the active mq home directory:
rem ===================================================
rem Set Active MQ Home.
rem ===================================================
@set ACTIVEMQ_HOME="D:\project\action-khub-samples\apps\3rd-parties\activemq\apache-activemq-4.1.1"
Now, see the <src>/main/java/com/ktf/khub/samples/grid/messaging/pipeline/service/MessagingGridRunner.java
and modify the source like this:
package com.ktf.khub.samples.grid.messaging.pipeline.service; ... public class MessagingGridRunner { private final static String[] SPRING_XML_FOR_SPACE = { "META-INF/spring/spring-service-jms-space-context.xml", "META-INF/spring/spring-space-context.xml", "META-INF/spring/spring-tx-context.xml" }; private final static String[] SPRING_XML_FOR_ACTIVEMQ = { "META-INF/spring/spring-service-jms-activemq-context.xml" }; public static void main(String[] args) throws Exception { sendWithJms(); } private static void sendWithJms() throws InitialisationException, ConfigurationException, MuleException { MuleContextFactory muleContextFactory = new DefaultMuleContextFactory(); MuleContext context = muleContextFactory .createMuleContext(new SpringXmlConfigurationBuilder( SPRING_XML_FOR_ACTIVEMQ)); context.start(); MuleClient muleClient = new MuleClient(); for (int i = 0; i < 10; i++) { Order order = new Order(i, "An Order Bean", new Integer(0)); System.out.println("Input Order bean: " + order); muleClient.sendAsync("jms://queue.stage.0", order, null); } } }
As you see in sendWithJms(), MuleContext will load the Spring xml 'META-INF/spring/spring-service-jms-activemq-context.xml' listed in SPRING_XML_FOR_ACTIVEMQ.
After that, mule client send Order messages into the queue with the address 'jms://queue.stage.0'.
Now, it is ready to run the example. Follow the next steps:
- open a command window and change the directory to <pipeline>, and type 'ant' in it. Ant will build our example project.
- change to <pipeline>/bin, and run start-activemq.bat to run Active MQ.
- change to <pipeline> in the command window, and type 'ant run-app' in the command to run 'MessagingGridRunner' above.
In this example, we have seen that JMS messages are transported via Active MQ.
Run Pipeline example with Space
To run pipeline example with space, some similar steps like with Active MQ above should be followed.
Make sure GigaSpaces Home is set correctly. And in this case, Active MQ Home setting is not necessary.
Just modify the following code snippet in MessagingGridRunner like this:
package com.ktf.khub.samples.grid.messaging.pipeline.service; ... public class MessagingGridRunner { private final static String[] SPRING_XML_FOR_SPACE = { "META-INF/spring/spring-service-jms-space-context.xml", "META-INF/spring/spring-space-context.xml", "META-INF/spring/spring-tx-context.xml" }; private final static String[] SPRING_XML_FOR_ACTIVEMQ = { "META-INF/spring/spring-service-jms-activemq-context.xml" }; public static void main(String[] args) throws Exception { sendWithJms(); } private static void sendWithJms() throws InitialisationException, ConfigurationException, MuleException { MuleContextFactory muleContextFactory = new DefaultMuleContextFactory(); MuleContext context = muleContextFactory .createMuleContext(new SpringXmlConfigurationBuilder( SPRING_XML_FOR_SPACE)); context.start(); MuleClient muleClient = new MuleClient(); for (int i = 0; i < 10; i++) { Order order = new Order(i, "An Order Bean", new Integer(0)); System.out.println("Input Order bean: " + order); muleClient.sendAsync("jms://queue.stage.0", order, null); } } }
In this case, from the spring xmls of SPRING_XML_FOR_SPACE, mule context will load all the mule services.
To run the example, follow the next:
- open a command window and change the directory to <pipeline>, and type 'ant' in it. Ant will build our example project.
- change to <pipeline>/bin, and run start-part-*.bat to run all the partitioned spaces.
- run start-jini-tx.bat to run jini transaction manager.
- change to <pipeline> in the command window, and type 'ant run-app' in the command to run 'MessagingGridRunner' above.
All the JMS messages are transported through the partitioned spaces.
Conclusion
We have seen that JMS messaging via Active MQ or via Space has been done.
The source codes in components have not been modified to satisfy such requirement to do messaging through Active MQ or Space.
Just some configuration change of spring xml makes our pipeline application portable to run with MQ and Space.
Attachment
- Pipeline Source Codes: pipeline.zip





