38 JMS – II

Dr S. Abirami

Learning Objectives

 

In the previous module, we learnt about the JMS Messaging Model, Communication Model and Programming Models and some introduction about the JMS Messages. In this module, let us continue the exploration of JMS Messages, its types, formats and properties along with the illustration of a small JMS Sender and Receiver application. Also, we are going to learn the significance and need of Model View Controller.

  1. JMS – Messages

JMS application produces and consumes message.In the earlier module, we have seen about the five different types of messages along with a session object to create a message. Now, let us look through the functionality of JMS Message Producer and Message Consumer.

 

1.1 JMS – MessageProducer

 

A Message Producer is an object created by a session and is used for sending messages to a destination.MessageProducer comes in two forms by implementing either the QueueSender or the TopicPublisher interface as shown in Figure 1.

 

Here, we use the Session object to create a message producer.The following snippet shows how to create a message producer using either a queue sender or a topic publisher interface.

MessageProducer producer =session.createProducer (destination)

QueueSender queueSender = queueSession.createSender(queue);

TopicPublisher topicPublisher = topicSession.createPublisher(topic);

 

Once a message producer has been created, we can use it to send messages as shown below:

     queueSender.send(message);

topicPublisher.publish(message);

 

1.2 JMS – MessageConsumer

 

A Message Consumer is an object that is created by a session and used for receiving messages sent to a destination. It is created by impleemnting the MessageConsumer interface.A message consumer allows a JMS client to register interest in a destination with a JMS provider. The JMS provider manages the delivery of messages from a destination to the registered consumers of the destination.The PTP form of message consumer implements the QueueReceiver interface and the publish/subscribe form implements the TopicSubscriber interface.

 

For example, you may use a QueueSession to create a receiver for the queue myQueue, and you may use a TopicSession to create a subscriber for the topic myTopic as given below:

 

QueueReceiverqueueReceiver = queueSession.createReceiver(myQueue); TopicSubscribertopicSubscriber = topicSession.createSubscriber(myTopic); (OR)

 

TopicSubscribertopicSubscriber = TopicSession.createDurableSubscriber(myTopic); Once a message consumer has been created, it becomes active, and we can use it to

 

receive messages. With either a QueueReceiver or a TopicSubscriber, receive method can be used to consume a message synchronously. This method can be invoked at any time after calling the start method as given below:

 

queueConnection.start();

Message m = queueReceiver.receive( );

(OR)

topicConnection.start();

Message m = topicSubscriber.receive(1000); // time out after a seccond.

 

In order to consume a message asynchronously, a message listener need to be used. In synchronous message consumption, receive method can be used to consume a message synchronously. Similarly, this can be invoked at any time after calling the start method:

 

queueConnection.start();

Message m = queueReceiver.receive();

topicConnection.start();

Message m = topicSubscriber.receive(1000); // time out after a second

 

In Asynchronous message consumption, message listeners and message selectors objects are included. A message listener is an object that acts as an asynchronous event handler for messages.This implements MessageListener Interface, which has only one method “onMessage(Message msg)”. MessageListener is not specific to a particular destination. The “onMessage” method is responsible for handling all exceptions too. The code snippet for setting a message listener for Topic is given below:

 

TopicListenertopicListener = new TopicListener(); topicSubscriber.setMessageListener(topicListener);

 

Message selectors are used for filtering out the messages received by the application.Message selectors assign the work of filtering messages to the JMS provider rather than to the application.A message selector is a SQL92 String that contains an expression.A message selector cannot select messages on the basis of the content of the message body. Examples for Message Selector is given below:

 

Examples:

 

phone LIKE ‘223’

JMSType IS NOT NULL

name = ‘Tom’

 

1.3 JMS – Message Format

 

The ultimate purpose of a JMS application is to produce and consume messages that can then be used by other software applications.JMS messages have a basic format that is simple but highly flexible, allowing the users to create messages that match formats used by non-JMS applications on heterogeneous platforms.A JMS message consists of three parts:

  • Header consists of predefined fields
  • Properties (optional) consisting additional fields
  • Body (optional) – actual message content

1.4 JMS – Message Header: A JMS message header contains a number of predefined fields that contain the values used by both clients and providers to identify and route messages. For example, every message has a unique identifier, which is represented in the header field as JMSMessageID. The value of another header field, JMSDestination, represents the queue or the topic to which the message is sent. Other fields include a timestamp and a priority level.Each header field has associated setter and getter methods. Table 1 shows the different header fields used in JMS Message Header with their description and the methods associated with it for setting the corresponding information.

 

 

