Overview
SmallRye Mutiny Vert.x Bindings provides Vert.x client APIs using the Mutiny reactive programming model.
Instead of working with Vert.x Future and callback-based APIs, you use Uni (for single results) and Multi (for streams of items) with a rich, explicit set of operators.
The bindings are generated automatically from the Vert.x source code, so they stay in sync with every Vert.x release.
Why Mutiny?
- Lazy evaluation: a
Unidoes nothing until you subscribe, giving you full control over when side effects happen. - Explicit operator vocabulary: methods like
onItem().transform()andonFailure().retry()make the intent of each pipeline stage obvious. - Back-pressured streams:
Multiimplements Reactive Streams, so producers cannot overwhelm consumers. - Blocking helpers for tests and virtual threads: call
andAwait()to block until a result is available, which is useful in unit tests and when running on virtual threads.
Quick Example
The following example fetches JSON data from an HTTP endpoint. Compare the Mutiny bindings with the equivalent vanilla Vert.x code:
Future<JsonObject> fetchData(WebClient client, int retries) {
return client.get("/api/data")
.as(BodyCodec.jsonObject())
.send()
.map(HttpResponse::body)
.recover(err -> {
logger.error("Request failed", err);
if (retries > 0) {
return fetchData(client, retries - 1);
}
return Future.failedFuture(err);
});
}
With the Mutiny bindings, every step in the pipeline is visible:
send()returns aUni<HttpResponse<JsonObject>>: nothing happens yet.onItem().transform()maps the response to its JSON body when the item arrives.onFailure().retry().atMost(3)retries the entire operation up to 3 times on failure.onFailure().invoke()logs errors that persist after retries, without swallowing them.
Notice that retry logic requires no extra code with Mutiny — it is a built-in operator. With vanilla Vert.x, you need to manage a retry counter and use recursive recover() calls, as shown in the second tab.
You can also block for the result when that is appropriate (tests, virtual threads):
Explicit operators
Mutiny favours explicit names over short aliases.
Prefer onItem().transform() over map, onItem().transformToUni() over flatMap, and onItem().invoke() over a bare invoke.
The longer forms make pipelines easier to read and review.
Next Steps
- Getting Started: add the dependency and write your first Mutiny Vert.x program.
- Uni and Multi: learn the two core reactive types in depth.
- Type Mapping: understand how Vert.x types are converted to Mutiny types.
- Error Handling: strategies for handling failures in reactive pipelines.
- Available Modules: the full list of generated client modules.
- Upgrading from version 3 to 4: migrate to the new Mutiny bindings generator.
- Using the binding generator for your own APIs: learn to use the generator for your own APIs.