onComplete

Signature

def onComplete[T](future: 

Description

Evaluates its parameter of type Future[T]CompletionStage<T>, and once it has been completed, extracts its result as a value of type Try[T]Try<T> and passes it to the inner route. A Try<T> can either be a Success containing the T value or a Failure containing the Throwable.

To handle the Failure case automatically and only work with the result value, use onSuccess.

To complete with a successful result automatically and just handle the failure result, use completeOrRecoverWith, instead.

Example

Scala
sourcedef divide(a: Int, b: Int): Future[Int] = Future {
  a / b
}

val route =
  path("divide" / IntNumber / IntNumber) { (a, b) =>
    onComplete(divide(a, b)) {
      case Success(value) => complete(s"The result was $value")
      case Failure(ex)    => complete(InternalServerError, s"An error occurred: ${ex.getMessage}")
    }
  }

// tests:
Get("/divide/10/2") ~> route ~> check {
  responseAs[String] shouldEqual "The result was 5"
}

Get("/divide/10/0") ~> Route.seal(route) ~> check {
  status shouldEqual InternalServerError
  responseAs[String] shouldEqual "An error occurred: / by zero"
}
Java
sourceimport static org.apache.pekko.http.javadsl.server.Directives.complete;
import static org.apache.pekko.http.javadsl.server.Directives.onComplete;
import static org.apache.pekko.http.javadsl.server.Directives.path;

// import static org.apache.pekko.http.javadsl.server.PathMatchers.*;

final Route route =
    path(
        segment("divide").slash(integerSegment()).slash(integerSegment()),
        (a, b) ->
            onComplete(
                () -> CompletableFuture.supplyAsync(() -> a / b),
                maybeResult ->
                    maybeResult
                        .map(result -> complete("The result was " + result))
                        .recover(
                            new PFBuilder<Throwable, Route>()
                                .matchAny(
                                    ex ->
                                        complete(
                                            StatusCodes.InternalServerError(),
                                            "An error occurred: " + ex.getMessage()))
                                .build())
                        .get()));

testRoute(route).run(HttpRequest.GET("/divide/10/2")).assertEntity("The result was 5");

testRoute(route)
    .run(HttpRequest.GET("/divide/10/0"))
    .assertStatusCode(StatusCodes.InternalServerError())
    .assertEntity("An error occurred: / by zero");
Note

Using the onComplete directive means that you’ll have to explicitly and manually handle failure cases. Doing this for every route in your app will result in a lot of boilerplate code. Most of the time you want to use the Exception Handling mechanism instead.

Note

The identically named onComplete method of Scala’s Future (from the standard library) does not work at all in this context since it’s just a method that returns Unit - whereas Apache Pekko HTTP’s onComplete is a Directive that creates a Route.