Saturday, October 4, 2014

Caching with Spring Hibernate - EHCache Basic



Caching is basic concept in ORM which keeps a representation of current database state close to the application, either in memory or on disk of the application server machine.

Cache is a local copy of the data which sits between application and the database. Caching mechanism operates at different levels and types. In general, there are three main types of cache.
  • Transaction scope cache : First-level cache is at the transaction level or the unit of work. It’s valid and used as long as the unit of work runs. It corresponds to one session in Hibernate for a single request and is by default enabled for the Hibernate session.  
  • Process scope cache : This type of cache is shared  between  many units  of work  or  transactions. 
  • Cluster scope cache : Shared  between  multiple  processes  on  the  same machine or between multiple machines in a cluster.

Hibernate has a two-level cache architecture:
  • First-level cache : This is persistence context cache. This is at the unit-of-work level. It corresponds to one session in Hibernate for a single request and is by default enabled for the Hibernate session. 
  • Second-level cache : This is either at the process scope or the cluster scope. This is the cache of the state of the persistence entities. At the second-level cache, all persistence contexts that have been started from the same SessionFactory share the same cached data.

In this post, we are going to implement a simple second level caching application to demonstrate the configuration  of second level caching.

There are different policies which can be configured for second level caching.
- Whether the second-level cache is enabled
- The Hibernate concurrency strategy
- Cache expiration policies
- The physical format of the cache (memory, indexed files, or cluster-replicated)



We are going to configure second-level cache at process scope using hibernate JPA and ehCache cache provider.

As usual we will create a simple Employee entity and demonstrate caching mechanism. We have annotated our entity with  @Cacheable annotation which makes entity eligible for caching. JPA2 provides @Cacheable annotation to instruct persistence provider to decide which entity to be cached.
Employee.java
package com.sarf.domain;
import java.io.Serializable;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Cacheable
@Entity
@Table(name = "employee")
public class Employee implements Serializable {

 private static final long serialVersionUID = 1L;
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "employeeId")
 private int employeeId;
 
 @Column(name = "employeeName")
 private String employeeName;

 //Setter and getter for fields
}

After setting the entity as cacheable, we need to provide an appropriate caching mechanism to be used by the persistence provider in persistence.xml. <shared-cache-mode> XML element is used to configure cache mode for the entire persistence unit. ENABLE_SELECTIVE indicates that caching is enabled for all entities specified as @Cacheable(true).
Below xml elements to configure Hibernate for second level caching and second level cache provider.
So our final persistence.xml will look like this
persistence.xml
As usual, we will have a spring data repository as DAO layer . @QueryHint is used to indicate persistence provider that we want to cache the query result.
EmployeeRepository.java

package com.sarf.repository;

import java.util.List;
import javax.persistence.QueryHint;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.stereotype.Repository;
import com.sarf.domain.Employee;

@Repository()
public interface EmployeeRepository 
  extends JpaRepository<Employee, Integer> {
 
  @Query(value="select e from Employee as e ")
  @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") })
  List<Employee> findAllEmployees();
}
Our service layer will have two methods, namely getEmployees() and updateEmployee()
SarfService.java
package com.sarf.service;
import java.util.List;
import com.sarf.domain.Employee;

public interface SarfService {
 public List getEmployees();
 public void updateEmployee();
}
SarfServiceImpl.java
package com.sarf.service;

import java.util.List;
import java.util.UUID;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sarf.domain.Employee;
import com.sarf.repository.EmployeeRepository;

@Service("sarfService")
@Transactional
public class SarfServiceImpl{
  
  static final Logger logger = Logger.getLogger(SarfServiceImpl.class);  
 
  @Autowired
  private EmployeeRepository employeeRepository;
 
  public List<Employee> getEmployees() {
   logger.info("Fetching all employees");
   List<Employee>  employeeList = 
    employeeRepository.findAllEmployees();
   logger.info("Fetched all employees successfully");
   return employeeList;
  }

  public void updateEmployee() {
   Employee employee = this.employeeRepository.findOne(1000);
   employee.setEmployeeName(UUID.randomUUID().toString());
   this.employeeRepository.save(employee);
   logger.info("Employee with id 1000 updated successfully");
  }
}
 Click here to get source code

