What is the Mono class in Java, and when should it be used?

I have the following Java code:

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

@Component
public class GreetingHandler {
    public Mono<ServerResponse> hello(ServerRequest request) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
                .body(BodyInserters.fromValue("Hello Spring!"));
    }
}

I understand most of the code, but I’m not clear on what the Java Mono class does and what its key features are. I searched for explanations but couldn’t find a straightforward answer. What exactly is Mono, and when should it be used?

I’ve been working with reactive systems for a while now, especially with Spring WebFlux, and here’s how I usually explain it.

The java mono type is part of Project Reactor and is essentially a reactive container for 0 or 1 item. It’s like Optional<T> but tailored for asynchronous, non-blocking flows. So when you see something like this:

public Mono<ServerResponse> hello(ServerRequest request) {
    return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
            .body(BodyInserters.fromValue("Hello Spring!"));
}

That Mono<ServerResponse> is telling you: “Hey, I’ll give you a response later—but just one!” This is super handy when your data source (like a DB or a remote API) might be slow or unavailable at the moment of request.

I’ve built a few microservices using WebFlux recently, and just to expand on Tom’s point—

The beauty of java mono really shines in non-blocking applications. You’d typically use it when you’re:

  1. Fetching a single piece of data (like a user from a database).
  2. Handling API endpoints that return just one item or a status.
  3. Chaining reactive operations using .map(), .flatMap(), etc.

Take this example:

Mono<String> name = Mono.just("Alice")
    .map(String::toUpperCase);
name.subscribe(System.out::println); // Output: ALICE

Notice how the operation doesn’t run until we subscribe? That’s the reactive magic—java mono enables lazy, event-driven programming that reacts only when needed.

After using Reactor in a high-throughput system, here’s something worth noting—

One key clarification: java mono handles one (or no) result. But if you ever need to return multiple values—like a list or a stream—you’d switch to Flux.

Example for clarity:

Flux<Integer> numbers = Flux.just(1, 2, 3, 4);
Mono<Integer> singleValue = Mono.just(42);

So, TL;DR:

  • Use java mono for 0…1 reactive values.
  • Use Flux for 0…N values.

This distinction really matters when structuring APIs or database calls in reactive programming. Choosing the right one keeps your flow clean and predictable.