camel-component-jms 0.18.0

JMS component for rust-camel via Java bridge
Documentation

camel-component-jms

JMS component for rust-camel. Supports ActiveMQ Classic and ActiveMQ Artemis.

URI Format

Three URI schemes are supported:

# Generic — requires explicit destination type
jms:queue:name[?param=value&...]
jms:topic:name[?param=value&...]

# Broker-specific — destination type can be omitted (defaults to queue)
activemq:queue:name[?param=value&...]
activemq:name              # shorthand → queue
activemq:topic:name

artemis:queue:name[?param=value&...]
artemis:name               # shorthand → queue
artemis:topic:name

Using activemq: or artemis: as scheme locks the broker_type automatically — no brokerType query param needed.

URI Query Parameters

Parameter Default Description
broker default_broker from config Named broker to use (must exist in the broker map)

brokerUrl, username, and password are not URI parameters — credentials live in Camel.toml or programmatic config. broker_type is inferred from the scheme (activemq: → ActiveMQ Classic, artemis: → Artemis) or from the broker config entry.

Overview

JMS component for rust-camel via Java bridge.

Camel.toml Configuration

[default.components.jms]
default_broker = "main"      # which broker to use when no ?broker= param is given

[default.components.jms.brokers.main]
broker_url  = "tcp://localhost:61616"
broker_type = "activemq"     # "activemq" | "artemis"
username    = "admin"        # optional
password    = "admin"        # optional

Multiple brokers are supported — add as many [default.components.jms.brokers.<name>] entries as needed.

Quick Start

use camel_component_jms::{BrokerType, JmsBridgePool, JmsComponent, JmsPoolConfig};
use std::sync::Arc;

// Option A: single broker (programmatic)
let pool_config = JmsPoolConfig::single_broker("tcp://localhost:61616", BrokerType::ActiveMq);
let pool = Arc::new(JmsBridgePool::from_config(pool_config).unwrap());

ctx.register_component(JmsComponent::with_scheme("jms", Arc::clone(&pool)));
ctx.register_component(JmsComponent::with_scheme("activemq", Arc::clone(&pool)));
ctx.register_component(JmsComponent::with_scheme("artemis", Arc::clone(&pool)));

// Option B: config from Camel.toml (via camel-config crate)
// JmsPoolConfig is built automatically by configure_context()
// Consumer — generic scheme
let route = RouteBuilder::from("jms:queue:orders")
    .to("log:info")
    .build()?;

// Consumer — activemq: shorthand (queue is the default)
let route = RouteBuilder::from("activemq:orders")
    .to("log:info")
    .build()?;

// Producer — explicit broker selection (multi-broker setup)
let route = RouteBuilder::from("timer:tick?period=1000")
    .set_body("hello".to_string())
    .to("activemq:queue:events?broker=secondary")
    .build()?;

// Producer — Artemis topic
let route = RouteBuilder::from("timer:tick?period=1000")
    .set_body("hello".to_string())
    .to("artemis:topic:notifications")
    .build()?;

How It Works

The component manages a Java bridge process (jlink native binary) internally:

  1. On first use, downloads the bridge binary from GitHub releases (SHA256-verified, cached at ~/.cache/rust-camel/jms-bridge/).
  2. Spawns the bridge with broker config passed via environment variables.
  3. Reads the ephemeral gRPC port from stdout ({"status":"ready","port":N}).
  4. Polls the health endpoint until ready, then routes messages over gRPC.

No Java runtime is required on the host — the bridge is a native binary.

Bridge Health Monitor

Each bridge runs a background health monitor that:

  • Checks bridge health periodically (default: every 5s)
  • Auto-restarts the bridge process on failure with exponential backoff (5s → 10s → 20s → ... up to 120s)
  • Caps restart attempts at 10 before transitioning to a permanent Degraded state

Graceful Shutdown

When using the bridge pool programmatically, call begin_shutdown() before ctx.stop() to prevent the health monitor from restarting the bridge during shutdown:

pool.begin_shutdown();          // Signal health monitors to stop restarting
ctx.stop().await?;             // Stop routes and services
pool.shutdown().await?;        // Clean up bridge processes

When using camel-cli, Ctrl+C handles shutdown automatically. A second Ctrl+C force-exits if shutdown hangs.

Environment Variables

Variable Description
CAMEL_JMS_BRIDGE_BINARY_PATH Development override — absolute path to a local jms-bridge binary; skips download entirely
CAMEL_JMS_BRIDGE_RELEASE_URL Override release download URL (must be https://github.com/**)

Development Setup

Prerequisites

  • Docker (daemon running)
  • NixOS: programs.nix-ld.enable = true must be set in your NixOS configuration
  • Linux: glibc ≥ 2.34 (Ubuntu 22.04+, Debian 12+, RHEL 9+)

Building the JMS Bridge

The bridge binary is built using Docker (no Java required on your host):

# One-time build (~5–8 min first time, faster on subsequent runs)
cargo xtask build-jms-bridge

# The binary is auto-detected. No env vars needed:
cargo run -p jms-example
cargo test -p camel-test --features integration-tests --test jms_test

Override

If you need to use a custom binary:

export CAMEL_JMS_BRIDGE_BINARY_PATH=/path/to/your/jms-bridge
cargo run -p jms-example

Known Limitations

  • IBM MQ not supported (planned for a future release)
  • No durable topic subscribers yet
  • Bridge uses AUTO_ACKNOWLEDGE — messages are acknowledged on delivery, not after processing. Failed messages cannot be redelivered by the broker.

Installation

Add to your Cargo.toml:

[dependencies]
camel-component-jms = "*"