1.5 JMS – Message Properties: This message property consists of optional fields which are set by the client before the message is sent. Some properties are predefined (prefix JMSX). E.g. JMSXUserId specifies the user about sending the messages. It can be evaluated by message selectors. The values can be of different types such asboolean, byte, short, int, float, double, and String. The JMS API provides some predefined property names that a provider can support. The use of these predefined properties or of user-defined properties is optional.

 

1.6 JMS – Message Bodies: The JMS API defines five message body formats, also called message types. They are listed in Table 2.

 

 

1.7 JMS – Message Type: The JMS API provides methods for creating messages of different types and for filling in their contents. For example, to create and send a TextMessage, the following statements can be used:TextMessage message = queueSession.createTextMessage(); message.setText(msg_text); // msg_text is a String queueSender.send(message);

 

At the consuming end, a message gets arrived as a generic Message object and must be cast to the appropriate message type. Either one or more getter methods can be used to extract the message contents. The following code fragment demonstrates the usage of the getText method for receiving message:

 

Message m = queueReceiver.receive();

if (m instanceofTextMessage) {

TextMessage message = (TextMessage) m; System.out.println(“Reading message:”  + message.getText());

}

else {

//  Handle error

}

 

1.8 JMS – Queue Browsers: The messages that are sent to a queue remain in the queue until the message consumer for that queue consumes them. The JMS API provides a QueueBrowser object that allows to browse the messages in the queue and display the header values for each message. To create a QueueBrowser object, Session.createBrowser method can be used. For example:

QueueBrowser browser = session.createBrowser(queue);

 

1.9 JMS – Exception Handling: The root class for exceptions thrown by JMS API methods is JMSException. Catching JMSException provides a generic way of handling all exceptions related to the JMS API.The JMSException class includes the following subclasses as listed below, described in the API documentation:

 

IllegalStateException                                  InvalidClientIDException

 

InvalidDestinationException                  InvalidSelectorException

 

JMSSecurityException                               MessageEOFException

 

MessageFormatException                        MessageNotReadableException

 

MessageNotWriteableException           ResourceAllocationException

 

TransactionInProgressException           TransactionRolledBackException

 

1.10 JMS – Queue:

 

To develop JMS queue, anyone of the application server needs to be installed. Here, a glassfish3 server has been used for creating two JNDI. First connection factory named “myQueueConnectionFactory” need to be created and a destination resource named “myQueue” has to be created. After creating JNDI, server and receiver applications need to be created. Later, server and receiver has to be executed in different consoles. The steps involved in developing a JMS Queue has been explained below:

 

1)   Create connection factory and destination resource

 

As a first step, server admin console need to be opened using the URL http://localhost:4848 (localhost with port number). Later, login process need to be completed with the username and passwordfollowed by clicking on the JMS Resource -> Connection Factories -> New. Next to it, pool name has to be written and the Resource Type has to be selected as QueueConnectionFactory as shown in Figure 2.

 

Figure 2. New JMS Connection Factory establishment using Glass Fish Server.

 

Subsequently, on the JMS Resource -> Destination Resources -> New has to be clicked, and the JNDI name and physical destination name has to be written as shown in Figure 3.

 

 

    2) Create sender and receiver application

 

Next to it, Sender and Receiver code has been developed by using the QueueConnection Factory, Queue Connection, Session, Sender and Receiver Objects explained earlier in the previous module and in this module. Note that the Receiver is attached with listener which will be invoked only when the user sends message.During the execution, the receiver class has to be executed first followed by the Sender class. An example for Sender and Receiver application for sending/receiving messages using all the objects explained earlier has been shown below:

    File: MySender.java

 

importjava.io.BufferedReader;

importjava.io.InputStreamReader;

importjavax.naming.*;

import javax.jms.*;

