Keep JMS simple with Spring and MantaRay

Create a simple, distributed application framework

Almost from its inception, Java Platform, Enterprise Edition (Java EE is Sun's new name for J2EE) has been criticized for being too complex. One of the main problems is that developers must face 100 percent of Java EE's complexity even if they only need 20 percent of the services. In addition, some elements like Enterprise JavaBeans are so complex by themselves that they make the development process—especially deployment and configuration—a living hell.

To address these issues, several simpler frameworks, all intended to help developers, were created. One of the most promising and best known to date is Spring—a simple-to-use application framework that provides programmers with the same Java EE functionality they need, but with a fraction of the complexity and cumbersomeness.

As part of the core package, Spring provides a Java Message Service abstraction framework that simplifies the use of the JMS API and shields the user from differences between the JMS 1.0.2 and 1.1 APIs. A natural extension to Spring's messaging framework is MantaRay, open source, distributed messaging middleware designed for high-traffic, distributed environments.

Developed and maintained by Coridan, MantaRay supports both JMS APIs (1.1 and 1.02). Compared to traditional messaging systems, such as busses or brokers, MantaRay provides robustness, scalability, and better performance by eliminating the need for a centralized broker. MantaRay eliminates the single point of failure and the congestion of traditional models by using a peer-to-peer, server-less architecture, and optimized network transport implementations.

MantaRay's distributed architecture is lightweight, embeddable, and operating-system-agnostic, and plays a key role in enabling its OCC (occasionally connected computing) capability. Simply put, MantaRay can abstract applications from network failures by automatically switching to an offline mode, where messages are stored locally on the machine. When the sending machine reconnects to the network, these persisted messages are automatically sent to their original destination without any user involvement.

Here at the MantaRay project, we have been talking about the complexity of the Java EE framework for the last three years and have been striving to make our JMS implementation as simple as possible. Most of the credit belongs to our community members; they have provided invaluable advice on how to make MantaRay simple, with features such as automatic discovery and advanced configuration mechanisms, which include a working default configuration, and automatic IP and port selection.

We believe that the time is now right to take the next step and combine these two simple frameworks so that developers using the Spring Framework will be able to use MantaRay and JMS to get a simple, yet powerful, application framework.

Why integrate MantaRay with Spring?

One of Spring's strongest features is that developers do not need to install any piece of software to start using it. Most of Spring's functionality works without installing and configuring an application server (one of the horrors of Java EE mentioned above). Instead, developers are only required to import a Spring JAR with its dependencies, and they are good to go.

Using MantaRay is exactly the same: Developers do not need to install any messaging broker and configure it. They just import the MantaRay JAR and its dependencies, and start communicating through the standard JMS implementation.

Moreover, when adding more applications and more computers to messaging systems, a centralized environment forces developers to reinforce their brokers to handle the additional traffic and load. This is not the case with MantaRay. Developers just need to install the MantaRay framework on the additional applications in their system. That's all there is to it.

Because JMS is a well-known standard, it can easily be plugged in and out of any Java EE container or be used as a pluggable, standalone messaging framework. And since Spring has a pluggable architecture, developers can plug or map implementation into it (such as Hibernate). Developers can also plug a JMS provider into the framework quite easily. Thus, in effect, the combined solution ensures that no installation is required and no code needs to be changed.

Figure 1 provides a schematic overview of Spring's plugable nature, which is the core of its IoC (Inversion of Control) paradigm.

Figure 1. MantaRay integration with the Spring framework

Although JMS is not a particularly complex API, it is not the simplest either. To abstract the JMS API, Spring provides a simplified wrapper over it. Spring users can access MantaRay using this simplified wrapper or the complete JMS API.

MantaRay and Spring in a distributed/multitier environment

Distributed applications must be written for several reasons:

  1. High availability: Having one or more backup applications in case the main application, or its computer, crashes.
  2. Load balancing: Having the ability for several servers to share the load of requests while keeping a shared context.
  3. Security: In some network topologies, developers might not want to expose a backend application on the Internet. Instead, they opt to put some parts on a gateway or a frontend machine. For example, a developer might develop an application that provides online banking services, but expose only a subset of the bank's real back-office to the world.
  4. Functional requirements: Some applications, like instant messaging, chats, and even games, are distributed by nature.

As developers, we often encounter communication problems between two or more applications we write. This problem grows complex when the applications are not on the same computer or even in the same network. JMS is a preferred approach for distributed applications to communicate with each other in an asynchronous way.

Figure 2 presents a two-tier application. Tier one consists of the application's backend modules, whereas tier two is the front end. The frontend Web application, which is Spring-enabled, uses the JmsTemplate and by extension MantaRay to communicate with the backend application.

Figure 2. An example of a distributed application using Spring and MantaRay

MantaRay's "no server needed" architecture allows users who integrate it with Spring to use a full-blown JMS implementation, while continuing to benefit from Spring's lightweight architecture. By augmenting the Spring framework with a messaging solution that requires no additional servers, users can immediately start developing distributed/multitier applications, while still maintaining Spring's simplicity and ease of use.

How to integrate Spring with MantaRay

There are several different ways to configure MantaRay as a JMS provider in Spring. In this article, we demonstrate the easier configurations. MantaRay's integration process with Spring is purely a matter of standard Spring configuration.

Binding the JMS ConnectionFactory as a Spring bean

Spring beans are objects created by a BeanFactory, a sophisticated implementation of the Factory pattern that removes the need for programmatic singletons and allows you to decouple the configuration and specification of dependencies from your actual program logic. In other words, developers configure the object in an XML file, and the Spring Framework is responsible for creating it.

Developers may configure the MantaRay JMS ConnectionFactory to be used with their applicative beans in the Spring configuration file. The following XML fragment is an example of configuring the JMS ConnectionFactory as a Spring bean:

  <bean id="jmsFactory"
        class="org.mr.api.jms.MantaConnectionFactory"/>

Additionally, developers will need to set the system property mantaConfig to the location of the MantaRay configuration file. They will also need to add the MantaRay JAR and its dependencies to the classpath.

Now that everything has been configured, users can retrieve the MantaConnectionFactory from the Spring context using the following code fragment, which shows how to retrieve the JMS ConnectionFactory from Spring using its ApplicationContext:

 ClassPathXmlApplicationContext context = new 
   ClassPathXmlApplicationContext("spring-mantray.xml");
ConnectionFactory connectionFactory = (ConnectionFactory)context.getBean("jmsFactory")

Kicking it up a notch: Using Spring JMS templates

As we have seen, Spring provides a simpler messaging API as a wrapper. The JmsTemplate is a helper class that simplifies JMS access code and can be used with any JMS provider. Developers can configure the Spring JMS template using the jmsFactory bean we previously configured.

The following XML fragment shows how to configure a JMS template:

 <bean id="myJmsTemplate"
      class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory">
      <bean 
class="org.springframework.jms.connection.SingleConnectionFactory">
        <property name="targetConnectionFactory">
          <ref bean="jmsFactory"/>
        </property>
      </bean>
    </property>
<property name="defaultDestinationName"> 
            <value>defaultDestination</value>
        </property>
</bean>

A JMS template can be used for sending and receiving JMS messages. The subsequent example illustrates how a JMS sender and receiver use the Spring JMS template. The myJmsTemplate is wired into both beans: jmsSender and jmsReceiver. When declaring the jmsTemplate property, the Spring container passes the jmsTemplate to the jmsSender and jmsReceiver.

The following XML fragment shows how to configure a JMS template into a bean:

 <bean id="jmsSender"
    class="org.mr.spring.JmsSender">
    <property name="jmsTemplate">
        <ref bean="myJmsTemplate"/>
    </property>
</bean>
<bean id="jmsReceiver"
      class="org.mr.spring.JmsReceiver">
    <property name="jmsTemplate">
        <ref bean="myJmsTemplate"/>
    </property>
</bean>

The following class illustrates how JmsSender uses JmsTemplate to send a JMS message:

 

package org.mr.spring;

import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.MessageCreator; public class JmsSender { private JmsTemplate jmsTemplate;

public JmsTemplate getJmsTemplate() { return jmsTemplate; } public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void sendMessage() { jmsTemplate.send(new MessageCreator() { public Message createMessage(Session session) throws JMSException { return session.createTextMessage("Hello World"); } }); } }

The JmsSender class sends a JMS message using the jmsTemplate.send() method.

The following class is an example of JmsReceiver using JmsTemplate to receive a JMS message:

 

package org.mr.spring; import org.springframework.jms.core.JmsTemplate;

public class JmsReceiver{ private JmsTemplate jmsTemplate; public JmsTemplate getJmsTemplate() { return jmsTemplate; } public void setJmsTemplate(JmsTemplate jmsTemplate) { this.jmsTemplate = jmsTemplate; } public void reciveMessage() { try{ TextMessage msg = (TextMessage)jmsTemplate.receive(); System.out.println("Message received: " +msg.getText()); }catch(JMSException e){}

} }

The JmsReceiver class receives a JMS message using the jmsTemplate.receive() method. To run this example, developers should use the following code fragment, which loads the Spring configuration file for the example above:

 ClassPathXmlApplicationContext context = 
   new ClassPathXmlApplicationContext("spring-jms.xml"});
JmsSender jmsSender = (JmsSender) context.getBean("jmsSender");
jmsSender.sendMessage();
JmsReceiver jmsReceiver = (JmsReceiver) context.getBean("jmsReceiver");
msReceiver.receiveMessage();

Conclusion

The world is moving towards simplicity and ease of use, and away from complexity and cumbersomeness. Combining the simplicity of both Spring and MantaRay creates an application framework that is distributed, robust, and scaleable, while still easy to use and lightweight.

Amir Shevat is a senior software developer with eight years of experience in computing. He is an expert in Java development and has vast experience in C++, Symbian, PHP, as well as other programming languages. Formerly, he served as a senior software engineer in Comverse, and at present, he administers and leads the development team of Coridan open source projects. Yuval Lubowich is a senior software developer with more than 10 years of experience in computing. He is an expert in Java development, C++, and Visual Basic, as well as other programming languages. Formerly, he served as Coridan's chief architect, and before that, he managed several infrastructure teams at Comverse Technology. Presently, he is responsible for all of Cordian's R&D operations and open source initiatives.
1 2 Page 1
Page 1 of 2