Skip to content

JMS Swiftlet

Overview

The JMS Swiftlet implements the core JMS (Java Message Service) protocol support for SwiftMQ routers, providing all functionality necessary for JMS client connectivity, messaging, and resource management. It manages inbound and outbound JMS connections, sessions, producers, consumers, temporary queues, durable subscriptions, and enforces resource limits and authentication. The Swiftlet also exposes detailed runtime usage statistics and supports advanced features such as message selectors, duplicate detection, and failover/reconnect.

Features

JMS Connection Management

The JMS Swiftlet manages all incoming JMS client connections, both over TCP and intra-VM (intravm). Each connection is tracked and limited according to global and per-listener maximums. The Swiftlet enforces unique JMS client IDs by default, but can be configured to allow duplicates. It handles authentication using a pluggable challenge/response mechanism and maintains runtime statistics for each connection, including messages sent/received per second and totals. Connections are monitored for activity, and keepalive intervals are enforced to detect and close stale sessions.

Connection Factories and Listeners

Listeners define network endpoints (ports, addresses) for JMS clients to connect. Each listener can have multiple connection factories, each with its own set of properties (e.g., reconnect behavior, buffer sizes, duplicate detection). Connection factories are registered in JNDI for client lookup. Intra-VM connection factories allow for high-performance, in-process JMS connections.

Host Access Control

Each listener can restrict inbound connections based on a host access list, using SQL-LIKE predicates (with % as a wildcard) to match allowed client addresses.

Authentication and Challenge/Response

Authentication is performed using a configurable challenge/response factory class. The default is com.swiftmq.auth.ChallengeResponseFactoryImpl, but this can be replaced to implement custom authentication schemes.

Configuration Example:

<swiftlet name="sys$jms" allow-same-clientid="true" max-connections="100" crfactory-class="com.example.CustomCRFactory">
  <listeners>
    <listener name="tcp-listener" port="4001">
      <host-access-list>
        <host-access-entry name="192.168.%"/>
      </host-access-list>
      <connection-factories>
        <connection-factory name="cf1" reconnect-enabled="false" duplicate-message-detection="false"/>
      </connection-factories>
    </listener>
  </listeners>
</swiftlet>

JMS Session, Producer, and Consumer Lifecycle

For each active JMS connection, the Swiftlet manages multiple JMS sessions, which may be transacted or non-transacted and support all standard JMS acknowledge modes. Each session can create producers (senders/publishers) and consumers (receivers/subscribers), with resource limits enforced per connection. The Swiftlet supports both queue and topic semantics, including temporary destinations and durable subscriptions. Message delivery is optimized with consumer-side caching and bulk delivery, and message selectors are fully supported for filtering.

Temporary Queues and Topics

Temporary queues are created per connection and are automatically deleted when the connection closes. Their names follow the pattern tmp$- and are tracked under each connection's usage entity.

Durable Subscriptions

Durable topic subscriptions are mapped to internal queues named $. These queues persist messages for offline subscribers and are managed as part of the session and connection lifecycle.

Message Selectors

Consumers and browsers can specify message selectors using standard JMS SQL-92 syntax. Selectors are compiled and validated at creation time, and only matching messages are delivered.

Configuration Example:

<swiftlet name="sys$jms">
  <listeners>
    <listener name="tcp-listener" port="4001">
      <connection-factories>
        <connection-factory name="cf1" smqp-consumer-cache-size="1000" smqp-consumer-cache-size-kb="4096"/>
      </connection-factories>
    </listener>
  </listeners>
</swiftlet>

Resource Limits and Usage Statistics

The Swiftlet enforces resource limits for connections, sessions, producers, and consumers, both globally and per-listener. These limits prevent resource exhaustion and can be tuned for different deployment scenarios. The Swiftlet also collects and exposes detailed runtime statistics, such as messages per second and total messages sent/received per connection. These statistics are updated at a configurable interval and can be viewed via management tools.

Consumer Cache Low Water Mark

Each consumer maintains a message cache, which is refilled when the number of cached messages drops below the configured low water mark. This ensures efficient bulk delivery and minimizes latency.

Configuration Example:

<swiftlet name="sys$jms" consumer-cache-low-water-mark="50" collect-interval="5000"/>

Duplicate Message Detection and Reconnect

To ensure reliable message delivery, the JMS Swiftlet supports duplicate message detection for consumers. When enabled, a backlog of recent JMS message IDs is maintained to filter out duplicates, which is especially important in failover or reconnect scenarios. Connection factories can be configured to enable or disable duplicate detection, set the backlog size, and control reconnect behavior (number of retries, delay between attempts).

