JMS and MQ JMS function selector

When a message arrives on a destination, the function selector is used to determine which operation corresponds to the message.

Two function selectors are supplied. In the default function selector section, we discuss the general behavior of a function selector and the implementation of the default function selector. In the standard JMS message function selector section, we discuss a particular function selector for the body types used by this standard.

Default function selector

There has to be some mechanism that can be used to determine which of the possible JMS or MQ JMS export components the message should be delivered to, and which SCA operation the message corresponds with. A JMS or MQ JMS message contains only data, and the message may contain an indication about the target operation, but there is not a standard way to retrieve this information. Therefore, we need to map a certain message to a certain operation of the targeted service interface. The JMS or MQ JMS export listens to a particular destination. When a message arrives to that destination, the function selector determines the target operation.

In the export binding, the method binding has a native method attribute, which contains an identifier representing a JMS or MQ JMS message. Use of the native method allows for a level of indirection, which enables rename of an operation, without affecting the mapping.

By default, the value of native method is set to the interface operation name when the export is created. The export utilizes a function selector to inspect an incoming message in the message header or the message body. The export provides a default function selector that returns the value of JMS String Property TargetFunctionName from the header. So to identify the JMS or MQ JMS messages, the default behavior is for the import to set the JMS header property TargetFunctionName to the name of the interface operation name, and the default function selector used by the export will extract the TargetFunctionName property from the JMS header to correctly identify the incoming message. If the manner in which the native method name is to be found does not use the TargetFunctionName property, then a FunctionSelector implementation must be provided to correctly map the incoming JMS message to its intended SCA operation.

The commonj.connector.runtime.FunctionSelector interface presented below is used to extract the native function name or identifier (event ID) from the native data flowing inbound from the resource adapter using an EIS export.

public interface FunctionSelector {

	public String generateEISFunctionName(Object[] argObjects)
			throws SelectorException;

}

The implementation of this interface has to be provided by a resource adapter or third party who understands how to locate in the native data the appropriate identifier.

The implementation for the default JMS function selector basically looks like the following:

public class JMSFunctionSelectorImpl implements FunctionSelector {

	public String generateEISFunctionName(Object[] argObjects)
			throws SelectorException {

		try {
			Message message = (Message) argObjects[0];
			String functionName = message
					.getStringProperty("TargetFunctionName");
			return functionName;
		} catch (Throwable e) {
			throw new SelectorException(e);
		}
	}
}

Some other possible implementations for a FunctionSelector could use the JMSType header property or hard code the name of the method on the interface. Why would you hard code the name of the method on the interface? You would only hard code the name of the method if there were only one target SCA operation and that operation had a single input or output. Using the header property would typically be done for routing the message, performing some parsing and applying some logic to the parsed message. But suppose your application does not require any routing and does not need to incur the performance overhead. A hard coded value in this case would make sense.

public class JMSFunctionSelectorImpl implements FunctionSelector {

    public String generateEISFunctionName(Object[] argObjects) throws SelectorException {
		
	return "handleMessage";
}

Another possible implementation is to have the SCA application handle the routing. The mapped SCA operation would decide how to dispatch the message and then another part of the application would parse the message contents represented by its Service Data Object (SDO).

The following method demonstrates how a JMSType function selector could be used to create a name for the function:

public String generateEISFunctionName(Object[] arg)
			throws SelectorException {

		try {
			Message message = (Message) arg[0];
			String type = message.getJMSType();
			return type;
		} catch (JMSException e) {
			// Todo - Auto-generated catch block
			throw new SelectorException(e);
		}
	}

Standard JMS message function selector

A second function selector is available that follows the JMS standard of defining a message class with five subclasses of the message class for the body or payload which contains the message itself. Each subclass has a different body type. This function selector uses the JMSType property of the message to select the operation name.

The function selector is com.ibm.websphere.jms.data.bindings.JMSFunctionSelector.

To simplify working with this function selector, a function has been added to generate the appropriate business objects for the body types. In the dependencies editor of a module beneath the Predefined Resources heading, selecting Schema for simple JMS Data Bindings and saving the dependencies generates the business objects for these body types. You can then use these business objects to represent the message from the JMS client.

These data bindings could be used for routing messages. For example, using a mediation module between an export and two imports, a message filter primitive examines the values in the message properties and routes high priority messages to one destination and lower priority messages to another destination. Another possible use could be to add an XSL transformation or database lookup mediation primitive between an export and import to modify the message.

The following table shows the relationship of the data binding selection, the body type, the business object created for it, and the data type for standard JMS messages.

Table 1. Relationship of data binding selection, body type, business object and data type for standard JMS messages
Data binding selection Body type Business object Data type
Simple JMS BytesMessage Data Binding BytesMessage JMSBytesBody Byte array
Simple JMS MapMessage Data Binding MapMessage JMSMapBody Set of name/value pairs addressed by name. Value is a simple Java type.
Simple JMS Message Data Binding Message JMSBaseBody None (empty)
Simple JMS ObjectMessage Data Binding ObjectMessage JMSObjectBody Serialized Java object
Simple JMS StreamMessage Data Binding StreamMessage JMSStreamBody Stream of simple Java types
Simple JMS TextMessage Data Binding TextMessage JMSTextBody Java String

Note that if the operation name is not set, it will be derived from the type of incoming message as determined by this table:

Table 2. Default behavior if an operation name is not set
Message type Operation name
BytesMessage handleBytes
MapMessage handleMap
ObjectMessage handleObject
StreamMessage handleStream
TextMessage handleText
Message handleBase

If the operation name returned by the function selector has not been configured for the export, an exception will be thrown.

Related concepts
Java Message Service (JMS)
WebSphere MQ (WMQ)
WebSphere MQ Java Message Service (MQ JMS)
Related reference
Mapping a JMS, MQ or MQ JMS message to an SCA interface
JMS and MQ JMS data bindings

Feedback
(C) Copyright IBM Corporation 2005, 2007. All Rights Reserved.