Mapping JMS messages to WebSphere MQ Everyplace messages

This section describes how the JMS message structure is mapped to a WebSphere MQ Everyplace message. It is of interest to programmers who wish to transmit messages between JMS and traditional WebSphere MQ Everyplace applications.

As described earlier, the JMS specification defines a structured message format consisting of a header, three types of property and five types of message body, while WebSphere MQ Everyplace defines a single free-format message object, MQeMsgObject. WebSphere MQ Everyplace defines some constant field names that messaging applications require, for example UniqueID, MessageID, and Priority, while applications can put data into a WebSphere MQ Everyplace message as <name, value> pairs.

To send JMS messages using WebSphere MQ Everyplace, we define a constant format for storing the information contained in a JMS message within an MQeMsgObject. This adds three top-level fields and four MQeFields objects to an MQeMsgObject, as shown in the following example.

Figure 8. Mapping a JMS message to a WebSphere MQ EveryplaceMQeMsgObject
Diagram showing how to map a JMS message
to an MQeMsgObject, that is a WebSphere MQ Everyplace message. JMS message information is mapped
onto the MQeMsgObject using MQeFields objects.These fields are listed in the
text below.

The following sections describe the contents of these fields.

Naming MQeMsgObject fields

An MQeMsgObject stores data as a <name, value> pair. The field names used to map JMS message data to the MQeMsgObject are defined in com.ibm.mqe.MQe and com.ibm.mqe.jms.MQeJMSMsgFieldNames:

MQeJMS field names
MQe.MQe_JMS_VERSION
MQeJMSMsgFieldNames.MQe_JMS_CLASS
JMS message field names
MQeJMSMsgFieldNames.MQe_JMS_HEADER
MQeJMSMsgFieldNames.MQe_JMS_PROPERTIES
MQeJMSMsgFieldNames.MQe_JMS_PS_PROPERTIES
MQeJMSMsgFieldNames.MQe_JMSX_PROPERTIES
MQeJMSMsgFieldNames.MQe_JMS_BODY
JMS header field names
MQeJMSMsgFieldNames.MQe_JMS_DESTINATION 
MQeJMSMsgFieldNames.MQe_JMS_DELIVERYMODE 
MQeJMSMsgFieldNames.MQe_JMS_MESSAGEID 
MQeJMSMsgFieldNames.MQe_JMS_TIMESTAMP
MQeJMSMsgFieldNames.MQe_JMS_CORRELATIONID 
MQeJMSMsgFieldNames.MQe_JMS_REPLYTO 
MQeJMSMsgFieldNames.MQe_JMS_REDELIVERED
MQeJMSMsgFieldNames.MQe_JMS_TYPE 
MQeJMSMsgFieldNames.MQe_JMS_EXPIRATION
MQeJMSMsgFieldNames.MQe_JMS_PRIORITY

WebSphere MQ Everyplace JMS information

Two <name, value> pairs holding information required for WebSphere MQ Everyplace to recreate the JMS message are added directly to the MQeMsgObject:

MQe.MQe_JMS_VERSION
This contains a short describing the version number of the WebSphere MQ Everyplace JMS implementation used to store the message. The current version number is 1. The presence or absence of a field named MQe.MQe_JMS_VERSION is used to determine if an MQeMsgObject contains a WebSphere MQ Everyplace JMS message.
MQeJMSMsgFieldNames.MQe_JMS_CLASS
This contains a String describing the type of JMS message body stored in the MQeMsgObject. It defines the strings in Table 24.
Table 6. Strings in MQeJMSMsgFieldNames.MQe_JMS_CLASS
JMS message type MQe.MQe_JMS_CLASS
Bytes message jms_bytes
Map message jms_map
Null message jms_null
Object message jms_object
Stream message jms_stream
Text message jms_text

JMS header files

