KubeMQ
ConnectorsHow-to guidesMigration

Migrating from ActiveMQ

Route ActiveMQ onto KubeMQ by client type — JMS via Qpid JMS, STOMP and MQTT by endpoint; OpenWire is not supported.

ActiveMQ is a multi-protocol broker, so there is no single migration path. Which connector you use — and which guide you follow — depends on which protocol your client speaks and which ActiveMQ variant (Classic or Artemis) you run. This page is the router: it points you at the right per-protocol guide and calls out the one thing that does not migrate at all.

KubeMQ serves ActiveMQ workloads through three existing connectors — AMQP 1.0, STOMP, and MQTT — depending on the protocol. All three are opt-in (Enable = false by default); you enable only the connector(s) your clients need. The per-protocol guides carry the full code; this page keeps the endpoint deltas and the cross-cutting deviations in one place.

OpenWire is NOT supported. KubeMQ has no OpenWire wire decoder. Any client connecting over the OpenWire protocol will fail. There is no configuration option to add OpenWire support — an ActiveMQ client using the default OpenWire transport must switch to AMQP 1.0, STOMP, or MQTT before it can talk to KubeMQ.

Choose your path

Pick the row that matches your client, then follow the linked guide for the connection snippet, destination mapping, and a working code example.

Client typeActiveMQ variantConnectorGuide
Java / JMS applicationsClassic or ArtemisAMQP 1.0 (via Apache Qpid JMS)Migrating from JMS
Non-Java clients using STOMPClassic or ArtemisSTOMPMigrating from STOMP
Non-Java clients using MQTTClassic or ArtemisMQTTMigrating from MQTT
Native AMQP 1.0 clientsArtemis (native AMQP 1.0)AMQP 1.0Migrating from AMQP 1.0

Java/JMS applications keep their JMS code and swap only the ConnectionFactory implementation to Apache Qpid JMS — a client-swap. STOMP, MQTT, and native AMQP 1.0 clients are endpoint-only: change the broker host and credentials, nothing else.

Default ports (when the connector is enabled):

ConnectorPortTLS portProtocol
AMQP 1.056725671AMQP 1.0 (Qpid JMS, Artemis)
STOMP6161361614STOMP 1.0 / 1.1 / 1.2
MQTT18838883 (WS 8083)MQTT 3.1.1 / 5.0

Enable only what you need. Each connector has its own enable variable:

Enable variables
CONNECTORS_AMQP10_ENABLE=true   # Java/JMS via Qpid JMS, and native AMQP 1.0 (Artemis) clients
CONNECTORS_STOMP_ENABLE=true    # STOMP clients (Classic and Artemis)
CONNECTORSMQTT_ENABLE=true      # MQTT clients (note: no underscore)

Compatibility Matrix

This matrix is self-contained for the ActiveMQ workload across all three connectors. Where a capability differs by path, the cell names the path it applies to.

DimensionStatusNotes
Drop-in levelclient-swap / endpointJava/JMS: client-swap (Qpid JMS); STOMP/MQTT: endpoint-only
Point-to-point queuesAll three connectors support Queues
Pub/sub (non-durable)Events pattern on all paths
Durable subscriptionsVia Events Store; unsubscribe() is node-local — see Behavioral deviations
Request/reply (RPC)✅ ²AMQP 1.0 (Qpid JMS) path only
Ordering⚠️ node-localPer-channel ordering is not preserved cluster-wide
TransactionsNot supported on any path
Dead-letter / redrive❌ no client DLQ ⁶No client-settable DLQ; poison messages are silently dropped
Selectors / filtering✅ (AMQP 1.0) / ❌ (STOMP)SQL92 selectors work on the AMQP 1.0 path (Events / Events Store); no selectors on STOMP
Auth modelPLAIN (JWT)JWT in SASL PLAIN password (AMQP 1.0), CONNECT passcode (STOMP), or CONNECT password (MQTT)
TLS / mTLS5671 (AMQP 1.0), 61614 (STOMP), 8883 / wss 8083 (MQTT)
Top unsupportedOpenWire protocol; transactions; selectors on the STOMP path

Footnotes:

  • ² ActiveMQ RPC via the AMQP 1.0 (Qpid JMS) path only; STOMP reply-to works but requires a pre-existing reply subscription.
  • ⁶ See What Does NOT Migrate → Hard blockers for the authoritative statement.

Connection / Endpoint Migration

