vertx-web
vertx-web copied to clipboard
Inconsistent exception handling
Version
Vertx Version 4.0.2
Context
I have a problem with the exception handling vertx . makesEvery time I use the evetbus to connect to another verticle the exception does not get handled the way I expect it to get handled.
My goal is for example to write a errorHandler(500) which prints i want this to be displayed every time an uncaught exception happens. And if I try curl "http://localhost:8888/works this woks. The exception gets caught and errorHandler returns i want this to be displayed.
But if I communicate with another verticle with the eventbus the exception does not get caught and transfered to the errorHandler. This results in a pending request and with enough patience in a timeout, because the request did not get answered (In this calse curl http://localhost:8888/does-not-work)
Interestingly the error gets caught by vertx.exceptionHandler, but not by the errorHandler.
final Router router = Router.router(vertx);
final EventBus eventBus = vertx.eventBus();
router.get("/works").handler(routingContext -> {
throw new RuntimeException("gets caught");
});
router.get("/does-not-work").handler(routingContext -> {
eventBus.request("image", null, asyncResponse -> {
throw new RuntimeException("does not work");
});
});
router.errorHandler(500, routingContext -> {
routingContext.end("i want this to be displayed");
});
vertx.exceptionHandler(e -> {
System.err.println(e.toString());
// Prints: java.lang.RuntimeException: does not work
});
Expectation
I would expect vertx to handle Exceptions which happen in a callback form the evetbus the same way vertx handles exceptions which happen without a callback.
Perhaps this is a lack of understanding, but it seems weird and inconsistent.
Extra
OS: Centos 7.9 openjdk version: "1.8.0_275"
Related: ~~I was looking into having a generic handler for dealing with "Record Not Found" exceptions. In order to avoid repetition, my services would only throw a RecordNotFoundException and then a centralized error handler would pick it up and format it consistently.
But in the error handler the failure() method only returns ServiceException without its cause being available.~~
Update: I found that if I derive my exception from ServiceException, it becomes available in the handler.
Version
Vertx Version 4.0.2
Context
I have a problem with the exception handling vertx . makesEvery time I use the evetbus to connect to another verticle the exception does not get handled the way I expect it to get handled.
My goal is for example to write a
errorHandler(500)which prints i want this to be displayed every time an uncaught exception happens. And if I trycurl "http://localhost:8888/worksthis woks. The exception gets caught and errorHandler returns i want this to be displayed. But if I communicate with another verticle with the eventbus the exception does not get caught and transfered to the errorHandler. This results in a pending request and with enough patience in a timeout, because the request did not get answered (In this calsecurl http://localhost:8888/does-not-work)Interestingly the error gets caught by
vertx.exceptionHandler, but not by theerrorHandler.final Router router = Router.router(vertx); final EventBus eventBus = vertx.eventBus(); router.get("/works").handler(routingContext -> { throw new RuntimeException("gets caught"); }); router.get("/does-not-work").handler(routingContext -> { eventBus.request("image", null, asyncResponse -> { throw new RuntimeException("does not work"); }); }); router.errorHandler(500, routingContext -> { routingContext.end("i want this to be displayed"); }); vertx.exceptionHandler(e -> { System.err.println(e.toString()); // Prints: java.lang.RuntimeException: does not work });Expectation
I would expect vertx to handle Exceptions which happen in a callback form the evetbus the same way vertx handles exceptions which happen without a callback. Perhaps this is a lack of understanding, but it seems weird and inconsistent.
Extra
OS: Centos 7.9 openjdk version: "1.8.0_275"
I am also having similar issue, where I couldn't send error to front-end/client, instead waiting for timeout to occur and sending timeout exception. I would be good if this can be addressed.
There's a scope problem with the example code:
...
router.get("/does-not-work").handler(routingContext -> {
eventBus.request("image", null, asyncResponse -> {
// This code is defined inside a lambda, which means the execution is not specifically bound to
// the current vertx-web route, in this case it is bound to the execution of the eventbus (which
// means vertx-core.
throw new RuntimeException("does not work");
// because it's not bound to the route, exceptions here are not catched by the router
// but by core, that is why the vertx.exceptionHandler() can catch it
});
});
Maybe an alternative to solve this is to rewrite the code as:
router.get("/does-not-work").handler(routingContext -> {
eventBus.request("image", null, asyncResponse -> {
try {
throw new RuntimeException("does not work");
} catch (RuntimeException e) {
routingContext.fail(500, e);
}
});
});
This way exceptions on user code are handled by the user as the user so wants. Also note that the same should be done for the eventbus to be totally complete:
router.get("/does-not-work").handler(routingContext -> {
eventBus.request("image", null, asyncResponse -> {
if (asyncResponse.failed()) {
routingContext.fail(500, asyncResponse.cause());
return;
}
try {
throw new RuntimeException("does not work");
} catch (RuntimeException e) {
routingContext.fail(500, e);
}
});
});
Thanks for your reply. That is the solution I am currentely using. It is just not very elegant to surround everything with a try catch block