Saturday, September 27, 2014

JMS Topic using Spring and Active MQ

In our previous JMS posts, We learnt about creating JMS Queue, sending message and receiving message from Queue using Active MQ Broker. In this post, we are going to learn how to implement topic using Spring for Active MQ broker.



As we know from our previous post, A JMS client is an application that uses the services of the message broker. There are two types   of clients, Consumer and Producer. Destinations are the place where message get stored for clients. They can be either queues or topics.

In publish/subscribe model, client which produces message is called Publisher and client which consumes message is known as Subscriber.
Topic is a particular destination where Publisher publishes messages. Subscribers subscribe to topic to consume messages. More than one Subscribers can subscribe to same topic and a message can be consumed by many subscribers.


We are going to divide our publisher and subscriber implementation in two part. First we will learn how to create topic and publish a message [XML as String] into topic.

Apache MQ fully supports Spring for configuration of client and message broker. So we will leverage <amq:> tag in our implementation.
As usual we will create Spring JMS template configuration in our spring context file by following these three steps.

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

Note : JmsTemplate is designed for use with Java EE containers which  provide connection pooling capabilities as standardized by the Java EE specifications. So in Non J2EE container, every call to the JmsTemplate.send() method  creates and destroys all the JMS resources (connections, consumers, and producers).
So, In non J2EE container, You should use a pooled connection factory for sending messages with JmsTemplate.
Apache MQ pointed this problem as JmsTemplate gotchas

As we already know, our producer context xml file will look like this.
appProdContext.xml
We will define our producer bean and leverage Spring JMS template to send message to destination topic.

MessageProducerBean.java
package com.sarf.jms;

import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.jms.core.MessageCreator;
import org.springframework.jms.core.support.JmsGatewaySupport;

public class MessageProducerBean extends JmsGatewaySupport{
  //Method receives String object and send
  //it to destination topic as BytesMessage
  public void sendMessage(final String myMessage) {
   getJmsTemplate().send(new MessageCreator() {
   public Message createMessage(Session session) throws JMSException {
   //Create byte message
   BytesMessage message = session.createBytesMessage();
   message.writeBytes(myMessage.getBytes());
   return message;
   }
   });
 }
}

To send a xml message to destination topic, we will use a simple main class ProducerTest.
ProducerTest.java
package com.sarf.main;

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

public class ProducerTest {   
 public static void main(String[] args) {
    ApplicationContext context =
     new ClassPathXmlApplicationContext("appProdContext.xml");
     MessageProducerBean mp = (MessageProducerBean) 
                  context.getBean("producer");
     String msg = "skhan"+
      "Hello Topic!";
     mp.sendMessage(msg);
     System.out.println("Message sent to destination");
     } 
}
---------------------------------------------------------------------------------------------------
Now we will focus on implementing our subscriber which will consume XML and convert it to MessageObject using Spring OXM (Object XML Mappers).

Our MessageObject class will look like this
MessageObject.java
package com.sarf.data; 

import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "MessageObject")
public class MessageObject implements Serializable{
 
  @XmlElement(name = "mailId")
  private String mailId;
  
  @XmlElement(name = "message")
  private String 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;
 }
}

As we configured publisher, we will configure subscriber in our appConsumerContext.xml file.

Step 1: Configure Connection Factory
Step 2: Declare OXM JAXB Marseller bean
Step 3: Declare Message Converter bean

We register the MarshallingMessageConverter to use the JAXB2 marshaller for both marshaller abd unmarshaller. This converter bean will be used by spring message listener container to convert incoming message which contains XML into MessageObject using Spring OXM JAXB.

Step 4: Declare Consumer bean 
Step 5: Define JMS Listener 

Message listener container is used to receive messages from a JMS message queue/topic. Here we are creating a message listener container which is using consumer bean reference to delegate messages on onMessage() method.

So our final appConsumerContext.xml will look like
appConsumerContext.xml
After having this configuration file, Now its time to look at our Message Converter class and message consumer class.
MyMarshallingMessageConverter.java
package com.sarf.util;

import javax.jms.JMSException;
import javax.jms.Message;
import org.springframework.jms.support.converter.MarshallingMessageConverter;
import org.springframework.jms.support.converter.MessageConversionException;