The change is the same shape on every path: point the client at the KubeMQ host and supply a KubeMQ JWT as the credential. The full code lives in the linked per-protocol guides — these tabs show only the endpoint delta.

Java applications using the ActiveMQ JMS client (ActiveMQConnectionFactory) migrate by swapping the ConnectionFactory implementation to Apache Qpid JMS — the JMS application code itself does not change. Native AMQP 1.0 clients (e.g. go-amqp, AMQP.NET Lite, Qpid Proton) and Artemis clients that already speak AMQP 1.0 migrate by changing only the broker endpoint.

ConnectionFactory / broker URI
# Before (ActiveMQ Classic, OpenWire — must switch protocol)
tcp://activemq.example.com:61616

# Before (ActiveMQ Artemis, native AMQP 1.0)
amqp://artemis.example.com:5672

# After (KubeMQ)
amqp://kubemq.example.com:5672
amqps://kubemq.example.com:5671   # TLS

For the JNDI setup, destination mapping, and the full Qpid JMS snippet, see Migrating from JMS. For the native AMQP 1.0 path (addressing, message translation, RPC, and the go-amqp snippet), see Migrating from AMQP 1.0.

STOMP endpoint
# Before (ActiveMQ Classic STOMP)
host: activemq.example.com
port: 61613

# After (KubeMQ STOMP)
host: kubemq.example.com
port: 61613   # same port; TLS on 61614

Destination compatibility note: ActiveMQ uses /queue/NAME and /topic/NAME with .-delimited names. KubeMQ accepts both forms — /topic/orders.created and /topic/orders/created reach the same KubeMQ channel orders.created. Pick one convention and apply it consistently.

For destinations, ack modes, durable subscriptions, and the full stomp.py snippet, see Migrating from STOMP.

MQTT endpoint
# Before (ActiveMQ Classic MQTT)
host: activemq.example.com
port: 1883

# After (KubeMQ MQTT)
host: kubemq.example.com
port: 1883   # plain; TLS on 8883; WS on 8083

MQTT version note: KubeMQ rejects MQTT 3.1 clients at CONNECT. Use MQTT 3.1.1 (the default for most clients, including Eclipse Paho) or MQTT 5.0.

For topic→pattern mapping, QoS, and the paho-mqtt snippet, see Migrating from MQTT.

Concept & Destination Mapping

ActiveMQ concepts map onto KubeMQ patterns through the connector chosen for each client type.

AMQP 1.0 path (Qpid JMS / Artemis)

ActiveMQ conceptKubeMQ patternChannel / address
QueueQueues/queues/<name>
Topic (non-durable)Events/events/<name>
Durable topic subscriptionEvents Store/events-store/<name>
Temporary queueDynamic node (temp reply mailbox)source.dynamic = true
Virtual Topic / shared subConsumer grouplink property x-opt-kubemq-group
Command (request/reply)Commands or Queries/commands/<name> / /queries/<name>
Reply-to/responses/<RequestID> or dynamic node

The JMS capability hint (queue / topic) lets Qpid JMS Queue("orders") and Topic("orders") map automatically without an explicit prefix — see Migrating from JMS for details.

STOMP path

ActiveMQ destinationKubeMQ destinationPattern
/queue/NAME/queue/NAMEQueues
/topic/NAME/topic/NAMEEvents
Durable topic/topic-store/NAMEEvents Store
ActiveMQ Virtual Topic VirtualTopic.X/topic/VirtualTopic.XEvents

MQTT path

ActiveMQ MQTT topic prefixKubeMQ pattern
events/<channel>Events
store/<channel>Events Store
queues/<channel>Queues
commands/<channel>Commands (MQTT 5.0 only)
queries/<channel>Queries (MQTT 5.0 only)

Wildcards + and # are supported for Events subscriptions only.

Security

All three connectors accept the same KubeMQ JWT as the credential, but deliver it differently:

ConnectorWhere the JWT goesAuth disabled
AMQP 1.0SASL PLAIN password field (username is informational)ANONYMOUS or bare AMQP header accepted
STOMPCONNECT passcode header (username recorded for audit)Any credentials accepted
MQTTCONNECT password field (username recorded for audit)Any credentials accepted

All three connectors are opt-in (Enable = false). They do not open listeners until explicitly enabled. When Authentication.Enable = false (the server default), listeners accept unauthenticated clients — enable authentication or firewall the ports when the server is reachable from untrusted networks.

