Jooby catches application exception using the javadoc:ErrorHandler class. The
javadoc:ErrorHandler[DEFAULT] error handler produces simple HTML page or JSON based on the value
of the ACCEPT header and log the exception.
Not Found message: Page not found status code: 404
{
"message": "Page not found",
"status": 404,
"reason": "Not Found"
}
GET /xx 404 Not Found io.jooby.StatusCodeException: Not found at ... at ... at ... at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)
The javadoc:StatusCodeException works as generic exception that let you specify an status code.
throw new StatusCodeException(StatusCode.FORBIDDEN); throw new StatusCodeException(StatusCode.NOT_FOUND); ...
These exception types have a default status code:
-
IllegalArgumentException: BAD_REQUEST(400) (or sub-classes of it)
-
NoSuchElementException: BAD_REQUEST(400) (or sub-classes of it)
-
FileNotFound: NOT_FOUND(404) (or sub-classes of it)
-
Exception: SERVER_ERROR(500) (or sub-classes of it)
To set a custom status code, an entry should be added it to the error code map:
{
errorCode(MyException.class, StatusCode.XXX);
}You can provide your own error handler using the javadoc:Router[error, io.jooby.ErrorHandler] method:
{
error((ctx, cause, statusCode) -> { (1)
Router router = ctx.getRouter();
router.getLog().error("found `{}` error", statusCode.value(), cause); (2)
ctx.setResponseStatusCode(statusCode);
ctx.send("found `" + statusCode.value() + "` error"); (3)
});
}{
error { ctx, cause, statusCode -> (1)
val router = ctx.router
log.error("found `{}` error", statusCode.value(), cause) (2)
ctx.responseStatusCode = statusCode
ctx.send("found `${statusCode.value}` error") (3)
}
}-
Add a global/catch-all exception handler
-
Log the error to logging system
-
Send an error response to the client
You can use the javadoc:Context[render, java.lang.Object] object which looks for a registered javadoc:MessageEncoder[] or javadoc:TemplateEngine[].
The next example produces a HTML or JSON response based on the value of the Accept header.
import static io.jooby.Medio.json;
import static io.jooby.Medio.html;
{
install(new MyTemplateEngineModule()); (1)
install(new MyJsonModule()); (2)
error((ctx, cause, statusCode) -> {
Router router = ctx.getRouter();
router.getLog().error("found `{}` error", statusCode.value(), cause);
MediaType accept = ctx.accepts(json); (3)
if (json.equals(accept)) { (4)
Map error = ...;
ctx.render(error);
} else {
// fallback to html
Map error = ...;
ctx.render(new ModelAndView("error.template", error));
}
});
}import io.jooby.Medio.json
import io.jooby.Medio.html
{
install(MyTemplateEngineModule()) (1)
install(MyJsonModule()) (2)
error {ctx, cause, statusCode ->
val router = ctx.router
router.log.error("found `{}` error", statusCode.value(), cause)
val accept = ctx.accepts(json) (3)
if (json == accept) { (4)
val error = mapOf(...)
ctx.render(error)
} else {
// fallback to html
val error = mapOf(...)
ctx.render(ModelAndView("error.template", error))
}
}
}-
Install one of the available template engines
-
Install one of the available json modules
-
Test if the accept header matches the
application/jsoncontent type -
Render json or fallback to html
In addition to the generic/global error handler you can catch specific status code:
import static io.jooby.StatusCode.NOT_FOUND;
{
error(NOT_FOUND, (ctx, cause, statusCode) -> {
ctx.send(statusCode); (1)
});
}import io.jooby.StatusCode.NOT_FOUND
{
error (NOT_FOUND) { ctx, cause, statusCode ->
ctx.send(statusCode) (1)
}
}-
Send
404response to the client
Here we kind of silence all the 404 response due we don’t log anything and send an empty response.
|
Tip
|
The javadoc:Context[send, io.jooby.StatusCode] method send an empty response to the client |
In addition to the generic/global error handler you can catch specific exception type:
{
error(MyException.class, (ctx, cause, statusCode) -> {
// log and process MyException
});
}{
error (MyException::class) { ctx, cause, statusCode ->
// log and process MyException
}
}