6.17.4.2 Custom Exception Handler
Imagine your e-commerce app throws an OutOfStockException
when a book is out of stock:
public class OutOfStockException extends RuntimeException {
}
class OutOfStockException extends RuntimeException {
}
class OutOfStockException : RuntimeException()
Along with BookController
:
@Controller("/books")
public class BookController {
@Produces(MediaType.TEXT_PLAIN)
@Get("/stock/{isbn}")
Integer stock(String isbn) {
throw new OutOfStockException();
}
}
@Controller("/books")
class BookController {
@Produces(MediaType.TEXT_PLAIN)
@Get("/stock/{isbn}")
Integer stock(String isbn) {
throw new OutOfStockException()
}
}
@Controller("/books")
class BookController {
@Produces(MediaType.TEXT_PLAIN)
@Get("/stock/{isbn}")
internal fun stock(isbn: String): Int? {
throw OutOfStockException()
}
}
The server returns a 500 (Internal Server Error) status code if you don’t handle the exception.
To respond with 400 Bad Request as the response when the OutOfStockException
is thrown, you can register a ExceptionHandler
:
@Produces
@Singleton
@Requires(classes = {OutOfStockException.class, ExceptionHandler.class})
public class OutOfStockExceptionHandler implements ExceptionHandler<OutOfStockException, HttpResponse> {
private final ErrorResponseProcessor<?> errorResponseProcessor;
public OutOfStockExceptionHandler(ErrorResponseProcessor<?> errorResponseProcessor) {
this.errorResponseProcessor = errorResponseProcessor;
}
@Override
public HttpResponse handle(HttpRequest request, OutOfStockException e) {
return errorResponseProcessor.processResponse(ErrorContext.builder(request)
.cause(e)
.errorMessage("No stock available")
.build(), HttpResponse.badRequest()); (1)
}
}
@Produces
@Singleton
@Requires(classes = [OutOfStockException, ExceptionHandler])
class OutOfStockExceptionHandler implements ExceptionHandler<OutOfStockException, HttpResponse> {
private final ErrorResponseProcessor<?> errorResponseProcessor
OutOfStockExceptionHandler(ErrorResponseProcessor<?> errorResponseProcessor) {
this.errorResponseProcessor = errorResponseProcessor
}
@Override
HttpResponse handle(HttpRequest request, OutOfStockException e) {
errorResponseProcessor.processResponse(ErrorContext.builder(request)
.cause(e)
.errorMessage("No stock available")
.build(), HttpResponse.badRequest()) (1)
}
}
@Produces
@Singleton
@Requirements(
Requires(classes = [OutOfStockException::class, ExceptionHandler::class])
)
class OutOfStockExceptionHandler(private val errorResponseProcessor: ErrorResponseProcessor<Any>) :
ExceptionHandler<OutOfStockException, HttpResponse<*>> {
override fun handle(request: HttpRequest<*>, exception: OutOfStockException): HttpResponse<*> {
return errorResponseProcessor.processResponse(
ErrorContext.builder(request)
.cause(exception)
.errorMessage("No stock available")
.build(), HttpResponse.badRequest<Any>()) (1)
}
}
1 | The default ErrorResponseProcessor is used to create the body of the response |