Friday, March 1, 2013

JMS using Spring and ActiveMQ

In our previous post about (JMS using ActiveMQ), we learnt about JMS simple java example using Apache ActiveMQ. In this post, we will use Spring 3.0 to configure and use ActiveMQ server.
Setup ActiveMQ : Refer to the previous post (JMS using ActiveMQ) for ActiveMQ setup


Spring offers a JMS template that simplifies JMS code. Spring provides standard classes to configure Connection Factory, Queue, Topic in xml file as standard <bean> tag. To send a JMS message with  JMS template, we call the send() method and provide a message destination, as well as a MessageCreator object, which creates the JMS message you are going to send. The MessageCreator object is usually implemented as an anonymous inner class.
We need to include the library of the message broker in our classpath. download


To configure JMS Template, we have to perform the following steps.
  •  Configure a Connection Factory bean
  •  Configure a JMS destination bean, which can be either a queue or a topic.
  •  Configure a JMS Template bean

Step 1: Configure Connection Factory
Step 2: Configure JMS destination
Step 3: Configure a JMS Template bean

Now we are going to write our bean class for sending and receiving the message to/from the defined "mail.queue" destination.

MessageObject.java
This is our message class which will be used to carry message.
package com.sarf.data; 

public class MessageObject {
  private String mailId;
  private String message;
    
 public MessageObject(){}; 
 public MessageObject(String mailId, String message) {
  super();
  this.mailId = mailId;
  this.message = message;
 }
 public String getMailId() {
  return mailId;
 }
 public void setMailId(String mailId) {
  this.mailId = mailId;
 }
 public String getMessage() {
  return message;
 }
 public void setMessage(String message) {
  this.message = message;
 }
}

MessageProducerBean.java
package com.sarf.jms;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import com.sarf.data.MessageObject;

public class MessageProducerBean {

 //JMS Template object
 private JmsTemplate jmsTemplate;
 private Destination destination;
 public void setJmsTemplate(JmsTemplate jmsTemplate) {
     this.jmsTemplate = jmsTemplate;
 }
 public void setDestination(Destination destination) {
     this.destination = destination;
 }
 public void sendMessage(final MessageObject messageObj) {
  jmsTemplate.send(destination, new MessageCreator() {
  public Message createMessage(Session session) throws JMSException {
        MapMessage message = session.createMapMessage();
        message.setString("mailId", messageObj.getMailId());
        message.setString("message", messageObj.getMessage());
        return message;
       }
  }); //send method close here
 }//method ends here 
}
We are obtaining JmsTemplate and Destination objects using setter injection(see appContext.xml). In the sendMessage() method,We are creating a anonymous class of type MessageCreator by extending MessageCreator interface and defining the createMessage() method which in turn return MapMessage object.
The MessageCreator interface declares only a createMessage() method to implement.

MessageConsumerBean.java
package com.sarf.jms;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.JmsUtils;
import com.sarf.data.MessageObject;

public class MessageConsumerBean{

 private JmsTemplate jmsTemplate;
 private Destination destination;
  
 public void setJmsTemplate(JmsTemplate jmsTemplate) {
     this.jmsTemplate = jmsTemplate;
 }
 public void setDestination(Destination destination) {
     this.destination = destination;
 }
 
 public MessageObject receiveMessage() {
  MapMessage message = (MapMessage) jmsTemplate.receive(destination);
  try {
       MessageObject messageObj = new MessageObject();
       messageObj.setMailId(message.getString("mailId"));
       messageObj.setMessage(message.getString("message"));
       return messageObj;
       } catch (JMSException e) {
         throw JmsUtils.convertJmsAccessException(e);
       }
   }
}
To receive a JMS message with a JMS template, we call the receive() method by providing a message destination. This method returns a JMS message whose type is the base JMS message type, an interface, javax.jms.Message, so we are casting it into proper type before further processing.

appContext.xml




ProducerTest.java

package com.sarf.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sarf.data.MessageObject;
import com.sarf.jms.MessageProducerBean;

public class ProducerTest {   
 public static void main(String[] args) {
   ApplicationContext context =
     new ClassPathXmlApplicationContext("appContext.xml");
     MessageProducerBean mp = 
      (MessageProducerBean) context.getBean("producer");
     mp.sendMessage(new MessageObject("1234", "Test Message"));
   } 
}

ConsumerTest.java
package com.sarf.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sarf.data.MessageObject;
import com.sarf.jms.MessageConsumerBean;

public class ConsumerTest {
 public static void main(String[] args) {
    ApplicationContext context =
      new ClassPathXmlApplicationContext("appContext.xml");
    MessageConsumerBean mc = 
     (MessageConsumerBean) context.getBean("consumer");
    MessageObject messageObj = mc.receiveMessage();
    System.out.println("Message from " + 
     messageObj.getMailId() + " received");
    }
}