ExceptionHandler

Additionally you can implement a ExceptionHandler; a generic hook for handling exceptions that occurs during the execution of an HTTP request.

Imagine your e-commerce app throws an OutOfStockException when a book is out of stock:

  1. public class OutOfStockException extends RuntimeException {
  2. }
  1. class OutOfStockException extends RuntimeException {
  2. }
  1. class OutOfStockException : RuntimeException()

Along with BookController:

  1. @Controller("/books")
  2. public class BookController {
  3. @Produces(MediaType.TEXT_PLAIN)
  4. @Get("/stock/{isbn}")
  5. Integer stock(String isbn) {
  6. throw new OutOfStockException();
  7. }
  8. }
  1. @Controller("/books")
  2. class BookController {
  3. @Produces(MediaType.TEXT_PLAIN)
  4. @Get("/stock/{isbn}")
  5. Integer stock(String isbn) {
  6. throw new OutOfStockException()
  7. }
  8. }
  1. @Controller("/books")
  2. class BookController {
  3. @Produces(MediaType.TEXT_PLAIN)
  4. @Get("/stock/{isbn}")
  5. internal fun stock(isbn: String): Int? {
  6. throw OutOfStockException()
  7. }
  8. }

If you don’t handle the exception the server returns a 500 (Internal Server Error) status code.

If you want to respond 200 OK with 0 (stock level) as the response body when the OutOfStockException is thrown, you could register a ExceptionHandler:

  1. @Produces
  2. @Singleton
  3. @Requires(classes = {OutOfStockException.class, ExceptionHandler.class})
  4. public class OutOfStockExceptionHandler implements ExceptionHandler<OutOfStockException, HttpResponse> {
  5. @Override
  6. public HttpResponse handle(HttpRequest request, OutOfStockException exception) {
  7. return HttpResponse.ok(0);
  8. }
  9. }
  1. @Produces
  2. @Singleton
  3. @Requires(classes = [OutOfStockException.class, ExceptionHandler.class])
  4. class OutOfStockExceptionHandler implements ExceptionHandler<OutOfStockException, HttpResponse> {
  5. @Override
  6. HttpResponse handle(HttpRequest request, OutOfStockException exception) {
  7. HttpResponse.ok(0)
  8. }
  9. }
  1. @Produces
  2. @Singleton
  3. @Requirements(
  4. Requires(classes = [OutOfStockException::class, ExceptionHandler::class])
  5. )
  6. class OutOfStockExceptionHandler : ExceptionHandler<OutOfStockException, HttpResponse<*>> {
  7. override fun handle(request: HttpRequest<*>, exception: OutOfStockException): HttpResponse<*> {
  8. return HttpResponse.ok(0)
  9. }
  10. }
An @Error annotation capturing an exception has precedence over an implementation of ExceptionHandler capturing the same exception.