MQTT Binding
The MQTT binding provides integration with MQTT 5 message brokers for Rumi microservices.
Overview
The MQTT binding connects a Rumi microservice to any MQTT 5 broker (for example Mosquitto, HiveMQ, or EMQX). MQTT is a natural fit for the SMA messaging model because both are topic based publish and subscribe systems, so channel keys map directly onto MQTT topics with no delimiter rewriting.
The binding speaks MQTT 5 only. It does not fall back to MQTT 3.1.1, because it relies on an MQTT 5 feature (Correlation Data) to carry Rumi's message metadata alongside the payload.
Two operating modes
The binding operates in one of two modes, and choosing the right one is the first decision when you configure it:
Default (metadata) mode — the binding carries Rumi's message metadata on the wire (in MQTT 5 Correlation Data) alongside the payload. Use this for Rumi-to-Rumi messaging over MQTT, where both ends are Rumi microservices.
Raw mode (
raw_mode=true) — the binding puts only the payload on the topic, with no Rumi metadata. Use this to integrate with an external, non-Rumi source or sink (IoT devices, telemetry feeds, an existing MQTT broker). See Connecting to External Systems.
External integration is the most common reason to use the MQTT binding, so if you are connecting to anything that is not itself a Rumi service, you almost certainly want raw mode. It is not the default, and the binding does not infer it — you must set raw_mode=true (see the note in Connecting to External Systems on what happens if you forget).
For configuration details, see MQTT Binding Configuration.
This is a first release of the MQTT binding. It supports BestEffort delivery. Guaranteed delivery is not yet supported, see Quality of Service below.
MQTT Topic Format
MQTT uses / as its topic level separator, which is the same delimiter Rumi uses for hierarchical channel keys. As a result the binding uses channel keys as MQTT topics directly, unlike the Kafka and JMS bindings which rewrite / to . for their providers.
For example, a channel with the key orders/US/IBM publishes to, and subscribes from, the MQTT topic orders/US/IBM.
Wildcard Topics
MQTT topic filters support two wildcards, and the binding maps Rumi's channel filter wildcards onto them when a channel is joined:
*
+
Matches a single topic level.
>
#
Matches the remainder of the topic. May only appear as the last level of a filter.
The mapping is applied only on the subscribe path. A published topic name is always fully qualified, since MQTT does not permit wildcards in a published topic.
Message Metadata
The binding carries Rumi's message metadata in the MQTT 5 Correlation Data field, which is the only binary companion slot the protocol offers alongside a payload. The serialized message payload travels in the MQTT payload, and the metadata travels in the correlation data. This mirrors the way the Kafka binding uses the record key to carry metadata.
MQTT 5 user properties were considered for this purpose but not used, because they are UTF-8 string pairs and would require base64 encoding of the binary metadata.
This section describes the default (metadata) mode, which is intended for Rumi-to-Rumi messaging. A consequence of carrying metadata in correlation data is that a non-Rumi MQTT subscriber can still read the payload of a message published by Rumi, but it will not interpret the correlation data. In the other direction, a message that arrives on a metadata-mode channel without correlation data is treated as corrupt and raised as an Unhandled Message, not silently accepted — to consume metadata-less messages you must use raw mode (below).
Connecting to External (Non-Rumi) Systems (Raw Mode)
To integrate with a non-Rumi MQTT source or sink, run the channel's bus in raw mode by setting raw_mode=true on the bus descriptor. In raw mode:
Outbound — the binding publishes only the serialized message payload to the resolved topic, with no correlation data. An external subscriber sees a plain MQTT message. Choose a message encoding the external system understands (for example a JSON or bytes message), since there is no Rumi metadata to describe it.
Inbound — a message that arrives with no metadata is accepted (rather than rejected as corrupt) and delivered to the application as a bytes message. A channel subscribes an MQTT topic filter — for example
sensors/+/temp— and the messages it attracts are delivered to your handlers.
Raw mode is not the default and is not inferred. If you point a default (metadata-mode) channel at an external broker, every inbound message from the non-Rumi publisher arrives without correlation data and is rejected as a corrupt message (an Unhandled Message), so nothing is delivered to your handlers. If an MQTT integration "receives nothing," the first thing to check is that raw_mode=true is set.
Metadata mode and raw mode are mutually exclusive per bus: a raw-mode bus cannot also carry Rumi metadata, so a single MQTT bus is either a Rumi-to-Rumi bus or an external-integration bus, not both.
Quality of Service
SMA defines two qualities of service, and MQTT defines three. The binding maps them as follows:
BestEffort
0 (at most once)
Supported.
Guaranteed
1 (at least once)
Not supported in this release.
In this release, a Guaranteed send is rejected with an exception rather than being silently downgraded to best effort. A Guaranteed channel may still be created and joined for inbound traffic, but any attempt to send on it fails.
As with BestEffort on other bindings, BestEffort over MQTT (QoS 0) can lose messages: an MQTT broker does not queue QoS 0 messages for a subscriber that is not currently connected, so messages published while a microservice is briefly disconnected or has not yet re-established its subscription (for example across a restart) are not delivered. Use BestEffort for streams where occasional loss is acceptable, and configure a persistent session (see clean_start) if you need the broker to hold messages across a reconnect.
See Also
MQTT Binding Configuration - Configuration reference
Messaging Model - Overview of Rumi messaging
Configuring Bus Connections - General bus configuration
Last updated