TLS: each connector uses the server-wide Security block. TLS is active on the TLS port only when Security is configured. mTLS (client-certificate auth) is available on the AMQP 1.0 path via SASL EXTERNAL (cert CN = ClientID).

Authorization (Casbin): with Authorization.Enable = true, Write is enforced on SEND / produce, and Read on SUBSCRIBE / consume, against the resolved KubeMQ channel.

See Authentication & Security and the configuration reference.

What Does NOT Migrate / Deviations

Hard blockers

FeatureStatusDetail
OpenWire protocol❌ Not supportedSee the callout at the top of this page. There is no configuration option to add OpenWire support.
Transactions❌ Not supportedNo SESSION_TRANSACTED / XA (JMS), no STOMP BEGIN / COMMIT / ABORT. Use idempotent producers and at-least-once consumers instead.
Message selectors (STOMP path)❌ Not supportedThe STOMP connector rejects selector headers with ERROR selectors not supported and closes the connection. Remove all selector usage from STOMP applications.
No client-settable DLQNo dead-letter address is exposed to clients over AMQP 1.0, STOMP, or MQTT. A message that exceeds MaxReceiveCount is silently dropped — there is no consumable dead-letter address over any of these protocols.

Behavioral deviations

FeatureDeviation
Selectors (AMQP 1.0 path)Supported on Events / Events Store only (SQL92 subset via apache.org:selector-filter). Rejected on /queues/ links (amqp:not-implemented).
ActiveMQ durable subscriptionsMap to Events Store via /events-store/<name> (AMQP 1.0) or /topic-store/<name> (STOMP). Replay-position headers control where the subscription starts. unsubscribe() / DETACH of the durable identity is node-local — connect back to the same node to cleanly detach.
ActiveMQ Virtual TopicsMap to KubeMQ consumer groups via link property x-opt-kubemq-group (AMQP 1.0) or a shared STOMP subscription. No automatic VirtualTopic. prefix translation.
OrderingPer-channel ordering is node-local, not cluster-wide. MQTT ordering is QoS-dependent (QoS 0 unordered; QoS 1/2 ordered per connection only).
STOMP reply-to RPCThe reply subscription must be active before the SEND carrying reply-to is issued. Sending without a pre-existing reply subscription produces ERROR reply-to subscription required and closes the connection.
MQTT 3.1 rejectedKubeMQ refuses MQTT 3.1 clients at CONNECT. Use MQTT 3.1.1 or 5.0.
MQTT retained messagesRetainAvailable = 0. Retained publishes are rejected with an audit event (not silently dropped).
MQTT RPCRequest/reply (Commands / Queries) requires MQTT 5.0. Not available over MQTT 3.1.1.

Verification Smoke Test

Choose the path that matches your application, enable the relevant connector(s), and point a test client at the KubeMQ endpoint. The AMQP 1.0 and MQTT paths defer to their guides for the full client snippet; the STOMP quick check is below.

  • AMQP 1.0 path (Java/JMS) — requires the AMQP 1.0 connector enabled (CONNECTORS_AMQP10_ENABLE=true). See Migrating from JMS for the full Qpid JMS snippet, and Migrating from AMQP 1.0 for the native go-amqp snippet.
  • MQTT path — requires the MQTT connector enabled (CONNECTORSMQTT_ENABLE=true). See Migrating from MQTT for the full paho-mqtt snippet.

STOMP path — requires the STOMP connector enabled (CONNECTORS_STOMP_ENABLE=true):

smoke_test.py
# stomp.py 8.x — publish one message, consume it, confirm arrival
# Symbols: stomp.Connection, conn.connect, conn.send, conn.subscribe,
#          ConnectionListener.on_message, conn.ack, conn.disconnect

import stomp, time

class Listener(stomp.ConnectionListener):
    def __init__(self): self.received = []
    def on_message(self, frame):
        self.received.append(frame.body)
        print(f"received: {frame.body}")

listener = Listener()
conn = stomp.Connection([("kubemq.example.com", 61613)])
conn.set_listener("", listener)
conn.connect(login="user", passcode="<jwt-or-empty>", wait=True)

# Subscribe before publishing (required for Events pattern)
conn.subscribe("/topic/smoke-test", id=1, ack="auto")

# Publish
conn.send("/topic/smoke-test", body="hello from activemq migration")
time.sleep(1)

assert len(listener.received) == 1, "smoke test failed: no message received"
print("smoke test passed")
conn.disconnect()

See Also

Was this page helpful?

On this page