public class MyMarshallingMessageConverter 
 extends MarshallingMessageConverter {
  @Override
  public Object fromMessage(Message message) 
     throws JMSException, MessageConversionException{
      return super.fromMessage(message);
   }
}
MessageConsumerBean.java
package com.sarf.jms;
import com.sarf.data.MessageObject;

public class MessageConsumerBean {
 public void onMessage(MessageObject message) {
  try {
      System.out.println("Mail # "+message.getMessage()+" received.");
      } catch (Exception e) {
 e.printStackTrace();
 }
  }
}

We will use this simple ConsumerTest class to initialize the application context in main method to listen to topic.
ConsumerTest.java
package com.sarf.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ConsumerTest {
 public static void main(String[] args) {
    ApplicationContext context =
     new ClassPathXmlApplicationContext("appConsumerContext.xml");
     System.out.println("Consumer listening !!!!!!");
   }
}

 Click here to get source code

Sunday, May 11, 2014

Spring web application on WildFly


In this post, we are going to build a simple spring web application and deploy it in WildFly 8 application server. WildFly formerly know as JBoss Application Server. This release is Java EE7 certified, supporting both the Web and the Full profiles.


We are going to leverage the default data source defined in the Wildfly 8 for H2 in memory database. If you open standalone.xml file under the following directory wildfly-8.0.0.Final\standalone\configuration, You can see the following entry for the data source.
If you want to define your own data source for Oracle, MySQL etc. You can introduce one datasource element by filling necessary details along with JNDI name

Step 1: We will use the above JNDI to create our datasource bean in Spring configuration as:
Step 2: Container Managed Entity Manager will be used in our application to demonstrate the configuration of container managed entity manager in WildFly 8.
We will create a enity manager factory by looking up the JNDI registered as java:comp/env/persistence/my-emf in WildFly Application Server.

Step 3: To enable application that uses a server deployed persistence unit, It must register persistence context's or the persistence unit's JNDI via web.xml as follows:
JNDI binding
JNDI binding via persistence.xml properties is not supported in JBoss AS 7.0
Migration Guide for spring

Our Spring application context will look like this.
appContext.xml
Complete version of appContext.xml is available in source code


Now here we have one sample application consist of a REST Service "EmployeeRestService", one service class "EmployeeService" and Spring Data JPA Repository "EmployeeRepository" as DAO layer which in tern talk to underlying database.



Now we will start writing some code to understand our application implementation.
We will keep our entity as simple as possible. We will create a Employee POJO for our example as:
Employee.java
package com.sarf.domain;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@Table(name = "employee")
public class Employee implements Serializable {

 private static final long serialVersionUID = 1L;
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "employeeId")
 private int nEmployeeId;
 @Column(name = "employeeName")
 private String strEmployeeName;

 //Setter and Getter methods
}

We will define DAO layer as Spring Data Repository class which will perform CRUD operations for us 

EmployeeRepository.java
package com.sarf.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.sarf.domain.Employee;

@Repository()
public interface EmployeeRepository 
 extends JpaRepository<Employee,integer> {
 }

Our service class will perform employee entry and retrieval of employees
EmployeeService.java
package com.sarf.service;

import java.util.List;
import com.sarf.domain.Employee;

public interface EmployeeService {
 public void addEmployee(String emolpyeeName);
 public List<Employee> getEmployees();
}

EmployeeServiceImpl.java
package com.sarf.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sarf.domain.Employee;
import com.sarf.repository.EmployeeRepository;

@Service("employeeService")
@Transactional
public class EmployeeServiceImpl implements EmployeeService {

 @Autowired
 private EmployeeRepository employeeRepository;

 /** {@inheritDoc} */
 public void addEmployee(final String employeeName) {
  final Employee e = new Employee();
  e.setStrEmployeeName(employeeName);
  this.employeeRepository.saveAndFlush(e);
 }
 public List<Employee> getEmployees() {
  return this.employeeRepository.findAll();
 }
}

REST full service will define two operations : addEmployee and getEmployees
EmployeeRestService.java
package com.sarf.restservice;

import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.sarf.domain.Employee;

