javareactive-programmingreactordiscord4j

Reactively handle errors in Discord4J without error propagation


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.


Solution

  • 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.