handling Spring Reactor mono like an Optional for HTTP 404

433 Views Asked by At

I had understood Spring Reactor's Mono<FooBar> to be sort of like Optional<FooBar>, except that it doesn't start "pulling" data until I subscribe to it. I also understand that "pulling" may be from a WebClient, in which case I'll need to check for errors. And with HTTP an "error" of 404 isn't really an error as such—it just indicates that the requested object doesn't exist.

If I have a repository that looks up a FooBar by its ID, I don't want the consumer to have to think in terms of HTTP errors. For all the consumer knows, the repository might not even be using HTTP. Unfortunately if it's processing a Mono<FooBar>, won't it need to have some sort of error checking, and weed out HTTP 404?

Let's say my repository calls another service (the foo-bar-service) to retrieve a FooBar by its ID. Its implementation would look like this:

webClient.get().uri(FOOBAR_BY_ID_PATH, id)
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .bodyToMono(FooBar.class);

How can I add error handling to the returned Mono<FooBar> so that, if an HTTP 404 was encountered, the Mono<FooBar> is simply empty (like Optional.empty()), but any other errors are propagated for the consumer to check (via subscribe(action, error) or whatever)?

1

There are 1 best solutions below

0
On

Mono doesn't work like Optional. Mono will send one or zero messages. If you get an error, it applies an error way that will skip a lot of types of steps like flatMap, map, and so on. If mono hasn't any message, it behaves similarly to the error mode because there is no value to apply to other calls.

If you want to catch any error, you can use the onErrorResume set to replace any throwable class with a default message. (These methods will be skipped if you have or not any message.) If you haven't message in flow, you can set a default value what will be used after: defaultIfEmpty or switchIfEmpty. (These methods will be skipped if you have any message or error.)

However, there is a possibility: set to filter into web client and I guess you can handle errors. https://docs.spring.io/spring-framework/docs/6.0.8/javadoc-api/org/springframework/web/reactive/function/client/WebClient.Builder.html#filter(org.springframework.web.reactive.function.client.ExchangeFilterFunction)