2

There is a service which uses Spring AsyncRestTemplate for sending rest calls. Each call of AsyncRestTemplate.exchange() returns ListenableFuture. Something like this:

    ListenableFuture future1 = new AsyncRestTemplate().exchange(...);
    ListenableFuture future2 = new AsyncRestTemplate().exchange(...);
    ListenableFuture future3 = new AsyncRestTemplate().exchange(...);

Is there a way for create single ListenableFuture which combines all other calls? Something like Futures.allAsList from Guava.

destan
  • 4,301
  • 3
  • 35
  • 62
biven
  • 132
  • 3
  • 9

2 Answers2

3

Step #1: Convert each ListenableFuture to CompletableFuture

public CompletableFuture<T> toCompletableFuture(ListenableFuture<ResponseEntity<String>> listenableFuture) {
    final CompletableFuture<T> completableFuture = new CompletableFuture<>();

    listenableFuture.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
        @Override
        public void onFailure(Throwable e) {
            completableFuture.completeExceptionally(e);
            }
        }

        @Override
        public void onSuccess(ResponseEntity<String> result) {
            completableFuture.complete(parseResponse(result));
            }
        }
    });
    return completableFuture;
}

Step #2: call CompletableFuture.allOf(cF1, cF2, cF3...)

Gagandeep Kalra
  • 1,034
  • 14
  • 13
  • 3
    in spring 5 there is org.springframework.util.concurrent.ListenableFuture#completable method which does the same thing. – destan Aug 08 '17 at 12:47
3

Since Spring 5.0, ListenableFuture implements the method completable() which does exactly what you need:

    /**
     * Expose this {@link ListenableFuture} as a JDK {@link CompletableFuture}.
     * @since 5.0
     */
    default CompletableFuture<T> completable() {
blubb
  • 9,510
  • 3
  • 40
  • 82