Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Reactor : unhandled exception from map(), but is handled from a fromCallable()

Tags:

java

reactor

In the following two examples, the first one (with the map()) tells me that there's an unhandled exception from readTree(), but not in the second example. Why so ? Thx!

Mono.just(jsonString)
.map(jsonString1 -> {
    return new ObjectMapper().readTree(jsonString1);
})
.onErrorResume(IOException.class, error -> {
    return Mono.error(new InvalidContentException("error with the JSON. " + error));
})
Mono.fromCallable(() -> {
    return new ObjectMapper().readTree(jsonString);
})
.onErrorResume(IOException.class, error -> {
    return Mono.error(new InvalidContentException("error with the JSON. " + error));
})
like image 393
lgean Avatar asked Nov 01 '25 15:11

lgean


2 Answers

Mono.fromCallable :- Uses Callable as the parameter and creates a new MonoCallable object which extends Mono.So callable is a FunctionalInterface which has a method call() so this call method throws an exception.

For Example :- This won't throw an exception

Callable<JsonNode> callableObj = () -> new ObjectMapper().readTree(jsonString);

but when we call the method call() this will throw an exception.

callableObj.call();

So when we call this we are creating a MonoCallable over here,hence it is not throwing an exception.Since it is of the type Callable.

Mono.fromCallable(() -> {
    return new ObjectMapper().readTree(jsonString);
})

So when we apply a downstream call on this such as map or flatMap it will call the call() method. So if an exception occours it will be wrapped into MonoError and we don't have to explicitly handle.

This is the reason why readTree was not throwing error in Mono.fromCallable.

For further reference you can check callable here :- javadoc for callable where you can check that until you call call() it won't throw an exception.

Whereas in this case :-

Mono.just(jsonString)
.map(jsonString1 -> {
    return new ObjectMapper().readTree(jsonString1);
})
.onErrorResume(IOException.class, error -> {
    return Mono.error(new InvalidContentException("error with the JSON. " + error));
})

It is returning MonoMap which extends Mono in the .map call hence we have to handle it.

like image 185
Yasham Avatar answered Nov 04 '25 07:11

Yasham


The reason is that Mono.fromCallable is taking one Callable interface which is able to throw one exception. However, map takes Function interface which does not throw any exception. But the code inside

.map(jsonString1 -> {
return new ObjectMapper().readTree(jsonString1);})

might throw one checked exception. So the static syntax checking will report error. If map throws one runtime exception, It will not report any error. So one approach is to

try {
    //code that might throw checked exception

} catch(IOException e) 
{
  throw new RuntimeException(e)
}
like image 43
Ryan Zheng Avatar answered Nov 04 '25 07:11

Ryan Zheng



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!