onComplete
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
-
source
def 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
-
source
import static akka.http.javadsl.server.Directives.complete; import static akka.http.javadsl.server.Directives.onComplete; import static akka.http.javadsl.server.Directives.path; // import static scala.compat.java8.JFunction.func; // import static akka.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");
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.
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 Akka HTTP’s onComplete
is a Directive
that creates a Route
.