R. Kåbis
R. Kåbis

Reputation: 71

CompletableFuture how to return first FALSE or wait until all are completed to return TRUE

I have a bit of an odd situation that doesn’t seem to allow this peg to fit into any of the widely established CompletableFuture holes.

Right now, I am using a basic && chain to make this evaluation:

public boolean evaluateChecks() {
    return checkOne().Join() && checkTwo().Join() && checkThree().Join();
}

However this still does things in a specific order - if checkThree() is the first to return a FALSE value, it still has to wait until the prior two have provided their values before it gets evaluated, due to how the && fall-through works.

Right now all three methods return CompletableFuture<Boolean>, but I have no problem reverting these back into normal methods in order to run a CompletableFuture in the primary method that evaluates them.

I have looked at quite a few examples, but none seem to provide me with the functionality I need.

Upvotes: 1

Views: 3344

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279960

Adapted from the answer by Didier L here:

Instead of using exceptionally and completeExceptionally, use thenAccept to complete the CompletableFuture returned by allOf().

For example, save the futures because you're about to chain actions on them:

CompletableFuture<Boolean> a = checkOne(), b = checkTwo(), c = checkThree();

Use CompletableFuture.allOf to wait for all of them to complete (presumably you're not expecting failures/exceptions) and transform the Void result into the expected Boolean value of true.

CompletableFuture<Boolean> allWithFailFast = CompletableFuture.allOf(a, b, c).thenApply(__ -> a.join() && b.join() && c.join());
// if there is an exception, it'll be propagated to the future returned by thenApply

With the returned CompletableFuture above, you can now complete it faster if any of the original futures completes with false.

Stream.of(a, b, c).forEach(f -> f.thenAccept(result -> {
    if (!result) {
        allWithFailFast.complete(false);
    }
}));

Depending on the order of completions and their result, either the allOf future will complete first with a result of evaluating the futures or one of the futures will return false and cause the allWithFailFast to complete with false.

If multiple futures complete with false, only the first call to

allWithFailFast.complete(false);

will do anything, the others will essentially be ignored.

Upvotes: 2

Related Questions