@Path("/employee-service/")
@Produces(MediaType.APPLICATION_JSON)
public interface EmployeeRestService {

 @POST
 @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
 @Path("addEmployee")
 public void addEmployee(@FormParam("employeeName") String employeeName);

 @GET
 @Consumes(MediaType.APPLICATION_JSON)
 @Path("getEmployees")
 public List<Employee> getEmployees();
}


EmployeeRestServiceImpl.java
package com.sarf.restservice;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sarf.domain.Employee;
import com.sarf.service.EmployeeService;

@Service
@Transactional
public class EmployeeRestServiceImpl implements EmployeeRestService {
 @Autowired
 private EmployeeService employeeService;

 public void addEmployee(final String employeeName) {
  this.employeeService.addEmployee(employeeName);
 }

 public List<Employee> getEmployees() {
  final List<Employee> listEmployee = 
  this.employeeService.getEmployees();
  return listEmployee;
 }
}

Our final persistence.xml will look like

persistence.xml


web.xml
data.sql
 Click here to get source code

Monday, March 11, 2013

Message Driven POJO using Spring and ActiveMQ

As we saw in our previous JMS with spring post, we used synchronous reception of JMS message from Queue.

When we call the receive() method on a JMS message consumer to receive a message, the calling thread is blocked until a message is available. During the duration, the thread can do nothing but wait.

The previous posts on JMS are as follow


In this post, we are going to look at Spring's feature for asynchronous reception of JMS Messages.

Starting with EJB 2.0, a new component called a message-driven bean (MDB) was introduced for asynchronous reception of JMS messages. An EJB container can listen for JMS messages at a message destination and trigger MDBs to react to these messages so that your application no longer has to wait for messages. Refer EJB3.0 specification


Message Driven Beans(MDB) can listen for JMS messages and  they must be deployed in an EJB container to run.  But Spring facilitates us to add the same capability to POJOs (declared in its IoC container) so that they can listen for JMS messages without an EJB container. We  called these bean as message-driven POJOs (MDPs).

A Message Driven POJO (MDP) is a simple java object which implements the javax.jms.MessageListener interface. MessageListener interface has one method onMessage() which need to be implemented by MDP. When a JMS message arrives, the onMessage() method will be called with the Message as the method argument.

This is our old Message Consumer class which has been modified to make it MDB.
MessageConsumerBean.java
package com.sarf.jms;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;

public class MessageConsumerBean implements MessageListener{
  public void onMessage(Message message) {
  MapMessage mapMessage = (MapMessage) message;
  try {
      String strEmail = mapMessage.getString("mailId");
      System.out.println("Mail #"+strEmail+" received.");
      } catch (JMSException e) {
  e.printStackTrace();
      }
  }
}



Step 1 : Now we have to configure our MDP in our bean configuration file as
Step 2 : Declaring MDP bean alone is not enough to listen for JMS messages. We need a message listener container to monitor JMS messages at a destination and trigger our message listener on message arrival.
Spring provides several types of message listener containers and we are using SimpleMessageListenerContainer  for our example.

So final version of our bean configuration file will look like this.
appContext.xml
This is our producer class MessageProducerBean.java
package com.sarf.jms;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.jms.core.MessageCreator;
import org.springframework.jms.core.support.JmsGatewaySupport;
import com.sarf.data.MessageObject;

public class MessageProducerBean extends JmsGatewaySupport{
 public void sendMessage(final MessageObject messageObj) {
  getJmsTemplate().send(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;
  }});
 }
}

Our producer Test class will look like this which will start the container as well as it will send a message to destination.
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("34", "Test Message"));
   } 
}
 Click here to get source code

Saturday, March 2, 2013

Spring JMS Message Converter

Spring’s JMS template helps us to convert JMS messages to and from Java objects using a message converter. By default, the JMS template uses SimpleMessageConverter for converting TextMessage to/from a string etc. Spring's JMS provides an interface MessageConverter  to create a custom message converter by implementing  fromMessage() and toMessage() methods.
Setup ActiveMQ : Refer to the previous post (JMS using ActiveMQ) for ActiveMQ setup
 In our previous post(JMS using Spring and ActiveMQ), we saw how to create a simple application using Spring's JMS API and Apache ActiveMQ. In this post, we are going to learn about user defined message converter and its usage.
              We need to include Apache ActiveMQ library in our classpath . download


