Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();
like image 895
plzdontkillme Avatar asked May 17 '16 00:05

plzdontkillme


People also ask

Is CompletableFuture get blocking?

The CompletableFuture. get() method is blocking. It waits until the Future is completed and returns the result after its completion.

Is CompletableFuture thread safe?

CompletableFuture is inherently thread-safe The results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation.

How does CompletableFuture supplyAsync work?

supplyAsync. Returns a new CompletableFuture that is asynchronously completed by a task running in the given executor with the value obtained by calling the given Supplier.

What is the difference between future and CompletableFuture?

While using Future, we do not get notified when it is complete neither does it provides us a callable method which will automatically be called when the result is available but CompletableFuture provides us with a lot of callable methods which can be used as per our use case.


2 Answers

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.

like image 135
Jose Solorzano Avatar answered Sep 19 '22 04:09

Jose Solorzano


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();
like image 22
Misha Avatar answered Sep 22 '22 04:09

Misha