Configuration Example:

<swiftlet name="sys$jms">
  <listeners>
    <listener name="tcp-listener" port="4001">
      <connection-factories>
        <connection-factory name="cf1" duplicate-message-detection="true" duplicate-backlog-size="5000" reconnect-enabled="true" reconnect-max-retries="20" reconnect-delay="5000"/>
      </connection-factories>
    </listener>
  </listeners>
</swiftlet>

Internal Queue Naming

  • tmp$<sequence>-<startuptime> — Temporary queues created per JMS connection; used for temporary destinations and automatically deleted when the connection closes.
  • <clientId>$<durableName> — Internal queue for durable topic subscriptions, storing messages for offline durable subscribers.

Configuration Guide

Restricting JMS Connections to Specific Hosts

Use this scenario to allow only clients from certain IP address ranges to connect to a JMS listener, improving security and compliance.

  1. Define a listener with the desired port.
  2. Add host access entries using SQL-LIKE predicates (use % as wildcard) to match allowed client addresses.
<swiftlet name="sys$jms">
  <listeners>
    <listener name="secure-listener" port="4002">
      <host-access-list>
        <host-access-entry name="10.0.%.%"/>
        <host-access-entry name="192.168.1.%"/>
      </host-access-list>
      <connection-factories>
        <connection-factory name="cf-secure"/>
      </connection-factories>
    </listener>
  </listeners>
</swiftlet>

Configuring a High-Performance IntraVM Connection Factory

Use this scenario to enable JMS clients running in the same JVM as the router to connect with minimal overhead, bypassing the network stack.

  1. Add an intraVM connection factory with custom cache sizes and delivery mode as needed.
<swiftlet name="sys$jms">
  <intravm-connection-factories>
    <intravm-connection-factory name="ivm-cf" smqp-consumer-cache-size="2000" smqp-consumer-cache-size-kb="8192" jms-default-delivery-mode="non_persistent"/>
  </intravm-connection-factories>
</swiftlet>

Configuration Reference

The top-level entity in routerconfig.xml is <swiftlet name="sys$jms">.

<swiftlet name="sys$jms"> Properties

These properties are attributes of the <swiftlet name="sys$jms"> entity.

Parameter Type Default Mandatory Reboot Required Description
allow-same-clientid Boolean false No No Allows multiple connection with the same JMS Client Id if set to true
collect-interval Long 10000 No No Collect Interval Messages/Sec
max-connections Integer -1 No No Maximum JMS Connections
consumer-cache-low-water-mark Integer 100 No No Consumer caches are refilled when reaching this mark (min: 0)
crfactory-class String com.swiftmq.auth.ChallengeResponseFactoryImpl No Yes Challenge/Response Factory Class
<swiftlet name="sys$jms" allow-same-clientid="false" collect-interval="10000" max-connections="-1" consumer-cache-low-water-mark="100" crfactory-class="com.swiftmq.auth.ChallengeResponseFactoryImpl"/>

<intravm-connection-factories> in <swiftlet name="sys$jms">

IntraVM Connection Factories

Each <intravm-connection-factory> entry is identified by its name attribute (the IntraVM Connection Factory).

Parameter Type Default Mandatory Reboot Required Description
smqp-producer-reply-interval Integer 20 Yes No Number of SMQP Requests after which a SMQP Reply is required (min: 1)
smqp-consumer-cache-size Integer 500 Yes No Cache Size per Consumer (Messages) (min: 1)
smqp-consumer-cache-size-kb Integer 2048 Yes No Cache Size per Consumer (KB)
jms-client-id String No No JMS Client Id for durable Subscribers
jms-default-delivery-mode String persistent Yes No JMS Default Delivery Mode (choices: persistent, non_persistent)
jms-default-message-ttl Long 0 Yes No JMS Default Message TTL (min: 0)
jms-default-message-priority Integer 4 Yes No JMS Default Message Priority (range: 0–9)
jms-default-message-id-enabled Boolean true No No JMS Default Message Id Enabled
jms-default-message-timestamp-enabled Boolean true No No JMS Default Message Timestamp Enabled
thread-context-classloader-for-getobject Boolean false No No Use the Thread Context Classloader for getObject()
<swiftlet name="sys$jms">
  <intravm-connection-factories>
    <intravm-connection-factory name="..." smqp-producer-reply-interval="..." smqp-consumer-cache-size="..." smqp-consumer-cache-size-kb="..." jms-default-delivery-mode="..." jms-default-message-ttl="..." jms-default-message-priority="..."/>
  </intravm-connection-factories>