In our previous post, we saw how to send message and consume it from destination. We also witnessed that we were converting the MessageObject into MapMessage for sending and MessageObject from MapMessage while consuming as:
MapMessage message = session.createMapMessage();
message.setString("mailId", messageObj.getMailId());
message.setString("message", messageObj.getMessage());

This is our Plain old java class which will serve as our message Object. MessageObject.java
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;
 }
}



Create Custom Message Converter

Step 1 : We are going to write our customer message converter namely MyMessageConverter.java. This class will implement MessageConverter interface and provide implementation for methods  fromMessage() and toMessage( ). Method fromMessage() is responsible for converting a JMS Message to User Obect and method toMessage() is responsible for converting a User Object to JMS Message as shown below ;

MyMessageConverter.java
package com.sarf.util;

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

import org.springframework.jms.support.converter
 .MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import com.sarf.data.MessageObject;

public class MyMessageConverter implements MessageConverter{
 public Object fromMessage(Message message) 
  throws JMSException,MessageConversionException {
  MapMessage mapMessage = (MapMessage) message;
  MessageObject messageObject = new MessageObject();
  messageObject.setMailId(mapMessage.getString("mailId"));
  messageObject.setMessage(mapMessage.getString("message"));
  return messageObject;
 }

 public Message toMessage(Object object, Session session) 
  throws JMSException,MessageConversionException {
  MessageObject messageObject = (MessageObject) object;
  MapMessage message = session.createMapMessage();
  message.setString("mailId", messageObject.getMailId());
  message.setString("message", messageObject.getMessage());
  return message;
  } 
}
Step 2 : We will create a bean for custom message converter and inject it into JMS Template bean as When we set custom message converter in JMS template explicitly, it overrides the default SimpleMessageConverter.


The full version of appContext.xml will look like : appContext.xml

After creating and configuring custom message converter, we can call the JMS template’s convertAndSend() and receiveAndConvert() methods to send and receive MessageObjecct objects in our MessageProducerBean.java and MessageConsumerBean.java as defined below:

Our producer and consumer classes are extending JmsGatewaySupport to retrieve a JMS template. We can get JMS Template using getJmsTemplate() method. 

MessageProducerBean.java
package com.sarf.jms;

import org.springframework.jms.core.support.JmsGatewaySupport;
import com.sarf.data.MessageObject;
public class MessageProducerBean extends JmsGatewaySupport{
 public void sendMessage(final MessageObject mail) { 
  getJmsTemplate().convertAndSend(mail);
 }
}

MessageConsumerBean.java
package com.sarf.jms;

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

public class MessageConsumerBean extends JmsGatewaySupport{
 public MessageObject receiveMessage() {
   return (MessageObject) getJmsTemplate().receiveAndConvert();
 }
}



We will write plain main method  in Producer class to send Message to a Queue and consume it using Consumer class.

ProducerTest
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("34", "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 mail = mc.receiveMessage();
   System.out.println("Mail from #" + mail.getMailId() + " received");
   }
}
Check JMS Post: 

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");
    }
}

Wednesday, February 27, 2013

JMS using ActiveMQ


We discussed and learnt about JMS using EJB3.0 in our previous post Message Driven Bean in EJB3.0. Now in this post, we will explore plain java based JMS implementation using  Apache ActiveMQ.


Java Message Service (JMS) is a Java Message Oriented Middleware (MOM) API for sending messages between two or more clients. 
There are four main components which make the JMS system.



1. Client - A JMS client is an application that uses the services of the message broker. There are two types   of clients, Consumer and Producer. Producers create messages and send or publish them to the broker for delivery to a specified destination.Consumers retrieve messages from a destination.
2. Message Broker(Server) - A JMS Broker is a system which provides clients with connectivity and message storage/delivery services. It maintains a list of queues and topics for which applications can connect to and send and receive messages.
3. Destination - Destinations are the place where message get stored for clients. They can be either queues or topics. 
4. Message - A messages is an object that contains the required heading fields, optional properties, and data payload being transferred between JMS clients.

