Andrew Cheong
Andrew Cheong

Reputation: 30293

Do I have to call join() for a future inside a whenComplete()?

I'm adding some code to an existing endpoint to send an email. We don't need the result of sending an email to return a response to the user, so I'm adding a .whenComplete() at the end of the chain of futures, calling our email service from within. The call to the email service is also async, returning a CompletionStage<Void>.

CompletionStage<SomeResponse> someEndpoint() {
  return doThings()
      .thenApply(things -> {
        return someResponseFormat(things);
      })
      .whenComplete((someResponse, ex) -> {
        if (ex == null) {
          emailClient.sendEmail(someResponse); // CompletionStage<Void>
        }
      });
}

As I understand, that task will be scheduled and executed. Do I need to call join() on sendEmail(...)? Would doing so have a different behavior than not calling them? What is the best practice?

Edit: Originally I asked if I need to call join() or get(), which was misunderstood as "which do I need to call," when I meant, "do I need to call either at all."

Upvotes: 0

Views: 1166

Answers (1)

Holger
Holger

Reputation: 298539

The operation associated with emailClient.sendEmail(someResponse) will be scheduled regardless of whether you wait for its completion, so unless the JVM terminates in the meanwhile, it will complete. But

  • Nobody will notice when the operation completed or be able to wait for its completion.

  • Nobody will notice when the operation fails with an exception.

So what you probably want to do, is

CompletionStage<SomeResponse> someEndpoint() {
  return doThings()
      .thenApply(things -> someResponseFormat(things))
      .thenCompose(someResponse -> emailClient.sendEmail(someResponse)
          .thenApply(_void -> someResponse));
}

Then, when the caller of someEndpoint() invokes join() on it, the join() would wait for the completion of the sendEmail and also report errors when sendEmail fails. Likewise, when the caller of someEndpoint() chains dependent operations, they would start after the completion of sendEmail.

Upvotes: 3

Related Questions