In This Section

Overview

The JMS binding works with JMS 1.1 level JMS clients and is configured using JNDI lookup. In addition to JNDI lookup the platform provides a subclassed version of the JMS binding optimized for working with ActiveMQ. 

Bus Descriptor Format

A jms message bus can be configured via a descriptor string as follows which takes the connection information followed by a list of provider properties. 

jms://<address>:<port>&prop1=val1&propN=valN

An example bus descriptor for using tibco ems 

jms://tibcohost:2732&username=admin&password=changeme / 
&jndi=true / 
&jndi_contextfactory=com.tibco.tibjms.naming.TibjmsInitialContextFactory /
&jndi_principal=admin / 
&jndi_credentials=changme /
&jndi_connectionfactory=CSTopicConnectionFactory

DDL

In a DDL config file a jms bus can equivalently be configured in one two ways

<buses>
  <bus name="my-bus">
    <provider>jms</provider>
    <address>192.168.1.9</address>
    <port>55555</port>
    <properties>
      <username>admin</username>
      <password>changeme</password>
      <jndi>true</jndi>
      <jndi_contextfactory>com.tibco.tibjms.naming.TibjmsInitialContextFactory</jndi_contextfactory>
      <jndi_principal>admin</jndi_principal>
      <jndi_credentials>changme</jndi_connectionfactory>
      <jndi_connectionfactory>CSTopicConnectionFactory</jndi_connectionfactory>
    </properties>
    <channels>
      ...
    </channels>
  </bus>
</buses>
<buses>
  <bus name="my-bus" descriptor="jms://tibcohost:2732&username=admin&password=changeme / 
                                 &jndi=true / 
                                 &jndi_contextfactory=com.tibco.tibjms.naming.TibjmsInitialContextFactory /
                                 &jndi_principal=admin / 
                                 &jndi_credentials=changme /
                                 &jndi_connectionfactory=CSTopicConnectionFactory">
    <channels>
      ...
    </channels>
  </bus>
</buses>

(lightbulb) Note the '/' denoting line breaks above would not be valid in actual XML – they are provided here for readability. 

The descriptor form is useful in cases where the descriptor name may be supplied as an external configuration property that is substituted for example:

<buses>
  <bus name="my-bus" descriptor="${myBusDescriptor::loopback://mybus">
    <channels>
      ...
    </channels>
  </bus>
</buses>

Generic JMS Binding Properties

The following properties can be set in the descriptor used to create a JMS bus binding. 

PropertyDefaultDescription
jndi
true
Indicates that JNDI should be used to lookup the connection factory for creating JMS connections. 
jndi_contextfactory
-The name of the environment property for specifying the initial context factory to use
jndi_principal
-The name of the environment property for specifying the identity of the principal for authenticating the caller to the service
jndi_credentials
-The environment property for specifying the credentials of the principal for authenticating the caller to the service
jndi_connectionfactory
-The name of the connection factory to look up in jndi.

When using jndi the address portion of the binding descriptor is used as the address at which to lookup the connection factory. The returned connection factory may connect to a different host. 

The ActiveMQ Binding

While ActiveMQ can be configured via JNDI like any other JMS provider, the platform provides a custom 'activemq' bus provider. 

The ActiveMQ binding is additionally optimized to:

DDL

In a DDL config file a activemq bus can equivalently be configured in one two ways

<buses>
  <bus name="my-bus">
    <provider>activemq</provider>
    <address>192.168.1.9</address>
    <port>66666</port>
    <properties>
    </properties>
    <channels>
      ...
    </channels>
  </bus>
</buses>
<buses>
  <bus name="my-bus" descriptor="activemq://192.168.1.9:66666"
    <channels>
      ...
    </channels>
  </bus>
</buses>

Sending and Receiving from External Applications

This section describes how to send to Talon applications from non Talon applications and from Talon application to non Talon applications over jms. The sections below utilize ADM generated messages for convenience, but this is not required. For example, if you your messages are encoded in protobuf (or Xbuf) you could encode/decode the message yourself without using ADM. One such example of this might be if you were using C and generated protobuf message from the IDL generated by ADM. 

Sending Messages To Talon

The platform's JMS binding encodes a serialized message payload in a bytes message and sets metadata fields in its jms headers. The following example show 

