Saturday, December 5, 2015

Returning first successful result from CompletableFuture

Recently I wanted to get first non empty result from bunch of CompletableFutures. For my case, allOf - is bad because it runs all futures till end and returns nothing. AnyOf - is bad because it returns first result, even if it is empty. So there is no such function in Java API, but it is still very easy to implement, and maybe it is even more logical, because actually there are 2 cases: found or not found; and it can be easily solved with two CompletableFutures. There is example:

import java.util.concurrent.CompletableFuture

success = new CompletableFuture()

def futures = (1..10).collect { CompletableFuture.supplyAsync {
                                    if (val == 6) {
                                        success.complete(val)
                                    } else {
                                        Thread.sleep(1000)
                                    }
                                }
                          }

println CompletableFuture.allOf(futures as CompletableFuture[])
        .thenApply({ throw new RuntimeException("not found") })
        .applyToEither(success, {it}).get()


This way it will return result if there is any, or throw exception if all done and there is no result, and it can be easily adjusted to return default value, for example.