From the Official Documentation of Mono#block() it is said that:
Subscribe to this Mono and block indefinitely until a next signal is received. Returns that value, or null if the Mono completes empty. In case the Mono errors, the original exception is thrown (wrapped in a RuntimeException if it was a checked exception).
So it is sure that block() method is blocking and it will not execute the next line untill block()
resolved.
But my confusion is while I was using toFuture()
expecting it will be non-blocking but it is behaving exactly like block
method. And in the Documentation of Mono#toFuture() it is stated:
Transform this Mono into a CompletableFuture completing on onNext or onComplete and failing on onError.
Not much clear. Nowhere in this doc said Mono#toFuture()
is blocking.
toFuture()
method blocking or non-blocking?CompletableFuture
?Update: added code snippet
using Mono.block()
method:
long time = System.currentTimeMillis();
String block = Mono.fromCallable(() -> {
logger.debug("inside in fromCallable() block()");
//Upstream httpcall with apache httpClient().
// which takes atleast 1sec to complete.
return "Http response as string";
}).block();
logger.info("total time needed {}", (System.currentTimeMillis()-time));
return CompletableFuture.completedFuture(block);
Using Mono.ToFuture()
method:
long time = System.currentTimeMillis();
CompletableFuture<String> toFuture = Mono.fromCallable(() -> {
logger.debug("inside in fromCallable() block()");
//Upstream httpcall with apache httpClient().
// which takes atleast 1sec to complete.
return "Http response as string";
}).toFuture();
logger.info("total time needed {}", (System.currentTimeMillis()-time));
return toFuture;
these two code snippets behaves exactly same.
TL;DR
Mono.toFuture()
is not blocking but Mono.toFuture().get()
is blocking. block()
is technically the same as toFuture().get()
and both are blocking.
Mono.toFuture()
just transforms Mono
into a CompletableFuture
by subscribing to it and resolving immediately. But it doesn't mean that you can access result (in your case String
) of the corresponding Mono
after this. CompletableFuture
is still async and you can use methods like thenApply()
, thenCompose()
, thenCombine()
, ... to continue async processing.
CompletableFuture<Double> result = getUserDetail(userId)
.toFuture()
.thenCompose(user -> getCreditRating(user));
where getUserDetail
is defined as
Mono<User> getUserDetail(String userId);
Mono.toFuture
is useful when you need to combine different async APIs. For example, AWS Java v2 API is async but based on CompletableFuture
but we can combine APIs using Mono.toFuture
or Mono.fromFuture
.