// populate a message
OrderEventMessage orderEvent = OrderEventMessage.create();
orderEvent.setOrderId(1);

// serialize the payload to a byte buffer
byte [] serializedPayload = view.serializeToByteArray();

// prepare JMS message
javax.jms.Message message = null;
if(view.getEncodingType == MessageView.ENCODING_TYPE_JSON) {
  message = session.createTextMessage();
  ((TextMessage)message).setText(new String(serializedPayload));
}
else {
   message = session.createBytesMessage();
   ((Bytes)message).setBytes(serializedPayload);
}
// prepare message metadata
MessageMetadata metadata = MessageMetadataFactory.getInstance().createMessageMetadata();
metadata.serializeV2(view.getMessageEncodingType(),
                     view.getVfid(),
                     view.getType(),
                     0,  // message sender id
                     0,  // message flow
                     0,  // message sequence number (unsequenced)
                     -1, // channel id (unspecified)
                     XString.create("order-events"));

// The jms binding decomposes metadata into message properties:
message.setBooleanProperty(JmsMessageBusBinding.SMA_METADATA_PRESENT_JMSPROP, true);
message.setByteProperty(JmsMessageBusBinding.SMA_METADATA_VERSION_JMSPROP, (byte)metadata.getVersion());
message.setByteProperty(JmsMessageBusBinding.SMA_METADATA_ENCODING_JMSPROP, metadata.getMessageEncodingType());
message.setShortProperty(JmsMessageBusBinding.SMA_METADATA_VFID_JMSPROP, metadata.getMessageViewFactory());
message.setShortProperty(JmsMessageBusBinding.SMA_METADATA_VTYPE_JMSPROP, metadata.getMessageViewType());
message.setIntProperty(JmsMessageBusBinding.SMA_METADATA_SENDER_JMSPROP, metadata.getMessageSender());
message.setIntProperty(JmsMessageBusBinding.SMA_METADATA_FLOW_JMSPROP, metadata.getMessageFlow());
message.setLongProperty(JmsMessageBusBinding.SMA_METADATA_SNO_JMSPROP, metadata.getMessageSno());
message.setShortProperty(JmsMessageBusBinding.SMA_METADATA_CHID_JMSPROP, metadata.getMessageChannelId());
message.setStringProperty(JmsMessageBusBinding.SMA_METADATA_CHNAME_JMSPROP, metadata.getMessageChannelName());

// send 
Topic topic = session.createTopic("order-events");
messageProducer.publish(topic, message, DeliveryMode.PERSISTENT, 0, 0);

// dispose
orderEvent.dispose();
metadata.dispose(); 

Receiving Messages from Talon

The following code sample shows how an external  application using the JMS api directly can unpack a message sent over the platform's built in JMS binding and materialize it into a message view. 

public void onMessage(javax.jms.Message message) {
  // extract sma metadata
  final boolean isMetadataPresent = message.getBooleanProperty(SMA_METADATA_PRESENT_JMSPROP);
  if (!isMetadataPresent) {
     // not an x message. 
     handleNonXMessage(message);
  }
  final byte encodingType = message.getByteProperty(SMA_METADATA_ENCODING_JMSPROP);
  final short vfid = message.getShortProperty(SMA_METADATA_VFID_JMSPROP);
  final short vtype = version > MessageMetadata.V1 ? message.getShortProperty(SMA_METADATA_VTYPE_JMSPROP) : 0;
 
  // extract payload
  Object payload = null;
  if(message instanceof TextMessage) {
     payload = ((TextMessage) message).getText(); 
  }
  else if(message instanceof BytesMessage) {
     payload = ((BytesMessage) message).getBytes(); 
  }
  else {
    handleNonXMessage(message);
    return;
  } 
 
  // lookup factory
  // (assumes that view factory have already been registered)
  MessageViewFactory factory = viewFactoryRegistry.getMessageViewFactory(vfid);
  if (factory != null) {
    MessageView view = factory.wrap(vtype, encodingType, payload);
    if(view instanceof OrderEventMessage) {
      handleOrderEvent((OrderEventMessage) message);
    }
  }
  else {
    handleNonXMessage(message);
    return;
  }
}