Cameleer

JMS component

The jms component sends and receives JMS-style messages (queues, topics, selectors, request/reply, transactions) through any broker that speaks STOMP 1.2, such as ActiveMQ, Artemis or RabbitMQ.

Scheme: jms: · Also: activemq:, amqp-stomp: (same component, see activemq, amqp-stomp) · Crate: cameleer-amqp · Cargo feature: amqp · Consumer: yes · Producer: yes · Apache Camel: JMS

When to use it

  • Move Camel routes that use jms:queue:... to Cameleer without a JVM or a JMS client library.
  • Request/reply over a queue: a service answers on a temporary reply queue, as with JMS replyTo.
  • Competing consumers on a queue, publish-subscribe on a topic, durable and shared subscriptions.
  • Expose an AI model or agent as a queue-based service that other systems call with request/reply.

Difference from Apache Camel: there is no JMS API in Rust, so Cameleer speaks STOMP 1.2 to the broker and maps JMS semantics onto it. Use amqp for JMS over AMQP 1.0. XA transactions are not possible over STOMP (transactionManager is accepted and ignored); transacted=true gives local transactions.

URI format

text
jms:[queue:|topic:|temp-queue:|temp-topic:]destinationName[?options]

Without a prefix the destination is a queue.

Example

yaml example: jms-request-reply
- route:
    id: price-service
    from:
      uri: jms:queue:prices
      parameters:
        brokerURL: "{{env:JMS_BROKER_URL:tcp://localhost:61613}}"
        username: "{{env:JMS_USER:admin}}"
        password: "{{env:JMS_PASSWORD:admin}}"
        concurrentConsumers: 2
      steps:
        - setBody:
            simple: "price of ${body}: 42.00 EUR"

A caller that sends ACME as an InOut message to jms:queue:prices gets price of ACME: 42.00 EUR back through a temporary reply queue.

Rust DSL

rust
use cameleer_core::prelude::*;

pub fn routes(ctx: &CamelContext) -> Result<()> {
    ctx.add_routes(|b| {
        b.from("jms:queue:prices?brokerURL=tcp://localhost:61613&concurrentConsumers=2")
            .route_id("price-service")
            .set_body(simple("price of ${body}: 42.00 EUR"));
    })
}

Options

optiondefaultdescription
brokerURL (alias brokerUrl)tcp://localhost:61613Broker STOMP address: tcp://, stomp://, amqp:// or failover:(...) (first address used). ssl://, stomp+ssl:// or stomps:// use TLS. Also camel.component.jms.brokerUrl.
username, passwordCredentials (also camel.component.jms.username / password).
hostSTOMP virtual host.
clientIdClient id, needed for durable subscriptions.
concurrentConsumers1Consumers on a queue (one STOMP subscription each).
prefetchSize1Unacknowledged messages per consumer.
selectorJMS selector, evaluated by the broker, for example region = 'EU' AND priority > 5.
acknowledgementModeName (or acknowledgementMode 0-3)AUTO_ACKNOWLEDGEAUTO_ACKNOWLEDGE, DUPS_OK_ACKNOWLEDGE, CLIENT_ACKNOWLEDGE (failed messages are redelivered) or SESSION_TRANSACTED.
transactedfalseProcess each message in a STOMP transaction; a failure aborts it and the broker redelivers.
replyToFixed reply queue instead of a temporary one.
replyToTypeTemporary (Shared with replyTo)Temporary, Shared or Exclusive.
requestTimeout20000InOut producer: wait (ms) for the reply.
disableReplyTofalseDo not handle reply-to.
useMessageIDAsCorrelationIDfalseReply with the request's JMSMessageID as correlation id.
deliveryPersistenttruePersistent sends (wait for a broker receipt).
deliveryMode1 (non-persistent) or 2 (persistent).
prioritybroker defaultMessage priority, 0 to 9.
timeToLive-1Message expiry in ms. -1 never expires.
explicitQosEnabledAccepted; QoS options always apply.
preserveMessageQosfalseTake priority, delivery mode and expiry from the JMSPriority, JMSDeliveryMode, JMSExpiration headers.
jmsMessageTypefrom the bodyText, Bytes, Map or Object (map and object bodies travel as JSON).
durableSubscriptionNameDurable topic subscription name.
subscriptionName, subscriptionDurable, subscriptionSharedJMS 2.0 durable and shared subscriptions.
recoveryInterval5000ms between reconnect attempts.
sslContextParameters, useGlobalSslContextParametersTLS trust settings.

Message headers

headerdirectiondescription
JMSMessageID, JMSCorrelationID, JMSDestination, JMSReplyTo, JMSDeliveryMode, JMSPriority, JMSTimestamp, JMSType, JMSRedelivered, JMSExpirationout (consumer), some in (producer)JMS message headers.
CamelJmsDestinationNameinProducer: send to this destination instead.
CamelJmsRequestTimeoutinProducer: reply timeout for this message.

Other headers travel as message properties (keys encoded with Camel's _DOT_ / _HYPHEN_ strategy).

Run it with Docker

sh
docker run --rm -e JMS_BROKER_URL=tcp://activemq:61613 -v "$PWD:/routes:ro" pmsudhi/cameleer run /routes/prices.camel.yaml

The broker must have its STOMP connector enabled (port 61613 by default on ActiveMQ and Artemis; the rabbitmq_stomp plugin on RabbitMQ).

Common questions

How do I call a JMS service and wait for the answer?

Send an InOut exchange: add a setExchangePattern: InOut step before to: jms:queue:prices, or call request_body on a producer template. The reply body replaces the message.

How do I keep topic messages while my route is stopped?

Set clientId and durableSubscriptionName (or subscriptionName with subscriptionDurable=true). A durable subscription that is not shared requires clientId.

Does Cameleer support XA transactions with JMS?

No. STOMP has no two-phase commit. Use transacted=true for local transactions and an idempotent consumer for exactly-once processing.

Found a problem?

If something on this page doesn't match what Cameleer does, or you hit a bug while building with it, please help fix it, whether you are a person or a coding agent: open an issue that describes what you saw, then fork the repository, fix it, add or update a test, run cargo test --workspace, and open a pull request. CONTRIBUTING.md explains the ground rules.

Edit this page on GitHub