JMS Header fields are stored within an MQeMsgObject using the following rules:

  1. If a JMS header field is identical to a defined MQeMsgObject field then the header value is mapped directly to the appropriate field in the MQeMsgObject.
  2. If a JMS header field does not map directly to a defined field but can be represented using existing fields defined by WebSphere MQ Everyplace then the JMS header value is converted as appropriate and then set in the MQeMsgObject.
  3. If WebSphere MQ Everyplace has not defined an equivalent field by then, the header field is stored within an MQeFields object, which is then embedded in the MQeMsgObject. This ensures that the JMS header field in question can be restored when the JMS message is recreated.

The header fields that map directly to MQeMsgObject fields are:

Table 7. Header fields that map directly to MQeMsgObject fields
JMS header field MQeMsgObject defined field
JMSTimestamp MQe.Msg_Time
JMSCorrelationID MQe.Msg_CorrelID
JMSExpiration MQe.Msg_ExpireTime
JMSPriority MQe.Msg_Priority

Two JMS header fields, JMSReplyTo and JMSMessageID, are converted prior to being stored in MQeMsgObject fields.

JMSReplyTo is split between MQe.Msg_ReplyToQMgr and MQe.Msg_ReplyToQ, while JMSMessageID is the String "ID:" followed by a 24-byte hashcode generated from a combination of MQe.Msg_OriginQMgr and MQe.Msg_Time.

The remaining four JMS header fields, JMSDeliveryMode, JMSRedelivered, and JMSType have no equivalents in WebSphere MQ Everyplace. These fields are stored within an MQeFields object in the following manner:

This MQeFields object is then stored within the MQeMsgObject as MQe.MQe_JMS_HEADER. Finally, JMSDestination is recreated when the message is received and, therefore does not need to be stored in the MQeMsgObject.

JMS properties

When storing JMS property fields in an MQeMsgObject, the <name, value> format used by the JMS properties corresponds very closely to the format of data in an MQeFields object:

Table 8. JMS property fields and the MQeFields object
Property type Corresponding MQeFields object
Application-specific MQe.MQe_JMS_PROPERTIES
Standard (JMSX_name) MQe.MQe_JMSX_PROPERTIES
Provider-specific (JMS_provider_name) MQe.MQe_JMS_PS_PROPERTIES

Three MQeFields objects, corresponding to the three types of JMS property, application-specific, standard, and provider-specific are used to store the <name, value> pairs stored as JMS message properties.

These three MQeFields objects are then embedded in the MQeMsgObject with the following names:

Note that WebSphere MQ Everyplace does not currently set any provider specific properties. However, this field is used to enable WebSphere MQ Everyplace to handle JMS messages from other providers, for example WebSphere MQ.

JMS message body

Regardless of the JMS message type, WebSphere MQ Everyplace stores the JMS message body internally as an array of bytes. For the currently supported message types, this byte array is created as follows:

Table 9. Caption Description
JMS message type Conversion
Bytes message ByteArrayOutputStream.toByteArray();
Object message <serialized object>.toByteArray();
Text message String.getBytes("UTF-8");

When the JMS message body is stored in an MQeMsgObject, this byte array is added directly to the MQeMsgObject with the name MQe.MQe_JMS_BODY.

The following code fragment creates a WebSphere MQ Everyplace JMS text message by adding the required fields to an MQeMsgObject:

