Messaging / Event-Driven Architecture

Messaging for Spring Boot microservices with Kafka and RabbitMQ

Spring Middleware provides a platform model for messaging in Spring Boot microservices. It standardizes publishers, consumers, and event-driven patterns across Kafka and RabbitMQ, including retry strategies, dead-letter handling, and explicit runtime behavior.

Kafka messaging RabbitMQ messaging Event-driven architecture Publishers and consumers Retry and dead-letter handling Platform messaging patterns

What messaging means here

Messaging in Spring Middleware is not just a wrapper around broker clients. The goal is to standardize how services publish events, consume messages, attach cross-cutting behavior, and manage infrastructure concerns such as topics, queues, bindings, retries, and dead-letter routing.

  • Keep publisher and consumer behavior explicit
  • Reduce repeated broker-specific setup in each service
  • Support both event-driven and integration-style messaging
  • Keep runtime hooks available for tracing, metrics, and error handling

Two messaging styles

Spring Middleware supports two complementary messaging models. Kafka is oriented to event streams and publisher/subscriber configuration. RabbitMQ is exposed through a JMS-like, annotation-driven resource model with producers, consumers, handlers, listeners, and lifecycle control.

  • Kafka: topic-based event publishing and subscriber registration.
  • RabbitMQ: resource-driven producers and consumers with explicit lifecycle and processing hooks.
  • Both: platform conventions instead of one-off per-service wiring.

High-level messaging view

Services publish or consume messages through platform-aligned abstractions, while broker-specific behavior remains visible and configurable.

Producer Service Consumer Service Spring Middleware Messaging Layer publishers • consumers • handlers • listeners • error handling Kafka Topics RabbitMQ Queues / Exchanges

Kafka runtime model

Kafka support is oriented around configuration-backed publishers and subscribers, with predictable event metadata and module-level error handling.

01

Configure topics and publishers

Topic definitions, publisher ids, and subscriber settings are declared under middleware.kafka.

02

Publish events

A named publisher wraps payloads into an EventEnvelope<T> and sends them through Kafka.

03

Consume and handle failures

Registered subscribers process records with retry and optional dead-letter behavior when configured.

Kafka configuration example

middleware:
  kafka:
    bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
    create-missing-topics: true
    topics:
      catalog-events:
        partitions: 5
        replication-factor: 3
    publishers:
      catalog:
        topic: ${KAFKA_TOPIC_CATALOG:catalog-events}
    subscribers:
      catalog:
        topic: ${KAFKA_TOPIC_CATALOG:catalog-events}
        group-id: ${KAFKA_GROUP_ID_CATALOG:catalog-service-group}
        concurrency: 3

Error handling example

middleware:
  kafka:
    error-handling:
      enabled: true
      max-retries: 3
      retry-backoff-ms: 1000
      dead-letter:
        enabled: true
        suffix: .DLT

RabbitMQ runtime model

RabbitMQ support is annotation-driven and resource-oriented. Producers, consumers, handlers, listeners, and error handlers are discovered and wired at startup.

01

Discover resources

JmsFactory scans configured packages and creates producers and consumers.

02

Attach processing hooks

Listeners, handlers, and error handlers are matched through annotation-based rules.

03

Process, acknowledge, or rollback

Runtime behavior depends on transacted sessions, acknowledgement mode, and configured error handlers.

Producer Resource RabbitMQ Broker Consumer Resource Processing hooks listeners • handlers • error handlers acknowledge • commit • rollback

Consumer example

@JmsConsumer
@JmsDestination(name = "information-uk", destinationType = DestinationType.QUEUE)
public class JmsConsumerUK extends JmsConsumerResource<TestingMessage> {

    public void process(TestingMessage testingMessage, Properties properties) {
        logger.info("Message Received " + testingMessage.getMessage() + "-UK");
    }
}

Handler pattern

@JmsHandler(ConsumerHandler.class)
public class ConsumerHandlerResource<T> extends JmsHandlerResource<String, T> {

    @Override
    public String handleBeforeProcessingMessage(T message, Properties properties) {
        return "dbSession";
    }
}

Messaging conventions in practice

The messaging model is designed to keep services explicit while reducing repeated infrastructure code.

Explicit configuration

Topics, queues, publishers, subscribers, and client behavior are declared clearly instead of being hidden in scattered runtime wiring.

Cross-cutting hooks

Handlers, listeners, and error handlers provide structured extension points for tracing, metrics, transactions, and alerts.

Operational predictability

Retry, acknowledge, rollback, dead-letter routing, and resource lifecycle remain part of the platform model, not implicit broker magic.