Queue Ordering

The order of messages on a queue is primarily determined by their priority. Message priority ranges from 9 (highest) to 0 (lowest). Messages with the same priority value are ordered by the time at which they arrive on the queue, with messages that have been on the queue for the longest being at the head of the priority group.

Reading messages on a queue

If you issue a getMessage command when a queue is empty, the queue throws a Java codebase Except_Q_NoMatchingMsg exception or returns a C codebase MQERETURN_QUEUE_ERROR, MQEREASON_NO_MATCHING_MSG. This allows you to create an application that reads all the available messages on a queue.

Java

Encasing the getMessage() call inside a try..catch block allows you to test the code of the resulting exception. This is done using the code() method of the MQeException class. You can compare the result from the code() method with a list of exception constants published by the WebSphere MQ Everyplace class. If the exception is not of type Except_Q_NoMatchingMsg, throw the exception again.

The following code shows this technique:

	try
	{
 	 while(true)
  		{ /* keep getting messages until 
				an exception is thrown		*/
    	MQeMsgObject msg = qmgr.getMessage( "myQMgr", "myQueue", 
															null, null, 0 );
    	processMessage(msg);
  		}
	}
	catch (Exception e)
	{
  		if ( e.code() != MQe.Except_Q_NoMatchingMsg )
    	throw e;
	}

Therefore, you can read all messages from a queue by iteratively getting messages until MQe.Except_Q_NoMatchingMsg is returned.

C

You can read all messages from a queue by looping, until the return code is MQERETURN_QUEUE_WARNING and the reason code is MQEREASON_NO_MATCHING_MSG.

Browse and Lock

Performing BrowseAndLock on a group of messages allows an application to ensure that no other application is able to process messages when they are locked. The messages remain locked until that application unlocks them. No other application can unlock the messages. Any messages that arrive on the queue after the BrowseAndLock operation are not locked.

An application can perform either a get or a delete operation on the messages to remove them from the queue. To do this, the application must supply the lockID that is returned with the enumeration of messages.

Specifying the lockID allows applications to work with locked messages without having to unlock them first.

Instead of removing the messages from the queue, it is also possible just to unlock them. This makes them visible once again to all WebSphere MQ Everyplace applications. You can achieve this by using the unlockMessage method.

Note:
See the WebSphere MQ Everyplace Configuration Guide for special considerations with WebSphere MQ bridge queues.

The following examples demonstrate the use of BrowseAndLock:

Java example

The MQeEnumeration object contains all the messages that match the filter supplied to the browse. MQeEnumeration can be used in the same manner as the standard Java Enumeration. You can enumerate all the browsed messages as follows:

Note:
You must supply a confirmID, in case the action of locating messages fails. It must be possible to undo the location, and this action requires the confirmID.
	long confirmID = MQe.uniqueValue();
	MQeEnumeration msgEnum = qmgr.browseMessagesAndLock( null, 
											"MyQueue", 
											null, null,
                               confirmID, false);
	
	while( msgEnum.hasMoreElements() )
	{	
  		MQeMsgObject msg = (MQeMsgObject)msgEnum.nextElement();
  		System.out.println( "Message from  queue manager: " + 
                      		msg.getAscii( MQe.Msg_OriginQMgr ) );
	}	
The following code performs a delete on all the messages returned in the enumeration. The message's UniqueID and lockID are used as the filter on the delete operation:
	while(msgEnum.hasMoreElements())
	{
  		MQeMsgObject msg = (MQeMsgObject)
									msgEnum.getNextMessage(null,0);
	
  		processMessage(msg);

  		MQeFields filter = msg.getMsgUIDFields();
  		filter.putLong(MQe.Msg_LockID, 
								msgEnum.getLockId());

  		qmgr.deleteMessage(null, "MyQueue", filter);
	}
