Metamerge logo
Search

Advanced Search
*
*
*
* HOME DOCUMENTS & RESOURCES DOWNLOADS EARLY TECH ACCESS SUPPORT FAQ KNOWN ISSUES OLD VERSIONS
*

 

JMS Connector

Overview

The JMS Connector provides access to a variety of JMS based systems. The current version has been tested with SonicMQ and FioranoMQ and IBM MQ Series.  

Refer to Specific topics to see what you might need to do to your Metamerge Installation in order to make the JMS Connector work. 

The Connector enables communication of both native Entry objects and XML text to be passed using a Java Message Server product.

The JMS Connector supports JMS message properties. Each message received by the JMS Connector will populate the conn object with properties from the JMS message (see the getProperty() and setProperty() methods of the entry class to access these). conn object properties are prefixed with "jms." followed by the JMS message property name. The property holds the value from the JMS message. When sending a message the user can set properties which will then be passed on to the JMS message sent. The JMS Connector will scan the conn object for properties that starts with "jms." and set the corresponding JMS message property from the conn property.

  • JMS: correlationID=12 ----> conn jms.correlationID=12
  • conn:jms.inReplyTo=12 ----> JMS:inReplyTo=12

The conn object is only available in a few hooks: See When is the conn object available under Attribute Mapping for where.

JMS Messages

Everything sent and received by the JMS connector is a JMS message. The JMS connector converts the MI Entry object into a JMS message and vice versa. Each JMS message contains pre-defined JMS headers, user defined properties and some kind of body that is either text, a byte array or a serialized Java object.

JMS Message Types

The JMS environment that allows you to send different types of data on the JMS bus. This connector recognize three of those types. The three types are referred to as TextMessage, BytesMessage and ObjectMessage. The most open-minded strategy is to use TextMessage (e.g. jms.usetextmessages=true) so that other applications than Metamerge Integrator can read messages generated by the JMS connector. When you communicate with other MI servers over a JMS bus the BytesMessage provides a very simple way to send an entire Entry object to the recipient. This is also particularly useful when the entry object contains special Java objects that are not easy to represent as text. Most Java objects provide a toString() method that returns the string representation of it but the opposite is very rare. Also, the toString() method does not always return very useful information. For example, the string representation of a byte array is "[B@<memory-address>".

TextMessage

A text message carries a body of text. The format of the text itself is undefined so it can be virtually anything. When you send/receive messages of this type the connector will do one of two things depending on whether you have specified a parser or not.

  • When you specify a parser the connector will call the parser to interpret the text message and return these attributes along with any headers and properties. When sending a message the provided conn object will be passed to the parser to generate the text body part. This makes it easy to send data in various formats onto a JMS bus (e.g. use the LDIF parser, XML parser etc ....). You can even use the SOAP parser to send SOAP requests over the JMS bus.
  • If you don't have a parser defined, the text body is returned in an attribute called message. When sending a message the connector will use the provided message attribute to set the JMS text body part.
var str = work.getString ("message");
task.logmsg ("Received the following text: " + str );

If you expect to receive text messages in various formats (XML, LDIF, CSV ...) you should leave the parser parameter blank and make the guess yourself as to what format the text message is. When you know the format you can use the system.parseObject(parserName, data) to do the parsing for you as in:

var str = work.getString ("message");
// code to determine format
if ( isLDIF )
	e = system.parseObject( "metamerge.LDIF", str );
else if ( isCSV )
	e = system.parseObject ( "metamerge.CSV", str );
else
	e = system.parseObject ( "metamerge.XML", str );
}

// Dump parsed entry to logfile
task.dumpEntry ( e );

The jms.usetextmessages flag determines whether the connector should use this method when sending a message.

Object Message

An object message is a message containing a serialized Java object. A serialized Java object is a Java object that has been converted into a byte stream in a specific format which makes it possible for the receiver to "resurrect" the object at the other end. Testing shows that this is fine as long as the Java class libraries are available to the JMS server in both ends. Typically, a java.lang.String object will cause no problems but other Java objects might. For this reason, the JMS connector will not generate object messages but is able to receive them. When you receive an object message the connector will return two attributes:

  • java.object - This attribute holds the java object and you should access the object using the getObject method in your work/conn entry.
  • java.objectClass - This attribute is a convenience attribute and holds the class name (String) of the Java object
var obj = work.getObject ("java.object");
obj.anyMethodDefinedForTheObject ();

You will only receive these messages.

Bytes Message

A bytes message is a message carrying an arbitrary array of bytes. The JMS connector will generate this type of message when the jms.usetextmessages flag is false. The connector will take the provided entry and serialize it into a byte array and send the message as a bytes message. When receiving a bytes message, the connector will first attempt to deserialize the byte array into an Entry object. If that fails, the byte array is returned in the message attribute. You should access the byte array using the getObject method in your work/conn entry.

var ba = work.getObject ("message");
for ( i = 0; i < ba.length; i++)
	task.logmsg ( "Next byte: " + ba [ i ] );
 

This type of message is generated only if jms.usetextmessages is false (not checked).