</swiftlet>

<listeners> in <swiftlet name="sys$jms">

Listener Definitions

Each <listener> entry is identified by its name attribute (the Listener).

Parameter Type Default Mandatory Reboot Required Description
connectaddress String No No Listener Connect IP Address for NAT
connectport Integer -1 No No Listener Connect Port for NAT
bindaddress String No No Listener Bind IP Address
port Integer Yes No Listener Port
hostname2 String No No Hostname of the 2nd HA Instance
connectaddress2 String No No Listener Connect IP Address for NAT of the 2nd HA Instance
connectport2 Integer -1 No No Listener Connect Port for NAT of the 2nd HA Instance
bindaddress2 String No No Listener Bind IP Address of the 2nd HA Instance
port2 Integer -1 No No Listener Port 2nd HA Instance of the 2nd HA Instance
use-tcp-no-delay Boolean true Yes No Use Tcp No Delay
socketfactory-class String com.swiftmq.net.PlainSocketFactory No No Listener Socketfactory Class
keepalive-interval Long 60000 No No Interval for sending Keep Alive Messages
max-connections Integer -1 No No Maximum JMS Connections for this Listener
router-input-buffer-size Integer 131072 No No Router Network Input Buffer Size (min: 1024)
router-input-extend-size Integer 65536 No No Router Network Input Extend Size (min: 1024)
router-output-buffer-size Integer 131072 No No Router Network Output Buffer Size (min: 1024)
router-output-extend-size Integer 65536 No No Router Network Output Extend Size (min: 1024)
<swiftlet name="sys$jms">
  <listeners>
    <listener name="..." port="..." use-tcp-no-delay="..."/>
  </listeners>
</swiftlet>

<host-access-list> in <listeners>

Host Access List

Each <host-access-entry> entry is identified by its name attribute (the Host Access Entry).

<swiftlet name="sys$jms">
  <listeners>
    <listener name="...">
      <host-access-list>
        <host-access-entry name="..."/>
      </host-access-list>
    </listener>
  </listeners>
</swiftlet>

<connection-factories> in <listeners>

Connection Factories

Each <connection-factory> entry is identified by its name attribute (the Connection Factory).

Parameter Type Default Mandatory Reboot Required Description
reconnect-enabled Boolean true No No Reconnect Enabled
reconnect-max-retries Integer 10 No No Maximum Retries for Reconnect
reconnect-delay Long 10000 No No Reconnect Delay in ms
duplicate-message-detection Boolean true No No Enables Duplicate Message Detection for Consumers
duplicate-backlog-size Integer 2000 No No Max. Number of Entries of JMS Message IDs in the Duplicate Backlog
client-input-buffer-size Integer 131072 No No Client Network Input Buffer Size (min: 1024)
client-input-extend-size Integer 65536 No No Client Network Input Extend Size (min: 1024)
client-output-buffer-size Integer 131072 No No Client Network Output Buffer Size (min: 1024)
client-output-extend-size Integer 131072 No No Client Network Output Extend Size (min: 1024)
smqp-producer-reply-interval Integer 20 Yes No Number of SMQP Requests after which a SMQP Reply is required (min: 1)
smqp-consumer-cache-size Integer 500 Yes No Cache Size per Consumer (Messages) (min: 1)
smqp-consumer-cache-size-kb Integer 2048 Yes No Cache Size per Consumer (KB)
jms-client-id String No No JMS Client Id for durable Subscribers
jms-default-delivery-mode String persistent Yes No JMS Default Delivery Mode (choices: persistent, non_persistent)
jms-default-message-ttl Long 0 Yes No JMS Default Message TTL (min: 0)
jms-default-message-priority Integer 4 Yes No JMS Default Message Priority (range: 0–9)
jms-default-message-id-enabled Boolean true No No JMS Default Message Id Enabled
jms-default-message-timestamp-enabled Boolean true No No JMS Default Message Timestamp Enabled
thread-context-classloader-for-getobject Boolean false No No Use the Thread Context Classloader for getObject()
<swiftlet name="sys$jms">
  <listeners>
    <listener name="...">
      <connection-factories>
        <connection-factory name="..." smqp-producer-reply-interval="..." smqp-consumer-cache-size="..." smqp-consumer-cache-size-kb="..." jms-default-delivery-mode="..." jms-default-message-ttl="..." jms-default-message-priority="..."/>
      </connection-factories>
    </listener>
  </listeners>
</swiftlet>