I was exploring reactive streams with project reactor, and I had a use case where I needed to skip to the next event if an error occurred during the processing of the current event (e.g., deserialization error).
For such a use case, I found out that I can use the onErrorContinue operator, but I also thought about wrapping my callback with a try catch like this:
Flux.just(1, 2, 3, 4, 5).mapNotNull(item -> {
try {
System.out.println("item = " + item);
if (item.equals(3)) throw new IllegalArgumentException(); // deserialization issue for example
return item;
} catch (Exception exception){
System.out.println(exception);
return null;
}
}).subscribe(item -> System.out.println("got element :" + item));
I have found this old issue before the introduction of onErrorContinue opperator where someone was complaining about having to wrap his callbacks in a try catch to solve the issue as I have shown in the example.
So I am wondering if there is a reason to prefer onErrorContinue over the second approach other than sticking to the functional reactive programming style, maybe? And if there is something wrong with the try-catch approach?
In Reactive Streams when an error is signaled, the publisher is considered terminated:
In order to prevent the termination of the
Publisherin Reactor, you cantry/catchor useonErrorContinuedepending on your requirements.In my opinion there is nothing wrong with
try/catchand sometimes like in the following scenario, it's the best solution, becauseonErrorContinuewill skip all error events, and sometimes you will handle terminal and non-terminal exceptions in the same chain of operators, for example:In this scenario, both exceptions thrown are the same type, but one is considered a terminal event. The correct solution for this problem in my opinion is using
try/catchinsideflatMap/concatMapinstead ofonErrorContinue:This way the terminal event will end the
Publisher, and the non-terminal event will be processed, preventing the emission by returningFlux.empty()in case of exception.