Version 1.22

In version 1.22 the JMS connector was enhanced with the following functionality.

Iterator Mode

A new parameter was added to the configuration where you can specify a Message Filter to filter out specific messages you want returned on a Queue/Topic (Topic is also called Pub/Sub). A message filter specification is a subset of SQL92 and is defined in the JMS specification.

Lookup Mode

The connector now supports Lookup mode (e.g. findEntry) where the user can search for matching messages in a JMS Queue (Topic (Pub/Sub) is not supported by Lookup). 

The Link Criteria specifies the JMS headers and properties for selecting matching messages on a queue. Important When you specify the link criteria you must not use the 'jms.' prefix. If you search for a property called MyProp you must say "MyProp = 'value'" even thought the connector returns the property as jms.MyProp. A future version will correct this potential confusion.

For the advanced link criteria you must conform to the Message Selection specification as described in the JMS specification (http://java.sun.com/products/jms). The JMS connector will in this release reuse the SQL filter specification (JMS message selection is a subset of SQL92) to build the message selection string. Turn on debug mode to view the generated message filter string.

There are basically two ways to perform a lookup. The first way is to do a non-destructive search in a Queue (using QueueBrowser) which will return matching messages without removing the messages from the JMS queue. The second mode removes all matching entries from the JMS queue. You decide which to use by setting the jms.lookupConsumesMessages flag in the connector configuration. For Topic connections the jms.lookupConsumesMessages flag does not apply as messages on topics are always removed when a subscriber receives it. However, the Lookup mode will heed the Durable Subscriber flag in which case the JMS server will hold any messages sent on a topic when you are disconnected.

The JMS connector works in the same way as other connectors in that you can specify a maximum number of entries to return in your assemblyline settings. Thus, to ensure you only retrieve a single message during lookup you could specify max duplicate entries = 1 in the AssemblyLine settings. By using the Allow Duplicates flag in the connector screen you can influence further the behavior of the Lookup mode. Setting max duplicates to 1 and checking Allow Duplicates allows you to retrieve one matching entry at a time regardless of the number of matching messages in the JMS queue.

Since the JMS bus is asynchronous the JMS connector provides parameters to determine when the Lookup should stop looking for messages. There are two parameters that tells the connector how many times it will query the JMS queue and for how long it will wait for new messages during the query. Specifying 10 for the retry count and 1000 for the timeout will cause the connector to query the JMS queue ten times each waiting 1 second for new messages. If no messages are received during this interval the connector returns. If during a query the connector receives a message, it will continue to check for additional messages (this time without any timeout) until the queue returns no more messages or until the received message count reaches the Max Duplicate Entries limit defined by the AssemblyLine. The effect of this is that a lookup operation only retrieves those messages that are available at the moment. 

JMS Headers & Properties

A JMS messages consists of headers, properties and the body. Headers are accessed differently than properties and was not available in previous versions. In this version you can specify how to deal with headers and properties.

JMS Headers

JMS headers are pre-defined named values that is present in all messages (although the value might be null). The following is a list of JMS header names this connector supports:

Name Type Description
JMSCorrelationID String This header is set by the application for use by other applications.
JMSDeliveryMode Integer This header is set by the JMS provider and denotes the deliver mode
JMSExpires Long A value of zero means that the message does not expire. Any other value denotes the expiration time for when the message is removed from the queue.
JMSMessageID String The unique message ID. Note that this is not a required field and may be null.

Since the JMS provider may not use your provided message id the connector will set a special property called $jms.messageid after sending a message. This is to insure that the message id always is available to the user. To retreive this value use conn.getProperty("$jms.messageid") in your After Add hook.

JMSPriority Integer The priority of the message
JMSTimestamp Long The time the message was sent
JMSType String The type of message
JMSReplyTo Destination The queue/topic the sender expects replies to. When receiving a message this value holds the provider specific Destination interface object and is typically an internal Queue or Topic object. When sending a message you should either reuse the incoming Destination object or set the value to a valid topic/queue name. If the value is NULL (e.g. an attribute with no values) or the string "%this%" the connector will use its own queue/topic as the value. The difference between this method and explicitly setting the queue/topic name is that you need not update the attribute assignment if you change your connector configuration's queue/topic name.

There is one restriction in the current version which allows you only to request a reply to the same type of connection as you are currently connected to. This means that you cannot publish a message on a topic and request the reply to a queue and vice versa.

It is not mandatory to respond to this header so the receiver of the message may completely ignore this field without any form of punishment ;-)

These headers are all set by the provider and may or may not be acted upon by the JMS driver for outgoing messages. In the configuration screen you can specify that you want all headers returned as attributes or specify a list of those of interest. All headers are named using a prefix of 'jms.'. Also note that JMS header names always start with the string JMS. This means that you should never use property names starting with jms.JMS as they would be intepreted as headers.

JMS Properties

