> For the complete documentation index, see [llms.txt](https://docs.xplatform.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xplatform.com/talon/concepts-and-architecture/messaging-model/jms-binding.md).

# JMS Binding

The JMS binding provides integration with JMS 1.1 message brokers using JNDI-based configuration for Talon microservices.

## Overview

The JMS binding works with JMS 1.1 level JMS clients and is configured using JNDI lookup. In addition to the generic JNDI-based configuration, the platform provides provider-specific implementations optimized for:

* **ActiveMQ** - Uses `INDIVIDUAL_ACKNOWLEDGE_MODE` for Guaranteed delivery
* **Tibco EMS** - Uses `EXPLICIT_CLIENT_ACKNOWLEDGE` for Guaranteed delivery

Both provider-specific implementations normalize topic delimiters from `/` to `.` for consistency with other Talon bindings.

For configuration details, see [JMS Binding Configuration](/talon/developing-applications/configuring-messaging/configuring-bus-connections/jms-binding.md).

## JMS Topic Format

JMS topics are JMS provider-specific. The platform treats channel key levels as being delimited by `/` and leaves it up to the binding implementation to normalize topic levels to the format native to the JMS provider.

For example, the ActiveMQ and Tibco EMS providers both normalize the channel key separator to `.` when sending or joining a channel.

## Wildcard Topics

Support for topic wildcards is specific to the JMS provider, if supported at all. The generic JMS binding does not perform any special handling for wildcard characters. When `nv.sma.cleanchannelfilter=true`, all non-alphanumeric characters are replaced with an `_` character (as they are during message sends when `nv.sma.cleanmessagekey=true`).

The platform's ActiveMQ and Tibco EMS specific binding implementations are sensitive to the following wildcards when `nv.sma.cleanchannelfilter=true` and preserve these characters rather than replace them with `_`:

| Wildcard | Description                                                                                  | Example                                                                                                                                                                                                                                            |
| -------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `*`      | Matches 0 or more characters within a topic level. Must be the only character in that level. | <p><code>orders/\*</code> matches:<br>- <code>orders/gin</code><br>- <code>orders/begin</code><br>- <code>orders/ginseng</code><br>- <code>orders/beginning</code><br><br>Does not match:<br>- <code>orders</code><br>- <code>orders/in</code></p> |
| `...`    | Matches multiple topic levels. May only be used as the last level in a topic filter string.  | <p><code>orders/...</code> matches:<br>- <code>orders/events/MSFT</code><br>- <code>orders/updates/APPL</code><br>- <code>orders/cancels/US/IBM</code><br><br>Does not match:<br>- <code>orders</code><br>- <code>order-updates</code></p>         |

## Sending and Receiving from External Applications

This section describes integration with non-Talon applications over JMS. This is an uncommon use case - see [Sending Messages](/talon/developing-applications/authoring-user-code/message-processing/processing-messages/sending-messages.md) for Talon-to-Talon messaging.

{% hint style="info" %}
These examples use ADM-generated messages for convenience, but this is not required. Messages can be encoded in any format (e.g., Protobuf, Xbuf) and encoded/decoded manually.
{% endhint %}

### 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.

**Example using JMS client**:

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

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

// prepare JMS message
javax.jms.Message message = null;
if (orderEvent.getEncodingType() == MessageView.ENCODING_TYPE_JSON) {
  message = session.createTextMessage();
  ((TextMessage)message).setText(new String(serializedPayload));
}
else {
  message = session.createBytesMessage();
  ((BytesMessage)message).writeBytes(serializedPayload);
}

// prepare message metadata
MessageMetadata metadata = MessageMetadataFactory.getInstance().createMessageMetadata();
metadata.serializeV2(orderEvent.getMessageEncodingType(),
                     orderEvent.getVfid(),
                     orderEvent.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

**Example using JMS client**:

```java
public void onMessage(javax.jms.Message message) {
  // extract SMA metadata
  final boolean isMetadataPresent = message.getBooleanProperty(SMA_METADATA_PRESENT_JMSPROP);
  if (!isMetadataPresent) {
    // not a Talon message
    handleNonTalonMessage(message);
    return;
  }

  final byte encodingType = message.getByteProperty(SMA_METADATA_ENCODING_JMSPROP);
  final short vfid = message.getShortProperty(SMA_METADATA_VFID_JMSPROP);
  final byte version = message.getByteProperty(SMA_METADATA_VERSION_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) {
    BytesMessage bytesMessage = (BytesMessage) message;
    byte[] bytes = new byte[(int) bytesMessage.getBodyLength()];
    bytesMessage.readBytes(bytes);
    payload = bytes;
  }
  else {
    handleNonTalonMessage(message);
    return;
  }

  // lookup factory (assumes view factories already registered)
  MessageViewFactory factory = viewFactoryRegistry.getMessageViewFactory(vfid);
  if (factory != null) {
    MessageView view = factory.wrap(vtype, encodingType, payload);
    if (view instanceof OrderEventMessage) {
      handleOrderEvent((OrderEventMessage) view);
    }
  }
  else {
    handleNonTalonMessage(message);
  }
}
```

## See Also

* [JMS Binding Configuration](/talon/developing-applications/configuring-messaging/configuring-bus-connections/jms-binding.md) - Configuration reference
* [Messaging Model](/talon/concepts-and-architecture/messaging-model.md) - Overview of Talon messaging
* [Configuring Bus Connections](/talon/developing-applications/configuring-messaging/configuring-bus-connections.md) - General bus configuration