public class MySender {

public static void main(String[] args)

{

try

{ //Create and start connection InitialContextctx=new InitialContext();

QueueConnectionFactoryf=(QueueConnectionFactory)ctx.lookup (“myQueueConnectionFactory”);

QueueConnection con=f.createQueueConnection(); con.start();

//2) create queue session

QueueSessionses=con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); //3) get the Queue object

Queue t=(Queue)ctx.lookup(“myQueue”); //4)create QueueSender object

QueueSender sender=ses.createSender(t); //5) create TextMessage object TextMessagemsg=ses.createTextMessage(); //6) write message

BufferedReader b=new BufferedReader(new InputStreamReader(System.in)); while(true)

{

System.out.println(“Enter Msg, end to terminate:”);

String s=b.readLine();

if (s.equals(“end”))

break;

msg.setText(s);

//7) send message

sender.send(msg);

System.out.println(“Message successfully sent.”);

}

//8) connection close

con.close();

}catch(Exception e){System.out.println(e);}

}}

    File: MyReceiver.java

 

import javax.jms.*;

importjavax.naming.InitialContext;

public class MyReceiver {

public static void main(String[] args)

{

try{

//1) Create and start connection

InitialContextctx=new InitialContext();

QueueConnectionFactoryf=(QueueConnectionFactory)ctx.lookup(“myQueueC onnectionFactory”);

QueueConnection con=f.createQueueConnection(); con.start();

//2) create Queue session

QueueSessionses=con.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); //3) get the Queue object

Queue t=(Queue)ctx.lookup(“myQueue”);

//4)create QueueReceiver

QueueReceiver receiver=ses.createReceiver(t);

//5) create listener object

MyListener listener=new MyListener();

//6) register the listener object with receiver

receiver.setMessageListener(listener);

System.out.println(“Receiver1 is ready, waiting for messages…”);

System.out.println(“press Ctrl+c to shutdown…”);

while(true){

Thread.sleep(1000);

}

}catch(Exception e){System.out.println(e);}

} }

File: MyListener.java

import javax.jms.*;

public class MyListener implements MessageListener { public void onMessage(Message m) { try{

TextMessagemsg=(TextMessage)m;

System.out.println(“following message is received:”+msg.getText()); }catch(JMSException e){System.out.println(e);}

}

}

 

    2. Introduction to Design Patterns

A pattern is a proven solution to a problem in a context.Christopher Alexander says that each pattern is a three-part rule which expresses a relation between a certain context, a problem, and a solution. Design patterns represents a solutions to problems that arise when developing software within a particular context i.e. Patterns = problems-solution pairs in a context

 

2.1 Details of MVC Design Pattern

 

Name (essence of the pattern)- Model View Controller MVC Context (where does this problem occur)- MVC is an architectural pattern that is used when developing interactive application such as a shopping cart on the Internet.

 

Problem (definition of the reoccurrence) -User interfaces change often, especially on the internet where look-and-feel is a competitive issue. Also, the same information is presented in different ways. The core business logic and data is stable.

 

One of the most common Design Patterns is Model-View-Controller (MVC). The model does all the computational work. It is input/output free and all communication with the model is done via methods. In a typical application we will find these three fundamental parts in Model View Controller architecture:

 

Data (Model) – This is used to model the data.

 

An interface to view and modify the data (View) – User Interface design to display and manipulate the data.

 

Operations that can be performed on the data (Controller) – This is used to operate for the data.

 

The pictorial representation of the Model View Controller design is shown in the figure4.

 

The controller tells the model what to do and the user input goes to the controller. The view shows results which is a “window” into the model. The view can get results from the controller or the view can get results directly from the model (where the data resides).

 

Summary

 

Therefore, through this module, we have learnt the JMS Messages along with the components of JMS Message Producer, Consumer, Message types, formats and its body. Also, we have learnt a JMS application of File Sender and Receiver which sends/receives JMS Messages. In addition to this, we also studied the need of Design patterns and Model view controller in this module.

 

Web Links

 

  • http://www-sop.inria.fr/members/Francoise.Baude/AppRep/JMS.pdf
  • http://theopentutorials.com/tutorials/java-ee/ejb3/mdb/java-message-service-jms-api/
  • http://www.computing.dcu.ie/~mcrane/CA4006/CA4006%20Lecture%206%20Message%20Pas sing%20in%20Distd%20Systems.pdf
  • https://www.novell.com/documentation/extend5/Docs/help/MP/jms/tutorial/
  • http://www.indigoo.com/dox/wsmw/1_Middleware/JMS.pdf
  • http://www-sop.inria.fr/members/Francoise.Baude/AppRep/JMS.pdf
  • https://www.tutorialspoint.com/jsp/
  • Mark Richards, Richard Monson-Haefel, AndDavid A. Chappell,“ Java Message Service”,Second Edition, O’Reilly Media,2009.