Scenario 1: Simple Synchronous Operation
@GET
@Produces(MediaType.TEXT_PLAIN)
public String greeting() {
return "Hello!";
}
Use Case: You have a straightforward operation that completes quickly and doesn’t involve any asynchronous tasks (database queries, network calls, etc.).
Why No Uni: In this case, using Uni would introduce unnecessary complexity. You can simply return the result directly as a String.
Scenario 2: Asynchronous Operation with a Single Result
@GET
@Produces(MediaType.APPLICATION_JSON)
public Uni<MyData> getData() {
return Uni.createFrom().emitter(e -> {
// Asynchronous task to fetch MyData (e.g., database query)
e.complete(result); // Emit the result
// Or e.fail(error); // Emit an error if something goes wrong
});
}
Use Case: Your operation involves an asynchronous task that will eventually produce a single result (MyData in this example).
Why Uni: Uni is perfect for this scenario. It represents the asynchronous result, allowing you to:
- Handle the result when it becomes available.
- Handle potential errors gracefully.
- Compose with other asynchronous operations.
Scenario 3: Asynchronous Operation with Multiple Results
@GET
@Produces(MediaType.SERVER_SENT_EVENTS)
public Multi<String> getUpdates() {
return Multi.createFrom().ticks().every(Duration.ofSeconds(1))
.onItem().transform(n -> "Update #" + n);
}
Use Case: Your operation produces a continuous stream of results (e.g., real-time updates).
Why Multi (Not Uni): Multi is designed for streams of data. It allows you to emit multiple values over time and have the client receive them as they become available.
Scenario 4: Fire-and-Forget Operation
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Uni<Void> processData(MyData data) {
return Uni.createFrom().voidItem()
.onItem().invoke(() -> {
// Asynchronous processing of the data (e.g., sending an email)
});
}
Use Case: You initiate an asynchronous task but don’t need to return a specific result to the client.
Why Uni: Returning Uni signals that the operation has been initiated and will complete in the background. The client doesn’t need to wait for a specific result.
Key Points:
- Synchronous: No asynchronous tasks? Return the result directly (e.g., String, MyData).
- Single Asynchronous Result: Use Uni to represent the result and handle it when it becomes available.
- Multiple Asynchronous Results: Use Multi to emit a stream of data.
- Fire and Forget: Use Uni when you don’t need to return a specific value.