> For the complete documentation index, see [llms.txt](https://docs.rumi.systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rumi.systems/rumi-core/concepts/messaging-model.md).

# Messaging Model

Rumi microservices are message-driven services that communicate through a flexible and powerful messaging model built on the Simple Messaging API (SMA). SMA provides a messaging abstraction layer that allows applications to communicate with one another (and external applications) using a consistent API, regardless of the underlying messaging provider.

## Overview

SMA defines a simple yet robust messaging API that allows any **bus provider** (messaging backbone such as Solace, JMS brokers, etc.) to be seamlessly integrated into the platform by implementing a **messaging binding** for that provider. The AEP engine underlying a Rumi microservice handles interaction with SMA on behalf of the microservice, managing the lifecycle of messaging connections, providing send methods, and dispatching received messages to message handlers in a transactionally atomic fashion with respect to the microservice's state updates.

At a high level, developers model messages using the Application Data Modeler (ADM) and map those messages to logical message buses and channels. Through configuration, logical buses are bound to actual messaging fabric implementations provided by bus providers (e.g., a Solace broker URL), and message channels are mapped to topics on that messaging fabric.

![SMA Overview](/files/S1Me61KlaEAV1CWEzuJ0)

*SMA provides an abstraction layer between Rumi microservices and messaging providers*

## Core Messaging Abstractions

### Message Buses

A **message bus** groups messaging participants (bus users) that exchange messages. Each bus serves as a messaging sandbox containing one or more message channels. An AEP engine uses its name as the bus username when connecting to a message bus.

### Message Bus User

A **bus user** is a messaging participant. When an AEP engine connects to a bus, it identifies itself using a username (typically the engine's configured name). This identity is used for:

* Connection authentication and authorization
* Message sender identification
* Administrative operations

### Messages (Views)

A **message** (represented by the [`MessageView`](https://build.neeveresearch.com/rumi/javadoc/LATEST/com/neeve/sma/MessageView.html) interface) is the unit of exchange between messaging participants. A MessageView is a Plain Old Java Object that:

* Implements the `MessageView` interface
* Provides accessors to the message's underlying fields
* Handles encoding and decoding for transmission
* Is modeled using the Application Data Modeler (ADM)

Messages are typed objects generated from ADM schema definitions. See [Modeling Messages & State](/rumi-core/guides/developing-applications/modeling-messages-and-state.md) for details on message modeling.

### Message Encoding

SMA transports MessageViews as bytes encoded according to the message's encoding type. The platform natively supports:

* **JSON** - Human-readable text format for debugging and interoperability
* **Protobuf** - Google Protocol Buffers for efficient binary encoding
* **Xbuf2** - Rumi's zero-garbage implementation with Protobuf wire encoding for maximum performance

The platform also has limited support for **Custom** encodings, useful for integrating with formats not native to the platform. Custom encoding is currently available in custom message bus bindings, with broader support anticipated.

See [Choosing an Encoding Type](/rumi-core/guides/developing-applications/modeling-messages-and-state/the-code-generator/choosing-an-encoding-type.md) for guidance on selecting an encoding.

### Message Channels

A **message channel** serves as a named conduit for messages between messaging participants. Senders send messages on a channel, and receivers express interest by joining the channel. Each channel can be configured with:

* **Quality of Service (QoS)**: BestEffort or Guaranteed delivery
* **Channel Keys**: Routing patterns that map channels to provider destinations

Channels are mapped to physical message bus provider destinations (such as topics) via a **channel key**, which allows channels to be bound to different message providers through configuration.

![Channel Mapping](/files/UQ2QJ2HEhymBvJRRqfjZ)

*Channels are mapped to provider destinations via channel keys*

#### Joining and Leaving Channels

Specifying that a channel should be **joined** indicates interest in receiving messages on that channel. When a channel is configured for join, the bus provider issues subscriptions for the associated topic. When a bus channel is closed, the microservice can elect to **leave** the channel, removing previously issued subscriptions.

See [Registering Message Interest](/rumi-core/guides/developing-applications/configuring-messaging/registering-message-interest.md) for configuration details.

#### Channel Quality of Service

SMA supports two qualities of service for message channels:

* **BestEffort**: In the absence of failures in the microservice or message fabric, messages won't be dropped. No durability guarantees across failures.
* **Guaranteed**: The messaging provider must support at-least-once delivery of messages even in the presence of message fabric or microservice failures. An AEP engine working with Guaranteed QoS supports exactly-once processing by filtering out duplicates, provided the message bus provider provides appropriate ordering guarantees.

### Channel Keys and Filters

**Channel keys** and **channel filters** enable fine-grained message routing on the bus:

* **Channel Keys**: Configured bus-wide and define a routing pattern (e.g., `Orders/${Region}/${Firm}/${Symbol}`)
* **Message Keys**: Resolved at send time using the channel key and message contents via **Key Resolution Tables (KRT)**
* **Channel Filters**: Configured per participant to specify which messages to receive (e.g., `Region=US|EMEA;Firm=BOA`)

A sent message is delivered only to participants with filters that match the message's resolved key.

#### Static vs Dynamic Keys

Channel keys can be either **static** or **dynamic**:

* **Static Keys**: Fixed topic names that don't vary (e.g., `OrderEvents`)
* **Dynamic Keys**: Allow substitution of variable portions in the topic at runtime, with dynamic components sourced from fields on the message being sent or from channel filters

**Example**: A message sent on a channel with a dynamic key of `Orders/${Region}/${Firm}/${Symbol}` where the message has:

* `getRegion() == "EMEA"`
* `getFirm() == "BOA"`
* `getSymbol() == "MSFT"`

Would be sent on topic: `Orders/EMEA/BOA/MSFT`

#### Channel Filters

A channel filter is used to filter subscriptions issued for a channel that has a dynamic key.

**Example**: A channel joined with:

* Dynamic key: `Orders/${OrderState}/${Region}`
* Filter: `OrderState=New|Canceled;Region=US`

Would issue subscriptions for:

* `Orders/New/US`
* `Orders/Canceled/US`

See [Sending Messages](/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/sending-messages.md) for details on message keys and routing.

### Message Participation

To participate in message exchange, a Rumi microservice:

1. **Connects** to one or more message buses
2. **Joins** channels it's interested in receiving messages from
3. **Processes** inbound messages in message handlers
4. **Sends** outbound messages through channels

The AEP engine manages the lifecycle and policies of messaging connections and registers message interest on behalf of the microservice.

## Messaging Bindings

A **messaging binding** (also called a "bus binding") is the component that connects a Rumi microservice to the messaging fabric provided by a **bus provider** (the underlying messaging backbone such as Solace, ActiveMQ, Tibco EMS, etc.). The binding handles:

* **Protocol Translation**: Converting between message POJOs (Plain Old Java Objects implementing the MessageView interface) and the provider's native protocol
* **Connection Management**: Establishing and maintaining connections to the messaging infrastructure
* **Message Transport**: Sending and receiving messages via the provider's API
* **Provider-Specific Features**: Leveraging unique capabilities of each messaging technology

### Binding Architecture

When a messaging user, such as the AEP engine, sends a message POJO (Plain Old Java Object implementing the MessageView interface) through a message bus binding:

1. The message POJO is serialized using a particular encoding (JSON, Protobuf, or Xbuf2)
2. The binding prepares a metadata object that contains metadata information, including information for the receiving side to know how to reconstitute the message POJO from the serialized form
3. The binding transmits the serialized message via the provider's native protocol
4. On the receiving side, the binding receives the provider's native message format
5. The binding uses the metadata information to deserialize the message and reconstruct the message POJO (MessageView instance)
6. The binding dispatches the message POJO to the receiving user

### Connection Descriptors

Each binding is configured through a **connection descriptor** that specifies:

* **Provider Type**: Which binding to use (jms, solace, loopback, executor)
* **Connection Details**: Address, port, credentials
* **Provider-Specific Properties**: Settings unique to each binding
* **Common Properties**: Cross-provider settings (key handling, concurrent sends, etc.)

Example descriptor formats:

```xml
<!-- Non-decomposed format -->
<bus name="orders-bus" descriptor="activemq://localhost:61616&set_key_on_receipt=true" />

<!-- Decomposed format -->
<bus name="orders-bus">
  <provider>activemq</provider>
  <address>localhost</address>
  <port>61616</port>
  <properties>
    <set_key_on_receipt>true</set_key_on_receipt>
  </properties>
</bus>
```

## Available Bindings

Rumi provides built-in bindings for various messaging technologies:

### [Solace Binding](/rumi-core/concepts/messaging-model/solace-binding.md)

Native integration with Solace PubSub+ message brokers using JCSMP (Java) or CCSMP (JNI) for high-performance, low-latency messaging.

**Use when:** Ultra-low latency and high throughput requirements with Solace PubSub+ infrastructure

**Configuration:** [Solace Binding Configuration](/rumi-core/guides/developing-applications/configuring-messaging/configuring-bus-connections/solace-binding.md)

### [JMS Binding](/rumi-core/concepts/messaging-model/jms-binding.md)

JNDI-based integration with JMS 1.1 message brokers, including provider-specific optimizations for ActiveMQ and Tibco EMS.

**Use when:** Integrating with existing JMS infrastructure or enterprise messaging systems

**Configuration:** [JMS Binding Configuration](/rumi-core/guides/developing-applications/configuring-messaging/configuring-bus-connections/jms-binding.md)

### [Loopback Binding](/rumi-core/concepts/messaging-model/loopback-binding.md)

In-memory messaging for applications running in the same process.

**Use when:** Development, testing, or single-process deployments

**Configuration:** [Loopback Binding Configuration](/rumi-core/guides/developing-applications/configuring-messaging/configuring-bus-connections/loopback-binding.md)

### [Executor Binding](/rumi-core/concepts/messaging-model/executor-binding.md)

Thread-based messaging for offloading processor-intensive work or implementing outbound gateways.

**Use when:** Processor-intensive tasks need to run on separate threads or implementing custom outbound integrations

**Configuration:** [Executor Binding Configuration](/rumi-core/guides/developing-applications/configuring-messaging/configuring-bus-connections/executor-binding.md)

## Choosing a Binding

Consider these factors when selecting a messaging binding:

* **Existing Infrastructure**: Use bindings compatible with your deployed messaging systems
* **Performance Requirements**: Match latency and throughput needs to binding capabilities
* **Deployment Model**: Cloud, on-premise, hybrid, or single-JVM
* **Message Persistence**: Whether messages need to survive restarts
* **Scalability**: Single-process vs. distributed system requirements

## Related Topics

* [Configuring Bus Connections](/rumi-core/guides/developing-applications/configuring-messaging/configuring-bus-connections.md) - How to configure buses and bindings
* [Registering Message Interest](/rumi-core/guides/developing-applications/configuring-messaging/registering-message-interest.md) - How to join channels and receive messages
* [Sending Messages](/rumi-core/guides/developing-applications/authoring-user-code/message-processing/processing-messages/sending-messages.md) - How to send messages through channels

## Next Steps

1. Review individual binding pages to understand each provider's characteristics
2. Learn how to [configure bus connections](/rumi-core/guides/developing-applications/configuring-messaging/configuring-bus-connections.md)
3. Understand [message processing](/rumi-core/guides/developing-applications/authoring-user-code/message-processing.md) in microservices


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.rumi.systems/rumi-core/concepts/messaging-model.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
