Orkun
Orkun

Reputation: 7238

Vertx - using the Router failureHandler for the errors in async calls

We have recently discovered the failureHandler in the Vertx router

We thought it could help us get rid of all the repetitive try-catch blocks we have. But alas, it seems that the exceptions that are thrown inside the callbacks are not caught by the failureHandler.

Example: below, the failureHandler is called only for the 3rd case:

// Get the user details
        router.get("/user").handler(ctx -> {

            ctx.response().headers().add("content-type", "application/json");

            // some async operation
            userApiImpl.getUser(ctx, httpClient, asyncResult -> {

//          ctx.response().setStatusCode(404).end();    //1 
//          throw new RuntimeException("sth happened"); //2 
                ctx.fail(404);  //3
            });
        });


        // ============================
        // ERROR HANDLER
        // ============================
        router.get("/user").failureHandler(ctx -> {

            LOG.info("Error handler is in the action.");
            ctx.response().setStatusCode(ctx.statusCode()).end("Error occurred in method");
        });
  1. Is this as expected?
  2. Can we somehow declare a global try-catch in a router for the exceptions occurring in the async context?

Upvotes: 1

Views: 6048

Answers (1)

tsegismont
tsegismont

Reputation: 9128

It is expected that sending a response manually with an error code does not trigger the failure handler.

It should be triggered if:

  1. the route path matches

  2. a handler throws an exception or ctx.fail() is invoked

Here's an example:

Route route1 = router.get("/somepath/path1/");

route1.handler(routingContext -> {

  // Let's say this throws a RuntimeException
  throw new RuntimeException("something happened!");

});

Route route2 = router.get("/somepath/path2");

route2.handler(routingContext -> {

  // This one deliberately fails the request passing in the status code
  // E.g. 403 - Forbidden
  routingContext.fail(403);

});

// Define a failure handler
// This will get called for any failures in the above handlers
Route route3 = router.get("/somepath/*");

route3.failureHandler(failureRoutingContext -> {

  int statusCode = failureRoutingContext.statusCode();

  // Status code will be 500 for the RuntimeException or 403 for the other failure
  HttpServerResponse response = failureRoutingContext.response();
  response.setStatusCode(statusCode).end("Sorry! Not today");

});

See the error handling section of the Vert.x Web documentation

Upvotes: 6

Related Questions