C example
The C codebase example gets the actual message. Note the additional parameters, a confirmID in case the operation needs undoing, and the lockID.
	MQeVectorHndl hMessages;
	MQEINT64 lockID, confirmID=42;
	rc = mqeQueueManager_browseAndLock(hQueueManager, 
															&exceptBlock, 
															&hmessages,
															&lockID, 
															hQueueManagerName,
															hQueueName,
															hFilter, 
															NULL,			/*No Attribute*/
															confirmID,
															MQE_TRUE);		/*Just UIDs*/
	/*process vector*/
	MQeFieldsHndl hGetFilter;
	rc = mqeFields_new(&exceptBlock, &hGetFilter);
	if (MQERETURN_OK == rc){
		rc = mqeFields_putInt64(&hGetFilter, 
								   		&exceptBlock,
								   		MQE_MSG_LOCKID,
								   		lockID);
			if (MQERETURN_OK == rc){
				rc = mqeQueueManager_getMessage(&hQueueManager, 
								   						&exceptBlock,
								   						hQueueManagerName,
								   						hQueueName,
															hGetFilter,
															&hMsg);
	}
						

Message listeners

Note:
This section does not apply to the C codebase.

WebSphere MQ Everyplace allows an application to listen for events occurring on queues. The application is able to specify message filters to identify the messages in which it is interested, as shown in the following Java example:

/* Create a filter for "Order" messages of priority 7	*/
MQeFields filter = new MQeFields();
filter.putAscii( "MsgType", "Order" );
filter.putByte( MQe.Msg_Priority, (byte)7 );
/* activate a listener on "MyQueue"				*/
qmgr.addMessageListener( this, "MyQueue", filter );

Listeners do not start automatically when you create a queue manager. A call to MQeAdministrator is required. However, listeners are persistent in the registry. This means that, once created, listeners that exist at queue manager start-up are started automatically.

The following parameters are passed to the addMessageListener() method:

When a message arrives on a queue with a listener attached, the queue manager calls the callback object that it was given when the message listener was created.

The following is an example of the way in which an application would normally handle message events in Java:

public void messageArrived(MQeMessageEvent msgEvent)			
	{
		String queueName =msgEvent.getQueueName();			
		if (queueName.equals("MyQueue"))
		{
	       	try									
	       	{									
			/*get message from queue */
			MQeMsgObject msg =qmgr.getMessage(null,queueName,
						msgEvent.getMsgFields(),null,0);	
			
			processMessage(msg );
	       	}									
	       	catch (MQeException  e)					
	      	{									
	     		...
	      	}									
		}
	}

messageArrived() is a method implemented in MQeMessageListenerInterface. The msgEvent parameter contains information about the message, including:

Message filters only work on local queues. A separate technique known as polling allows messages to be obtained as soon as they arrive on remote queues.

Message polling

Note:
This section does not apply to the C codebase.

Message polling uses the waitForMessage() method. This command issues a getMessage() command to the remote queue at regular intervals. As soon as a message that matches the supplied filter becomes available, it is returned to the calling application.

A wait for message call typically looks like this:

	qmgr.waitForMessage( "RemoteQMgr", "RemoteQueue", 
									filter, null, 0, 60000 );

The waitForMessage() method polls the remote queue for the length of time specified in its final parameter. The time is specified in milliseconds, so in the example above, the polling lasts for 60 seconds. The thread on which the command is executing is blocked for this length of time, unless a message is returned earlier.

Message polling works on both local and remote queues.

Note:
Use of this technique results in multiple requests being sent over the network.

Trigger transmission

This method attempts to transmit pending messages. Only unlocked messages are transmitted.

Asynchronous remote queues and home server queues respond to trigger transmission processing. Put messages with no confirmID or put messages and confirm them before calling this method. Only messages that are fully put can be transmitted.

Trigger transmission rules

There are a number of rules, which can control the trigger transmission processing, if processing occurs. Chapter 3, Rules, or the WebSphere MQ Everyplace System Programming Guide provides detailed information on trigger transmission rules. Chapter 3, "Rules", of the WebSphere MQ Everyplace System Programming Guide contains information on trigger transmission rules.

rc = mqeQueueManager_triggerTransmission(hQueueManager,&exceptBlock);