In JMS, a producer connects to an MQ server and sends a message to a destination(queue or topic). A consumer also connects to the MQ server and listens to destination(a queue or topics) for messages of interest.

To develop and test a JMS application, Message Broker is required. For our example, we will use the Apache ActiveMQ server (activemq.apache.org), which is an open source MQ server. 


Setting Up ActiveMQ 
Step 1: Download the latest release from ActiveMQ web site (activemq.apache.org/download.html) and extract the archive into a folder on your computer.

Step 2: Upon extraction, navigate to the bin folder, and run the activemq command  as
                                     apache-activemq-5.5.1\bin>activemq.bat                                          
The server will be started, and upon completion, you will see that the ActiveMQ server is listening to port 61616 for a JMS connection.

Step 3: Open your browser and type the following address http://localhost:8161/admin/
             Browser will open admin page of ActiveMQ as below image

Step 4: We can create queue and topic using ActiveMQ admin page. Click on Queues menu visible after Home|Queues. Then type the queue name in text box and click on Create button.
A queue should be visible as shown in the below figure.                



How To DO
To send or receive a JMS message, we have to perform the following tasks in our code.
  •  Create a JMS connection factory on a message broker.
  •  Create a JMS destination, which can be either a queue or a topic.
  •  Open a JMS connection from the connection factory.
  •  Obtain a JMS session from the connection.
  •  Send/receive the JMS message with a message producer/consumer.
  •  Handle JMSException, which is a checked exception that must be handled.
  •  Close the JMS session and connection.

To send/receive JMS messages to/from a JMS message broker, we have to include the library of the message broker in our classpath. download


MessageProducerTest.java
package com.sarf.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MapMessage;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import com.sarf.data.MessageObject;

public class MessageProducerTest{

  public void sendMessage(MessageObject mail) {
    //Step 1: Create Connection Factory
    ConnectionFactory cf = 
       new ActiveMQConnectionFactory("tcp://localhost:61616");
    //Step 2: Define Destination
    Destination destination = new ActiveMQQueue("mail.queue");
    Connection conn = null;
    try{
 //Step 3: Create connection from connection factory
 conn = cf.createConnection();
 //Step 4: Create session
 Session session = conn.createSession(false,Session.AUTO_ACKNOWLEDGE);
 //Step 5: Create Message Producer for destination queue
 MessageProducer producer = session.createProducer(destination);
 //Step 6: Create Message
 MapMessage message = session.createMapMessage();
 message.setString("mailId", mail.getMailId());
 message.setString("message",mail.getMessage());
    //Step 7: Send message
 producer.send(message);
 session.close();
 }catch(Exception e) {
   e.printStackTrace();
 }
   }
}
In the preceding sendMessage() method, we are creating ConnectionFactory using message broker URL and Destination objects for user created queue (mail.queue). Then we are creating a connection, session, and message producer to send message to destination queue. In step 6, we are creating MapMessage object which contains our actual message to be sent. At the final step 7, we are sending the message.


MessageConsumerTest.java
package com.sarf.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import com.sarf.data.MessageObject;

public class MessageConsumerTest{
 public MessageObject receiveMessage() {
 ConnectionFactory cf =
            new ActiveMQConnectionFactory("tcp://localhost:61616");
        Destination destination = new ActiveMQQueue("mail.queue");
        Connection conn = null;
        try {
            conn = cf.createConnection();
            Session session =
                conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer consumer = session.createConsumer(destination);
            conn.start();
            MapMessage message = (MapMessage) consumer.receive();
            MessageObject mail = new MessageObject();
            mail.setMailId(message.getString("mailId"));
            mail.setMessage(message.getString("message"));
            session.close();
            return mail;
        }catch(Exception e) {
          e.printStackTrace();
 }finally{
      if(conn != null) {
      try{conn.close();}catch(JMSException e){}
            }
 }
      return null;
   }
}
In the preceding receiveMessage() method, we are creating ConnectionFactory using message broker URL and Destination objects for user created queue (mail.queue). Then we are creating a connection, session, and message consumer to consume message from destination queue.

MessageObject.java
This class represent POJO message object that we are sending to destination and consuming it using consumer.
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;
  }
}