// create an MQeMsgObject
	MQeMsgObject msg = new MQeMsgObject();

	// set the JMS version number
	msg.putShort(MQe.MQe_JMS_VERSION, (short)1);
	// and set the type of JMS message this MQeMsgObject contains
	msg.putAscii(MQeJMSMsgFieldNames.MQe_JMS_CLASS, "jms_text");

	// set message priority and exipry time - these are mapped to 
		JMSPriority and JMSExpiration
	msg.putByte(MQe.Msg_Priority, (byte)7);
	msg.putLong(MQe.Msg_ExpireTime, (long)0);

	// store JMS header fields with no WebSphere MQ Everyplace 
		equivalents in an MQeFields object
	MQeFields headerFields = new MQeFields();
	headerFields.putBoolean(MQeJMSMsgFieldNames.MQe_JMS_REDELIVERED, 
										false);
	headerFields.putAscii(MQeJMSMsgFieldNames.MQe_JMS_TYPE, 
									"testMsg");
	headerFields.putInt(MQeJMSMsgFieldNames.MQe_JMS_DELIVERYMODE, 		
	Message.DEFAULT_DELIVERY_MODE);
	msg.putFields(MQeJMSMsgFieldNames.MQe_JMS_HEADER, 
							headerFields);

	// add an integer application-specific property
	MQeFields propField = new MQeFields();
	propField.putInt("anInt", 12345);
	msg.putFields(MQeJMSMsgFieldNames.MQe_JMS_PROPERTIES, 
							propField);

	// the provider-specific and JMSX properties are blank
	msg.putFields(MQeJMSMsgFieldNames.MQe_JMSX_PROPERTIES, 
						new MQeFields());
	msg.putFields(MQeJMSMsgFieldNames.MQe_JMS_PS_PROPERTIES, 
						new MQeFields());

	// finally add a text message body
	String msgText = 
			"A test message to WebSphere MQ Everyplace JMS";
	byte[] msgBody = msgText.getBytes("UTF8");
	msg.putArrayOfByte(MQeJMSMsgFieldNames.MQe_JMS_BODY,
										 msgBody);

	// send the message to a WebSphere MQ Everyplace Queue
	queueManager.putMessage(null, 
										"SYSTEM.DEFAULT.LOCAL.QUEUE", 
										msg, null, 0);

Now, we use JMS to receive the message and print it:

// first set up a QueueSession, then...
	Queue queue = session.createQueue
						("SYSTEM.DEFAULT.LOCAL.QUEUE");
	QueueReceiver receiver = session.createReceiver(queue);
	
	// receive a message
	Message rcvMsg = receiver.receive(1000);

	// and print it out
	System.out.println(rcvMsg.toString());

This gives:

	 HEADER FIELDS
	-----------------------------
 	JMSType:          testMsg
 	JMSDeliveryMode:  2
 	JMSExpiration:    0
 	JMSPriority:      7
 	JMSMessageID:     ID:00000009524cf094000000f07c3d2266
 	JMSTimestamp:     1032876532326
	JMSCorrelationID: null
	JMSDestination:   null:SYSTEM.DEFAULT.LOCAL.QUEUE
 	JMSReplyTo:       null
 	JMSRedelivered:   false

	 PROPERTY FIELDS (read only)	
	------------------------------
 	JMSXRcvTimestamp : 1032876532537
 	anInt : 12345

	 MESSAGE BODY (read only)
------------------------------------------------------------------
	A test message to WebSphere MQ Everyplace JMS

Note that JMS sets some of the JMS message fields, for examole JMSMessageID, JMSXRcvTimestamp internally.

WebSphere MQ Everyplace JMS classes

WebSphere MQ Everyplace classes for Java Message Service consist of a number of Java classes and interfaces that are based on the Sun javax.jms package of interfaces and classes. They are contained in the com.ibm.mqe.jms package. The following classes are provided:

Table 10. WebSphere MQ Everyplace JMS classes
Class Implements
MQeBytesMessage BytesMessage
MQeConnection Connection
MQeConnectionFactory ConnectionFactory
MQeConnectionMetaData ConnectionMetaData
MQeDestination Destination
MQeJMSEnumeration Java.util.Enumeration from QueueBrowser
MQeJMSJNDIQueue Queue
MQeJMSQueue Queue
MQeMessage Message
MQeMessageConsumer MessageConsumer
MQeMessageProducer MessageProducer
MQeObjectMessage ObjectMessage
MQeQueueBrowser QueueBrowser
MQeQueueConnection QueueConnection
MQeJNDIQueueConnectionFactory QueueConnectionFactory
MQeQueueConnectionFactory QueueConnectionFactory
MQeQueueReceiver QueueReceiver
MQeQueueSender QueueSender
MQeQueueSession QueueSession
MQeSession Session
MQeTextMessage TextMessage

Note that MessageListener and ExceptionListener are implemented by applications.