liveBook · Manning

Reactive messaging

As explained in Quarkus in Action

MicroProfile Reactive Messaging is a MicroProfile specification for defining asynchronous message-based communication between application components and external messaging systems.

MicroProfile Reactive Messaging defines an API for asynchronous message passing. It helps microservices communicate without waiting for responses on blocked threads or coupling services too closely. In Quarkus, SmallRye Reactive Messaging implements the specification; application code can use the same channel API with different messaging brokers. section 9.0 section 9.10

A channel is a named virtual address for messages. Methods on CDI beans produce, consume, or process those messages: @Outgoing names the channel a method produces to, while @Incoming names the channel it consumes from. A processor has both annotations. A channel has one source and one sink; processors connect through additional, uniquely named channels. Message flow builds on Reactive Streams, but Quarkus does not require every messaging method to use reactive types. section 9.3 section 9.3.2 section 9.8.2

Listing 9.1 MicroProfile Reactive Messaging with Mutiny example
@Outgoing("ticks")
public Multi<Long> aFewTicks() {
    return Multi.createFrom()
        .ticks().every(Duration.ofSeconds(1))
        .select().first(5);
}

@Incoming("ticks")
@Outgoing("times")
public Multi<String> processor(Multi<Long> ticks) {
    return ticks.map(tick -> Instant.now().toString());
}

@Incoming("times")
public void consumer(String payload) {
    System.out.println(payload);
}

A Mutiny Multi produces ticks, a processor transforms them into time strings, and a consumer prints the results; channel names connect the three methods. section 9.3.2

For an imperative entry point, inject an Emitter with @Channel and call send. Its CompletionStage completes when the message is acknowledged, completes exceptionally on a negative acknowledgment, and remains incomplete if no acknowledgment arrives. @Channel can also inject a channel as a Publisher or Mutiny Multi, for example to serve events over an HTTP server-sent-events connection. section 9.3.4

Send an invoice after a reservation

Add the quarkus-messaging extension, inject an Emitter<Invoice> for the invoices channel, and send an invoice when a reservation is persisted. An @Incoming("invoices") method can first act as a local Billing stub. Later, a RabbitMQ connector carries invoices to a separate Billing service, where a processor persists each invoice and forwards it for payment. When forwarding a Message, withPayload preserves its metadata and acknowledgment behavior. section 9.4 section 9.8.2

Connectors bridge application channels to external systems such as RabbitMQ and Kafka; their configuration selects the broker for a channel. Quarkus packages SmallRye connectors as separate extensions and can start broker Dev Services in development mode. For blocking work inside a pipeline, mark the method @Blocking. Asynchronous messages do not themselves trigger Quarkus live reload in Dev mode. section 9.10 section 9.8.2

How Quarkus in Action covers it

How deep it goes
Develops channels, annotated methods, emitters, connectors, acknowledgment handling, and blocking work through an invoice-processing implementation.
Examples
Uses a tick-processing pipeline and a reservation-to-billing invoice flow, including a local stub and RabbitMQ-backed processing.
What it assumes
Builds on prior reactive-programming and Reactive Streams concepts while defining messaging channels and annotations before applying them.
What you can do after
Apply it via Quarkus and SmallRye to connect annotated methods, send invoices from an HTTP endpoint, and route them through broker connectors.
How it connects
Connects Reactive Streams, CDI, Mutiny, RabbitMQ, Kafka, and server-sent events.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Quarkus in Action. The section links point to the parts of the book it draws on.