JMS Tags Overview

The JMS tag library allows JMS messages to be sent and received from within a JSP page. This allows web developers to use Message Orientated Middleware (MOM) directly from within JSP.

Why use JMS in a web application?

JMS provides a universal API to all Message Orientated Middleware (MOM) technologies such as MQSeries, MSMQ, TibCo Rendezvous and SpiritWave. MOM provides a number of important features for building web applications.

Asynchronous processing

Remote Procedure Call (RPC) mechanisms like RMI, CORBA and EJB are predominantly synchronous in nature, a client will block on an RPC call until the server has finished. In MOM systems, asynchronous processing can occur to maximise throughput and reduce latency.

For example if a web application has a registration page, then a registration message could be sent on a MOM queue so that asynchronously the message can be processed by some back end server. This allows the users online experience to be fast, for them to keep working and navigating the site without blocking, then at some point later the back end can verify the user, add them to the user database and an email can be sent back to the user to confirm.

Loosely coupled, connectionless architecture

RMI and EJB technologies tend to be connection based so that clients and servers must be running at the same time for the clients to be able to function. If a server is taken down or fails then client side references to remote objects become stale or operations timeout. This can lead to complex application code to detect these kinds of failures and retry operations; usually server failures will cause the clients to fail as well.

In MOM systems the client and server sides are completely decoupled, there is no direct connection and so both sides can continue to work when the other is not present. At any point the server side can be taken down for maintenance and restarted or relocated without adversely affecting the clients.

This decoupling also makes it much easier to completely replace a client or server using any technology, language or platform at a later date.

Scalability, load balancing and fault tolerance

Most MOM implementations implement proper load balancing of messages across consumers (servers); if a server fails then another takes over ensuring proper load balancing and fault tolerance. Few RMI or EJB vendors offer this facility.

Most MOM implementations have a variety of Quality of Services such as to provide for long-term message persistence when there are no servers available to process the messages, to ensure no message loss. Finally message consumers (servers) can work against the same JMS queue as peers in a cluster so as the load increases more consumers can be run to deal with the load.

Common use cases

As JSP pages are rendered, its often useful to log information such as what the user is looking at so that other decoupled processes can analyse the information in inference engines, personalization software etc. The JMS tag library makes it very easy to log information at any point a JSP page is rendered.

Using XML as the format of JMS messages is becoming increasingly common as it provides a language and platform neutral format for data. JSP is particularly good at producing textual mark-up and so is very useful for composing XML centric JMS messages.

Finally when rendering a JSP page it can often be useful to fire off some asynchronous processing on some back end business logic server, without hampering the users online experience. Sending JMS messages from the web tier is an ideal way to do that, especially if the back end business logic is implemented on some non-Java platform such as .NET or mainframes.

JMS tag library deployment

The JMS tag library is currently built on top of the Messenger component from Jakarta Commons. This provides a simple configuration mechanism using an XML deployment descriptor to configure all of the JMS connections, their factories, JNDI drivers and settings, the quality of service configuration etc. Please refer to the Messenger website for further details of how this configuration should look.

Essentially your web application should have a Messenger.xml deployment configuration document in the WEB-INF/classes directory or you should explicitly configure Messenger using an initialisation Servlet. In addition all the necessary Messenger jars should be placed in your WEB-INF/lib directory along with any jars required by your JMS provider.

Establishing a connection

To perform any JMS operation you will need a JMS connection which is used via the Messenger facade. The <jms:connection> tag is used to export a connection. The connection can be exported as a JSP attribute variable for explicit coordination between JSP tags as follows.

<jms:connection var="myConn" name="topicConnection"/>
<jms:send connection="$myConn">
...
</jms:send>

Or tags can be nested to provide implicit tag communication which avoids the need to use JSP attributes.

<jms:connection name="topicConnection"/>
  <jms:send>
  ...
  </jms:send>
</jms:connection>

The name attribute used in the <jms:connection> tag refers to the logical name of the JMS connection in the Messenger.xml deployment document. This allows the exact JMS provider, the quality of service, JNDI provider and so forth to all be changed at deployment time without needing to change your JSP files. So you can start developing your web application using (say) the reference implementation of JMS then at a later date just change your deployment descriptor to switch to a better JMS provider like MQSeries or SpiritWave.

Sending a message

