Error Handling
When your web application throws an exception, whether user initiated or not, Alpas tries its best to handle it gracefully.
Based on the exception's status code, it first converts it to a proper HTTP exception type, such as
NotFoundHttpException
for 404, ValidationException
for 422, MethodNotAllowedException
for 405, InternalServerException
for 500, etc. It then gives each exception a chance
to report and then render the exception.
Each exception type does what is appropriate for it. Most of the exceptions return a message and a status code if the expected response is JSON.
For non-JSON responses, different exceptions do different things—ValidationException
flashes errors and inputs making it available
to the next request, both NotFoundHttpException
and InternalServerException
render a beautiful error page.
Default Error Templates
When you scaffold a new Alpas web app, two error templates for the most common HTTP exceptions — 404 Page Not Found
and 500 Internal Server Exception — are created for you under resources/errors
directory.
These error pages look great out of the box! However, you are more than welcome to modify them to make them fit more with your app's overall branding.
/alert/ Do not change the name or the location of the default error templates.
Handling Exceptions
Alpas's default way of handling the exceptions may or may not work for you. You may want to tweak it or completely change the behavior. Alpas allows you to easily intercept an exception being thrown and handle it the way you want it to. This applies for both the built-in exceptions and your own custom exceptions.
To intercept an exception, you need to provide your own subclass of dev.alpas.exceptions.ExceptionHandler
class and then override one or more of report()
, render()
, or handle()
methods.
report(exception: HttpException, call: HttpCall)
Override this method to log or send the given HTTP exception to external services like Bugsnag,
Sentry etc. By default, the report()
method passes the exception to the base class which
then calls the report()
method on the exception itself. Most of the built-in exceptions just logs a message
either as a warning or as an error.
class ExceptionHandler : dev.alpas.exceptions.ExceptionHandler() {
override fun report(exception: HttpException, call: HttpCall) {
when (exception) {
is NotFoundHttpException -> call.logger.warn { "This resource is missing!" }
is ValidationException -> call.logger.warn { "The input is invalid!" }
is MyCustomException -> ThirdPartyLogger.log(exception)
else -> super.report(exception, call)
}
}
}
render(exception: HttpException, call: HttpCall)
Override this method to generate an HTTP response for a given exception and to send it back to the client. If you want to render a template for an exception, this is the place to do it. In fact, this is how the default 404 and 500 error pages are rendered by Alpas internally.
class ExceptionHandler : dev.alpas.exceptions.ExceptionHandler() {
override fun render(exception: HttpException, call: HttpCall) {
when (exception) {
is MyCustomException -> call.render("errors/custom_error", 418)
else -> super.render(exception, call)
}
}
}
handle(exception: Throwable, call: HttpCall)
Override this method if you want to handle non-http exceptions. You may be throwing a particular type of
exception from different parts of your web app. This method is the perfect place to handle those types
of exceptions in one central place. By default, this method converts any non-HTTP exception to a
catch-all InternalServerException
and reports and renders it accordingly.
/tip/ Your custom
ExceptionHandler
class can live anywhere in your package, but we recommend putting it underexceptions
directory. Don't worry about loading this class. Alpas will automatically discover, load, and use this class for you!
Throwing HTTP Exceptions
Use HttpCall
's one of many abort() methods to throw an HTTP exception.
Stacktrace Dump
When rendering an InternalServerException
, if your app environment is set to dev mode,
it dumps the stacktrace to your web page. This makes it easy to just see what's going on without having to
resort to your IDE's console.
You can control whether the stacktrace gets dumped to your web page or not by setting a proper value for
APP_LEVEL
variable in your .env
file. Setting it to development dumps
the stacktrace; but, setting it to production doesn't.
/alert/ Make sure to set your app's level to production, before your app goes live to avoid exposing any internal data through a dumped stacktrace.