plzdontkillme
plzdontkillme

Reputation: 1527

CompletableFuture chaining results

I am trying to chain the calls/results of the methods to the next call. I get compile time error methodE because if am not able to get the reference of objB from the previous call.

How can I pass the result of the previous call to the next chain? Have I completely misunderstood the process?

Object objC = CompletableFuture.supplyAsync(() -> service.methodA(obj, width, height))
    .thenApply(objA -> {
    try {
        return service.methodB(objA);
    } catch (Exception e) {
        throw new CompletionException(e);
    }
})
   .thenApply(objA -> service.methodC(objA))
   .thenApply(objA -> {
   try {
       return service.methodD(objA); // this returns new objB how do I get it and pass to next chaining call 
       } catch (Exception e) {
           throw new CompletionException(e);
       }
    })
    .thenApply((objA, objB) -> {
       return service.methodE(objA, objB); // compilation error 
  })
 .get();

Upvotes: 14

Views: 30186

Answers (2)

Jose Solorzano
Jose Solorzano

Reputation: 470

You should use thenCompose, which is an asynchronous mapping, as opposed to thenApply, which is synchronous. Here's an example that chains two future-returning functions:

public CompletableFuture<String> getStringAsync() {
    return this.getIntegerAsync().thenCompose(intValue -> {
        return this.getStringAsync(intValue);
    });
}

public CompletableFuture<Integer> getIntegerAsync() {
    return CompletableFuture.completedFuture(Integer.valueOf(1));
}

public CompletableFuture<String> getStringAsync(Integer intValue) {
    return CompletableFuture.completedFuture(String.valueOf(intValue));
}

With thenApply you don't return a future. With thenCompose, you do.

Upvotes: 7

Misha
Misha

Reputation: 28133

You could store intermediate CompletableFuture in a variable and then use thenCombine:

CompletableFuture<ClassA> futureA = CompletableFuture.supplyAsync(...)
    .thenApply(...)
    .thenApply(...);

CompletableFuture<ClassB> futureB = futureA.thenApply(...);

CompletableFuture<ClassC> futureC = futureA.thenCombine(futureB, service::methodE);

objC = futureC.join();

Upvotes: 14

Related Questions