1. Overview
In this tutorial, we’ll learn how to disable and customize the default error page for a Spring Boot application, as proper error handling depicts professionalism and quality work.
2. Disabling the Whitelabel Error Page
First, we’ll see how to disable the white label error page entirely by setting the server.error.whitelabel.enabled property to false:
server.error.whitelabel.enabled=false
Adding this entry to the application.properties file will disable the error page, and show a concise page that originates from the underlying application container, e.g., Tomcat.
We can achieve the same result by excluding the ErrorMvcAutoConfiguration bean. We can do so by adding this entry to the properties file:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
#for Spring Boot 2.0
#spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
Or we can add this annotation to the main class:
@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
All the methods mentioned above will disable the white label error page. That leaves us with the question of who then actually handles the error?
Well, as mentioned above, it’s usually the underlying application container. The good news is we can further customize things by showing our custom error pages, instead of all the defaults. This is the focus of the next section.
3. Displaying Custom Error Pages
We’ll first need to create a custom HTML error page.
We’ll save the file as error.html since we’re using Thymeleaf template engine:
<!DOCTYPE html>
<html>
<body>
<h1>Something went wrong! </h1>
<h2>Our Engineers are on it</h2>
<a href="/">Go Home</a>
</body>
</html>
If we save this file in the resources/templates directory, it’ll automatically be picked up by the default Spring Boot’s BasicErrorController.
This is all we need to display our custom error page. With some styling, we’ll now have a much nicer looking error page for our users:
We can also be more specific by naming the file with the HTTP status code we want it to use; for example, saving the file as 404.html in resources/templates/error means it’ll be used explicitly for 404 errors.
3.1. A Custom ErrorController
The limitation so far is that we can’t run custom logic when errors occur. To achieve that, we have to create an error controller bean that will replace the default one.
For this, we have to create a class that implements the ErrorController interface. Additionally, we need to set the server.error.path property to return a custom path to call when an error occurrs:
@Controller
public class MyErrorController implements ErrorController {
@RequestMapping("/error")
public String handleError() {
//do something like logging
return "error";
}
}
In the snippet above, we also annotated the class with @Controller and created a mapping for the path that’s specified as the property server.error.path:
server.error.path=/error
This way the controller can handle calls to the /error path.
In the handleError(), we’ll return the custom error page we created earlier. If we trigger a 404 error now, it’s our custom page that will be displayed.
Let’s further enhance the handleError() to display specific error pages for different error types.
For example, we can have nicely designed pages specifically for 404 and 500 error types. Then we can use the HTTP status code of the error to determine a suitable error page to display:
@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if(statusCode == HttpStatus.NOT_FOUND.value()) {
return "error-404";
}
else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return "error-500";
}
}
return "error";
}
Then for a 404 error, for example, we’ll see the error-404.html page:
4. Conclusion
With this information, we can now handle errors more elegantly, and show our users an aesthetically pleasing page.
As always, the complete source code is available over on Github.