In previous versions of this connector all JMS properties were copied between the Entry object and the JMS Message. In this release you can refine this behavior by telling the connector to return all user defined properties as attributes or specify a list of properties of interest. All properties are prefixed with 'jms.' to separate them from other attributes. If you leave the list of properties blank and uncheck the jms.propertiesAsAttributes flag you will get the same behavior as for previous versions. As opposed to JMS headers, JMS properties can be set by the user. If you use the backwards compatible mode you must set the entry properties in the Before Add hook as in:

conn.setProperty ( "jms.MyProperty", "Some Value" );

If you either check the jms.propertiesAsAttributes flag or specify a list of properties, you should provide the JMS properties as attributes.
One way to do that is to add attributes using the jms. prefix in your attribute map. For example, if you add jms.MyProperty attribute map it will result in a JMS property named MyProperty.

Configuration

The Connector needs the following parameters:

Parameter

Description

connectorType com.architech.connector.rscJMSConnector
jms.broker The URL for the JMS server (e.g. 
jms.username Username for authenticating access to the JMS
jms.password Password for authenticating access to the JMS
jms.topic The topic with which messages are exchanged.
jms.connectionID (Sonic MQ Only, referenced as ConnectID in the SonicMQ documentation) Only supported in "topic mode"
From SonicMQ Programming Guide: 

"The ConnectID is a SonicMQ identifier that can control whether the broker allows multiple connections under a user-name and ConnectID combination: 

  •  If the ConnectID is not null, only one connection with that particular user-name and ConnectID can be established. 
  • If the ConnectID is null, any number of connections can be established with the same username. You might create a ConnectID by combining the username with some additional identifier."
jms.mode Specify subscriber or publisher.
jms.connectionType Specify whether you are connecting to a Queue or Topic (Topic is sometime called Pub/Sub for Publish/Subscribe)
jms.durable Only relevant for jms.connectionType Topic (Pub/Sub) If true this will cause the connector to create a durable subscriber. This means that the server will store messages for a topic for later retrieval when the connector is offline. See also client ID being mandatory with durable.
jms.clientID The client ID to use for Topic connections (mandatory for durable).
parser If specified, the Text message of a JMS message will be parsed using this Parser upon receipt of a message and used to generate the text message when sending a message.
jms.driver Select the JMS server type
jms.usetextmessages True - The connector will produce a TextMessage and send the Entry object either by using the specified parser to generate the text body or use the pre-defined message attribute as the text body.
jms.autoAcknowledge If true, each message is automatically acknowledged by this Connector. If false, you must manually acknowledge the receipt of a JMS message.  If off, we use the JMS CLIENT_ACKNOWLEDGE mode.  Here are an extract of the JMS API documentation:

"AUTO_ACKNOWLEDGE - with this acknowledgment mode, the session automatically acknowledges a client's receipt of a message either when the session has successfully returned from a call to receive or
when the message listener the session has called to process the message successfully returns."

"CLIENT_ACKNOWLEDGE - with this acknowledgment mode, the client acknowledges a consumed message by calling the message's acknowledge method. Acknowledging a consumed message acknowledges all messages that the session has consumed.

Parameters introduced in version 1.13/1.22

jms.messageFilter Specifies a message filter for selection of messages from a queue/topic. Used in Iterator mode only.
jms.lookupConsumesMessage If true, each message found during lookup is removed from the queue. Note that you can set the maxDuplicateEntries parameter in your assemblyline settings to prevent lookup to return more than one entry. If false, messages are returned as usual but they are not removed from the queue. 
jms.lookupRetries Number of times Lookup will search the queue for matching messages
jms.lookupTimeout For how long (in milliseconds) the Connector will wait for new messages during a lookup query. 
This parameter is only used when "Lookup Removes" is set to "true".
jms.headersAsAttributes If true all JMS headers are returned as attributes (prefixed by jms.) in Iterator and Lookup modes. For AddOnly mode any attribute starting with jms.JMS will be treated as JMS header. This cause these attributes to be set as JMS headers  and removed from the Entry object before sending the message.  Note that very few headers may be set and setting them does not mean the JMS provider will ever use them.
jms.specificHeadersAsAttributes Same as jms.headersAsAttributes but only the listed JMS headers will be treated as headers. Specify one header per line.
jms.propertiesAsAttributes If true all JMS properties are returned as attributes (prefixed by jms.) in Iterator and Lookup modes. For AddOnly mode any attribute starting with jms. will be treated as a JMS property. This causes these attributes to be set as JMS properties
jms.specificPropertiesAsAttributes Same as jms.propertiesAsAttributes but only the listed JMS properties will be treated as properties. Specify one property per line.

Example

Demo package containing a ready to run configuration for the JMS Connector is included here. In addition you need a SonicMQ JMS server.

Specific Topics

Here are some files that you need to add to the Metamerge jars directory (or to the classpath)

JMS Implementation Files needed
Soniq MQ client.jar
Fiorano MQ fmprtl.zip (must to be added to classpath )
IBM MQ Series
com.ibm.mqjms.jar
com.ibm.mq.jar
jms.jar

Download

(You must replace your existing .jar-files with the ones provided in the .zip file.)

 

*
  Metamerge Integrator version 4.6 ©Copyright Metamerge AS 2000-2002 Last edited 2002-06-10 contact us