Skip to content
Advertisement

How to return a value from a nested CompletableFuture without blocking?

I’m having trouble returning car price value using getPrice() method because of the following error:

no instance(s) of type variable(s) U exist so that CompletableFuture<U> conforms to Double inference variable U has incompatible bounds: equality constraints: Double lower bounds: CompletableFuture<U81345>

I want getPrice return CompletableFuture<Double> but instead it returns CompletableFuture<CompletableFuture<Double>> because I’m returning a value from a nested future. I could call .join() on the nested future but I don’t want to block the thread. This is my code:

package my.package;

import java.util.concurrent.CompletableFuture;

public class Test {
    public CompletableFuture<String> getCar() {
        return CompletableFuture.completedFuture("Ford");
    }

    public CompletableFuture<Integer> getCarMileage() {
        return CompletableFuture.completedFuture(100000);
    }

    public CompletableFuture<Double> getPrice() {
        return getCar()
            .thenApplyAsync(car -> {
                // do something
                if (car.equals("Ford")) {
                    // do something
                    return getCarMileage()
                        .thenApplyAsync(mileage -> mileage * 0.2);
                } else {
                    // do something
                    return CompletableFuture.completedFuture(42);
                }
            });
    }
}

Advertisement

Answer

The operation you’re looking for (“return a Container<U> instead of plain U“) is normally called flatMap, but the Java CompletionStage API uses other terms. As the API shows, thenApplyAsync is supposed to take a T and return a U which will be wrapped into a CompletableFuture<U>, but you can instead use thenComposeAsync and return your CompletableFuture (as a “flat” return type).

Advertisement