Generic JMS and point-to-point messages

 

The WebSphere MQ queue manager (or Embedded JMS server) does not allow message filtering by content. So to implement selectors in point-to-point, MQ JMS will browse a message, parse it, compare it with the selector and then either retrieve it if there is a match or browse the next message. This is termed client-side selection, and has a performance cost as each message must be retrieved to the client to be browsed.

The queue manager does allow filtering by certain fields with certain formats in the MQ header which accompanies all messages. The only two of those fields which are available to a JMS application are:
Message ID
Correlation ID

When selecting on these fields, in the particular case of equality testing, the MQ JMS code is able to avoid the browse-parse-get loop and simply do a get-by-messageId or get-by-correlationId. This optimization is termed server-side selection as the messages are no longer retrieved to the client first to attempt to match the selector, instead this is done on the server. This only applies if the selector is a simple one, so for example no use of AND or OR with another field in the selector string. Using the server-side selection will make the matching process run faster.

The server side selection will only work if the values for message ID or correlation ID match the WebSphere MQ/Embedded JMS format.

Message ID

A message ID is generated by the JMS provider and has to conform to the JMS specification of:

    ID:nnnnn

where nnnnn is a provider specific value. For Embedded JMS and WebSphere MQ the message ID is a 48 character hexadecimal value and will look like:

    ID:414d51205741535f617070315f6a6d73b9f1cc3f2000071c

As it is generated, writing a selector that uses the message ID field will use server side selection.

 

Correlation ID

The correlation ID is not generated by the JMS provider and is left to the programmer to set. To take advantage of server side selection the correlation ID needs to be set to the correct format so that WebSphere MQ will recognize it and bypass the costly browse-parse-get loop. There are two ways to do this:

  1. Set the correlation ID to the message ID

    The message ID is already in the correct format as it is generated. Using this will save having to construct a correlation ID of the correct format and is the recommended method.

  2. Manually construct the correlation ID to the correct format

    This means making a String that is 48 hexadecimal characters. If you wish to use a String that is readable and then convert that into hexadecimal then that String needs to be 24 characters long.

 

Example

One common activity which uses a selector is within one application thread, send a request message and wait for the reply message. The reply message is identifiable on the incoming queue by an identifying field, in this example the correlation ID field. Finding the correct message is then a case of using a selector that will match on that correlation ID.

The code to do this would look something like the code fragment in Example 15-1.

Example 15-1 Example receive using a selector string for correlation ID

QueueSession qs = qc.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
String messageSelector = "JMSCorrelationID = '"+correlid+"'";
QueueReceiver receiver;
receiver = qs.createReceiver(myQueue,messageSelector);
TextMessage message = (TextMessage) receiver.receive();
String s = message.getText();

This code will only do a server side selection if the field correlid is encoded in the correct format. There are two choices, and for this example it needs to manually generate a correlation ID, which will then be placed in the request message to be returned in the reply message.

As the correlation ID field is a programmer defined field then the application flow needs to be:

  1. Create message.

  2. Create the correlation ID using your user defined mechanism. If it is a String then it needs to be 24 characters long. This might mean having to pad it with zeros or spaces.

  3. Place this 24 character string in the correlation ID of the message using the setCorrelationID method and send the message.

  4. For the receive, that correlation ID needs to be converted into the correct format for the selector to use in the code in Example 15-1. This is the format ID:hexadecimalnumber. An example of a method that could do this for you is in Example 15-2. Given a String this method will return a String that is the characters ID: followed by the original String encoded in hexadecimal.

    Example 15-2 Method to generate a WebSphere MQ formatted ID from a String object

    public String toHexString(String id) {
    	byte[] bytes = id.getBytes();
    	char[] result = new char[3+(2*bytes.length)];
    	result[0] = 'I';
    	result[1] = 'D';
    	result[2] = ':';
    	final char[] hexits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    	int source = 0;
    	int target = 3;
    	while(source <bytes.length)
    	{	int d = bytes[source++];
    		result[target++] = hexits[(d & 0xF0)>>4];
    		result[target++] = hexits[(d &  0x0F)];
    	}
    	return new String(result);
    }
    Meanwhile the request message is received and processed by the back end application. The correlation ID is taken from the request message and placed in the response message.

  5. The selector matches the correlation ID using server-side selection in the response message.

 Prev | Next

 

WebSphere is a trademark of the IBM Corporation in the United States, other countries, or both.

 

IBM is a trademark of the IBM Corporation in the United States, other countries, or both.