Messages are sent using the <jms:send> tag. This tag requires a connection, destination and message to be specified. These can all be passed in explicitly using tag attributes as follows.

<jms:connection var="myConn" name="topicConnection"/>
<jms:destination var="myDest" connection="$myConn" name="PRICE.STOCK.IBM"/>
<jms:message var="myMsg" connection="$myConn" type="PriceChange"/>
<jms:send connection="$myConn" destination="$myDest" message="$myMsg"/>    	

Or tag nesting can be used to specify the connection, destination and message. This more nested implicit approach is simpler to read and less error prone, though does result in more tag nesting. Any of the message tags described below may be nested within a <jms:send> tag.

<jms:connection name="topicConnection"/>
  <jms:send>    	
    <jms:destination>PRICE.STOCK.IBM</jms:destination>
    <jms:message type="PriceChange"/>
  </jms:send>
</jms:connection>

Message tags

JMS provides a variety of Message interfaces which are reflected by the following different message tags. For each message tag the standard JMS header properties are available as tag attributes (such as correlationID, replyTo and type) and user defined header properties can be specified via nested <jms:property> tags.

<jms:message>

This creates a standard JMS Message which has no body, just the standard and user defined JMS headers properties.

<jms:connection name="topicConnection"/>
  <jms:message var="myMsg"/>
  <jms:message var="myMsg2" type="PriceChange" correlationID="hello1234">
    <jms:property name="foo" value="$user.name"/>
    <jms:property name="bar">some text</jms:property>
  </jms:message>
</jms:connection>

<jms:mapMessage>

This creates a standard JMS MapMessage which the body has a number of different entries like a Map or Hashtable in Java. The keys of the MapMessage body must be Strings and the values can be any primitive type like Numbers or Date. The entries in the MapMessage are specified via the <jms:mapEntry> tag. 

<jms:connection name="topicConnection"/>
  <jms:mapMessage var="myMsg">
    <jms:mapEntry name="foo" value="$user.birthdate"/>
    <jms:mapEntry name="bar">James</jms:mapEntry>
  </jms:mapMessage >
</jms:connection>

An alternative is to specify the MapMessage entries via a Map object using the map attribute as follows. 

<jms:connection name="topicConnection"/>
  <jms:mapMessage var="myMsg" map="$myEntries"/>
</jms:connection>

<jms:objectMessage>

This creates a standard JMS ObjectMessage where the body is any Serializable Java object, which is specified via the body attribute.

<jms:connection name="topicConnection"/>
  <jms:objectMessage var="myMsg" body="$user.address"/>
</jms:connection>

<jms:textMessage>

This creates a standard JMS TextMessage where the body is a String. The text can be specified either via the body attribute or by using the content of the <jms:textMessage> tag itself. e.g..

<jms:connection name="topicConnection"/>
  <jms:textMessage var="myMsg" body="this is some text"/>
  <jms:textMessage var="myMsg2">This is some more text</jms:textMessage>
</jms:connection>

Receiving a message

The <jms:receive> tag is used to receive messages from some destination. Explicit attributes can be used to specify the connection and destination to use. The JMS Message that is received is exported as a JSP attribute variable, specified via the var attribute.

<jms:connection var="myConn" name="topicConnection"/>
<jms:destination var="myDest" connection="$myConn" name="PRICE.STOCK.IBM"/>
<jms:receive var="newMsg" connection="$myConn" destination="$myDest"/>    	

Or tag nesting can be used to specify the connection and destination. This more nested implicit approach is simpler to read and less error prone, though does result in more tag nesting.

<jms:connection name="topicConnection"/>
  <jms:receive var="newMsg">    	
    <jms:destination>PRICE.STOCK.IBM</jms:destination>
  </jms:receive>
</jms:connection>

By default this tag will block until a message is received, which could be for ever. An optional millisecond timeout value can be specified which will cause the tag to return a null Message if the timeout period is reached before a message is received. A timeout value of 0 will avoid any blocking and return a Message if one is available or return null.

<jms:connection name="topicConnection"/>
  <jms:receive var="newMsg" timeout="1000">    	
    <jms:destination>PRICE.STOCK.IBM</jms:destination>
  </jms:receive>
</jms:connection>

Summary

For a detailed look at each tag in turn along with all the attributes it supports, please refer to the tag summary or reference.