1

I have a method doTransmit which returns a CompletableFuture<T>. I want to call doTransmit in a loop and collect all the CompletableFuture<T> and convert into a CompletableFuture<List<T>> which resolves with the List<T> when all the collected CompletableFuture<T> have been resolved.

CompletableFuture<DeliveryResponse> doTransmit(Notification notification, Receiver receiver, ContentMutator contentMutator) {
   //send notification to this receiver
}

CompletableFuture<List<DeliveryResponse>> doTransmit(Notification notification, List<Receiver> receivers, ContentMutator contentMutator) {
        List<CompletableFuture<DeliveryResponse>> completableFutures = new ArrayList<>();
        receivers.forEach(receiver -> completableFutures.add(doTransmit(notification.clone(), receiver, contentMutator)));
        CompletableFuture<List<DeliveryResponse>> listCompletableFuture = CompletableFuture.supplyAsync(ArrayList::new);
        completableFutures.forEach(
                completableFuture ->
                        completableFuture.thenCombine(listCompletableFuture,
                            ((deliveryResponse, deliveryResponses) -> deliveryResponses.add(deliveryResponse))
                        )
        );
        return listCompletableFuture;
}

But when I call the second doTransmit(notification, receivers, null).thenAccept(list -> System.out.println(list.size())); the list received is empty.

I am new to the CompletableFuture concept. However, I know Javascript Promises. Please help.

Ayush Jaiswal
  • 43
  • 1
  • 8
  • So you want a `CompletableFuture` containing the `List` of the results of the other `CompletableFuture`s? – daniu Jan 25 '19 at 09:51
  • `List>` to `List` would make sense. I don't know why you'd want `CompletableFuture>`... The `T`s will have already been calculated. – Michael Jan 25 '19 at 09:53
  • From ```List``` I can check how many notifications have been delivered or failed. – Ayush Jaiswal Jan 25 '19 at 09:56

1 Answers1

1

What you want is a Supplier<List<DeliveryResponse>> which collects the responses:

// your code
List<CompletableFuture<DeliveryResponse>> completableFutures = new ArrayList<>();
receivers.forEach(receiver -> completableFutures.add(doTransmit(notification.clone(), receiver, contentMutator)));

Supplier<List<DeliveryResponse>> responseCollector = () -> {
    List<DeliveryResponse> result = new ArrayList<>();
    // get the result for each... I think you need to try-catch this
    receivers.forEach(r -> result.add(r.get());
    return result;
}

and then create a CompletableFuture from that:

CompletableFuture<List<DeliveryResponse>> listFuture = CompletableFuture.supplyAsync(responseCollector);
return listFuture;

Now the listFuture collects the results by calling get for each of the futures.

daniu
  • 14,137
  • 4
  • 32
  • 53