Reactively handle errors in Discord4J without error propagation

226 Views Asked by At

I am making a discord bot in Discord4J, with a command handler that returns the valid command:

return Mono.just(event.getCommandName())
        .filter(commandRegistry::has)
        .map(commandRegistry::get)
        .flatMap(discordCommand -> {
            try {
                return discordCommand.executeCommand(event);
            } catch (Exception e) {
                logger.error(e.getMessage());
                return event.reply("Error occurred!").then();
            }
        })
        .then();

(discordCommand.executeCommand returns Mono)

If I try to handle the error with doOnError the error propagates and crashes the program. My question is, how do I make this reactive without the error propagating. Surrounding the entire block with try/catch doesn't work either.

2

There are 2 best solutions below

1
NovaFox161 On BEST ANSWER

All .doOnX methods are what we call "side effects". They don't subscribe to anything, instead they are called whenever the condition is met.

So instead of using try/catch, for reactive we can do the following:

return Mono.just(event.getCommandName())
    .filter(commandRegistry::has)
    .map(commandRegistry::get)
    .flatMap(discordCommand ->> discordCommand.executeCommand(event);})
    .doOnError(e -> logger.error("an error happened", e))
    .onErrorResume(e -> event.reply("Sorry, an error occurred"));

In the above, we use .doOnError as a side effect to log the error since there is no further reactive actions we wish to take when logging. Then, we use onErrorResume which allows us to gracefully handle the error by sending the user a reply instead of the error propagating.

0
Azn9 On

You can use onErrorResume to convert the error into "nothing" (Mono.empty()):

.onErrorResume(throwable -> {
    //Do whatever you want with the error
    return Mono.empty();
})