Reactive Programming with Reactor 3




Reactor ships with several operators that can be used to deal with errors: propagate errors but also recover from it (eg. by falling back to a different sequence or by retrying a new Subscription).


In the first example, we will return a Mono containing default user Saul when an error occurs in the original Mono, using the method onErrorReturn. If you want, you can even limit that fallback to the IllegalStateException class. Use the User#SAUL constant.


Let's try the same thing with Flux. In this case, we don't just want a single fallback value, but a totally separate sequence (think getting stale data from a cache). This can be achieved with onErrorResume, which falls back to a Publisher<T>.

Emit bothUser#SAUL and User#JESSE whenever there is an error in the original FLux:

OnErrorResumeWith on flux

Dealing with checked exceptions is a bit more complicated. Whenever some code that throws checked exceptions is used in an operator (eg. the transformation function of a map), you will need to deal with it. The most straightforward way is to make a more complex lambda with a try-catch block that will transform the checked exception into a RuntimeException that can be signalled downstream.

There is a Exceptions#propagate utility that will wrap a checked exception into a special runtime exception that can be automatically unwrapped by Reactor subscribers and StepVerifier: this avoid seeing an irrelevant RuntimeException in the stacktrace.

Try to use that on the capitalizeMany method within a map: you'll need to catch a GetOutOfHereException, which is checked, but the corresponding test still expects the GetOutOfHereException directly.

Checked exception
Create your playground on
This playground was created on, our hands-on, knowledge-sharing platform for developers.
Go to
* Copyright (c) 2011-2017 Pivotal Software Inc, All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* See the License for the specific language governing permissions and
* limitations under the License.
package io.pivotal.literx;
//generic imports to help with simpler IDEs (ie
import io.pivotal.literx.domain.User;
import reactor.core.Exceptions;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
* Learn how to deal with errors.
* @author Sebastien Deleuze
* @see Exceptions#propagate(Throwable)
public class Part07Errors {
// TODO Return a Mono<User> containing User.SAUL when an error occurs in the input Mono, else do not change the input Mono.
Mono<User> betterCallSaulForBogusMono(Mono<User> mono) {
return null;
// TODO Return a Flux<User> containing User.SAUL and User.JESSE when an error occurs in the input Flux, else do not change the input Flux.
Flux<User> betterCallSaulAndJesseForBogusFlux(Flux<User> flux) {
return null;
// TODO Implement a method that capitalizes each user of the incoming flux using the
// #capitalizeUser method and emits an error containing a GetOutOfHereException error
Flux<User> capitalizeMany(Flux<User> flux) {
return null;
codingame x discord
Join the CodinGame community on Discord to chat about puzzle contributions, challenges, streams, blog articles - all that good stuff!
Online Participants