Thursday 31 October 2013

How to work with Spring JMS(Spring Integration Module)?



JMS Using Spring(JmsTemplate)


Spring provides the JMSTemplate class and this template helps us to avoid a lot of  boilerplate code for a JMS implementation. The following are some of the advantages provided by Spring framework when developing JMS applications for asynchronous messaging.


  • It provides a JMS abstraction API that simplifies the use of JMS to access the destinations (queues or topics) and publish messages to the specified destinations.
  • Java developers don't need to think about the differences between different JMS versions
  • In case if we are using spring JMS module then the developers don't need to specifically deal with JMS exceptions, as Spring provides an unchecked exception for any JMS exception that is re thrown in JMS code.
Many Java classes are available in spring framework in order to simplify the use of Spring JMS, once we start using spring in JMS applications then we will know about its simplicity for asynchronous messaging.

Spring JMS main classes available in the spring framework.

Class Name
Package
Function
JmsException
org.springframework.jms
This is the base (abstract) class for any exceptions thrown by Spring framework whenever there is a JMS exception.
JmsTemplate, JmsTemplate102
org.springframework.jms.core
These are helper classes used to simplify the use of JMS by handling the creation and release of JMS resources like connection factories, destinations, and sender/receiver objects. JmsTemplate102 is a subclass of JmsTemplate that uses the JMS 1.0.2 specification.
MessageCreator
org.springframework.jms.core
This is a callback interface used by the JmsTemplate class. It creates a JMS message for a specified session.
MessageConverter
org.springframework.jms.support.converter
This interface acts as an abstraction to convert between Java objects and JMS messages.
DestinationResolver
org.springframework.jms.support.destination
This is an interface used by JmsTemplate for resolving destination names. DynamicDestinationResolver and JndiDestinationResolver are the default implementations of this interface.
 


System Requirements:-
  •             Eclipse Editor or any other.
  •             JDK 1.5 or higher(I am using jdk 1.7.0_03)
  •             Spring jars version 2.5.5.
  •             Other related jars.
Note: - Apache Active MQ Setup is required for the execution of this example. For doing the Active MQ Setup please follow the below link:-


Required Jars:-

activemq-all-5.4.3.jar
xbean-spring-3.7.jar
activemq-pool-5.4.3.jar
commons-pool-1.5.4.jar
spring-tx.jar
spring-beans.jar
spring-context.jar
spring-context-support.jar
spring-core.jar
spring-jms.jar

Note: - I am referring spring framework 2.5.5/dist/modules directory jars.

Steps for creating Eclipse java project for implementing spring JMS:-


  • Create a java project named JMSUsingSpring



  • Create a package names com.gaurav.springjms.example in the src directory







  • Create a JMSTemplateTest class inside the package named com.gaurav.springjms.example.


  • Place the below available code in the JMSTemplateTest java file.

JMSTemplateTest.java

package com.gaurav.springjms.example;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;

public class JMSTemplateTest {
            public static void main(String args[]) throws JMSException {
                        ApplicationContext appContext = new ClassPathXmlApplicationContext(
                                                "JMSMessageListenerTest-Context.xml");
                        JmsTemplate jmsTemplate = (JmsTemplate) appContext
                                                .getBean("jmsTemplate");

                        jmsTemplate.send("TestQueueUsingSpringJMS", new MessageCreator() {

                                    @Override
                                    public Message createMessage(Session session) throws JMSException {

                                                TextMessage textMessage = session.createTextMessage();

                                                textMessage.setText("A Text Message from Spring JMS template By Kumar Gaurav ");
                                                return textMessage;

                                    }

                        });

                        System.out.println("Message sent successfully");

                        Message message = jmsTemplate.receive("TestQueueUsingSpringJMS");

                        if (message instanceof TextMessage) {
                                    TextMessage textMessage = (TextMessage) message;
                                    String text = textMessage.getText();
                                    System.out.println("Received :" + text);
                        } else {
                                    System.out.println("Received : " + message);
                        }

                        System.out.println("Message received successfully");

                        System.exit(1);
            }

}



  • Create an XML file names JMSMessageListenerTest-Context.xml in the classpath.


  • Place the below code in this file

JMSMessageListenerTest-Context.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:p="http://www.springframework.org/schema/p"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:jms="http://www.springframework.org/schema/jms" xmlns:amq="http://activemq.apache.org/schema/core"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/jms
                           http://www.springframework.org/schema/jms/spring-jms.xsd
                           http://activemq.apache.org/schema/core
                           http://activemq.apache.org/schema/core/activemq-core.xsd">
      <!-- the pooled ActiveMQ connection factory -->
      <bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
            <constructor-arg value="failover:(tcp://localhost:61616)" />
      </bean>

      <!-- configuring Spring JmsTemplate for sending messages -->
      <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <constructor-arg ref="connectionFactory" />
            <property name="sessionTransacted" value="false" />
            <property name="receiveTimeout" value="5000" />
      </bean>
      </beans>
                          
Note:-

  • Local resource transactions can simply be activated through the sessionTransacted flag on the listener container definition.
  • The property receiveTimeout specifies how long the receiver should wait before giving up waiting for a message.
  •  Default settings for JMS Sessions are "not transacted" and "auto-acknowledge". As defined by the J2EE specification, the transaction and acknowledgement parameters are ignored when a JMS Session is created inside an active transaction, no matter if a JTA transaction or a Spring-managed transaction. To configure them for native JMS usage, specify appropriate values for the "sessionTransacted" and "sessionAcknowledgeMode" bean properties.

  •  The Failover configuration syntax allows you to specify any number of composite uris. The Failover transport randomly chooses one of the composite URI and attempts to establish a connection to it. If it does not succeed or if it subsequently fails, a new connection is established to one of the other uris in the list.
                     Configuration Syntax
                                    failover:(uri1,...,uriN)?transportOptions
                                   or
                                   failover:uri1,...,uriN

  • The failover transport uses random by default which lets us to load balance clients over a number of brokers.
  • If we would rather connect to a primary first and only connect to a secondary backup broker if the primary is unavailable, turn off randomizing using something like
  • failover:(tcp://primary:61616,tcp://secondary:61616)?randomize=false
     
    Example:- 
     
    failover:(tcp://localhost:61616,tcp://remotehost:61616)
    ?initialReconnectDelay=100
     
    Here initialReconnectDelay is the transport option which means that  
    How long to wait before the first reconnect attempt (in ms)  
  •  More idea on failover please go through the below link:-
  •  Execute the JMSTemplateTest.java by selecting the option Run as Java Application. After Successful execution of this java file, the eclipse console will appear like below
         






  •  After Execution of this java file, we can see the status of ActiveMQ queue which is available as below:-