Tip #40 (Spring) Waiting for a Combo of CompletableFutures
In the last tip, we learned how to wait for a single CompletableFuture
using the join()
method.
But, imagine your new scenario: You’re in a loop, sending multiple messages, and now you need to wait for all CompletableFutures
to make sure everything was delivered.
Without any changes, you’d end up waiting for each message before sending the next one, right?
For this situation, we can use CompletableFuture.allOf
to create a single CompletableFuture
that completes only when all the given CompletableFutures
are done. If the definition sounds strange, don’t worry—the code is simple:
your class {
List<CompletableFuture> futures = new ArrayList<>();
loop to send a lot of messages (
var completableFuture = kafkaProducer.send(event, topic);
completableFuture
.thenAcceptAsync(result -> myJob.setStatus(NEW_STATUS))
.exceptionallyAsync(this::onFailure);
futures.add(completableFuture);
)
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
-- continue your code here
}
private Void onFailure(@NotNull Throwable t) {
log.warn("Unable to send message to Kafka. cause {}", t.getMessage());
return null;
}
Now we’ve removed join()
from the loop. Instead, we create a new CompletableFuture
using allOf()
, and then call join()
on this combined future.
With this setup, you may want to save or update all myJob
instances in the repository once the status updates are complet
Do you use CompletableFuture
? Let me know!
Happy coding!