Custom Error Pages with Spring Boot

I’ve been a big fan of the Spring Framework. Yes, it is now even more bloated than the JEE world it set out to replace, but for enterprise software development it provides a consistent solution to common problems, including ones you might not have realized you are going to have.

My biggest gripe with Spring is how painfully slow and complicated it has been to get a Spring Framework project started. Getting a basic MVC application setup with JPA and a good view technology is a royal pain in the butt. The new Spring Boot project was created to change that.

Spring Boot has turned setting up a Spring Framework project into a breeze. It’s not perfect, but after using it on a small project, I definitely plan on using it as a baseline going forward.

One of the issues with Spring Boot is that while it does a tremendous job with 90% of the problems, there is still 10% you need to dig in and figure out. Custom error pages was one of those problems for me.

Spring Boot uses embedded Tomcat by default, which means your 404 (and other) error page is the lovely, standard Tomcat page. I don’t want my error pages showing internal application state, especially for 500 errors, so I wanted to configure custom error pages.

It turns out this a pretty simple task with the org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer class.

Add the following Bean definition to whichever class you’re using for your main method to startup Spring Boot:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {

   return (container -> {
        ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html");
        ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
        ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");

        container.addErrorPages(error401Page, error404Page, error500Page);
   });
}

This the the Java 8 version using a lambda expression to simplify things. It creates three ErrorPage instances for three common HTTP Status Codes and then adds them to the container. The ErrorPage class is an abstraction for setting up error pages which will work with both Jetty and Tomcat.

The equivalent code for Java 7 using an inner class would be this:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {

    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {

            ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401.html");
            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
            ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");

            container.addErrorPages(error401Page, error404Page, error500Page);
        }
    };
}

The actual error pages need to be place in the static content directory of the Spring Boot web application. The default location is src/main/resources/static :

File Location

For the actual files, this archive contains versions inspired by the error page included in the awesome HTML5 Boilerplate.

With files in place, you will now see a simplified version of the core error pages which don’t expose the internal state of your application. For development, you would typically want to keep your regular 500 page so you can see what blew up without chasing the log files.

6 thoughts on “Custom Error Pages with Spring Boot”

  1. If you have the actuator enabled, you get “whitelabel” error pages instead of the browser’s craptastic defaults. Then you can define your own friendly error pages by creating a view whose name is “error” (which, depending on what view resolvers you’re using, may be as simple as creating an error.jsp or error.html file). See http://docs.spring.io/spring-boot/docs/1.1.0.BUILD-SNAPSHOT/reference/htmlsingle/#howto-customize-the-whitelabel-error-page.

  2. Thanks for this mate, this one is especially useful when one need to handle ResourceHttpRequestHandler SC_NOT_FOUND response codes.

  3. Hello,

    This method was really helpful for a while.

    Now I want to modify it so that the “404.html” page is actually served through home controller, when accessing “/404”. I need to do this since the page itself needs some functionality from the controller.

    Is there a quickfix to the current solution, or a different approach altogether?

Leave a Reply

Your email address will not be published. Required fields are marked *

*