title: Problem trying to display custom error pages with Spring Boot
body: <p>I'm maintaining a Spring Boot Application that uses Swagger to define Rest web services and uses Maven for dependency management. It uses an application.yml file for properties. By default, when an error occurs, a Whitelabel page is displayed in any browser.</p>
  <p>The parent in the application's pom.xml is defined as follows:</p>
  <pre><code>&lt;parent&gt;
      &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
      &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
      &lt;version&gt;2.1.1.RELEASE&lt;/version&gt;
      &lt;relativePath /&gt; &lt;!-- lookup parent from repository --&gt;
  &lt;/parent&gt;
  
  </code></pre>
  <p>I created HTML pages in the resources/templates/error and resources/public/error each for a generic error, a 404 error, a 401 error and a 500 error.</p>
  <p>Afterwards, I tried the following solutions without success:</p>
  <ol>
  <li>According to <a href="https://www.baeldung.com/spring-boot-custom-error-page" rel="nofollow noreferrer">https://www.baeldung.com/spring-boot-custom-error-page</a>, I must follow these steps:</li>
  </ol>
  <p>1.1. Disable the Whitelabel display from the properties file or from the main class. I have chosen to do it from the main class:</p>
  <pre><code>@SpringBootApplication(scanBasePackages = &quot;com.mycompanyname&quot;)
  @EnableConfigurationProperties(AppProperties.class)
  @EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class}) // &lt;- Like this!
  public class BuySellBackendApplication {
  
      public static void main(String[] args) {
          SpringApplication.run(BuySellBackendApplication.class, args);
      }
  }
  </code></pre>
  <p>1.2. Define a custom error controller that implements the <code>ÈrrorController</code> interface. Mine is defined as follows:</p>
  <pre><code>@Controller
  public class BazaarErrorController implements ErrorController {
  
      @Override
      public String getErrorPath() {
          return &quot;/custom-error&quot;;
      }
  
      @RequestMapping(&quot;/custom-error&quot;)
      public String handleError() {
          return &quot;error&quot;;
      }
  }
  </code></pre>
  <p>1.3. Add the path to the error mapping defined from the properties file. As I am using a yml file, the property is added as follows:</p>
  <pre><code>server:
     error:
        path: &quot;/custom-error&quot;
  </code></pre>
  <p>The desired result is to display the generic error page I defined. However, the obtained result is an error page defined by Tomcat. Moreover, Tomcat's error page is triggered from the following class in the application, that uses Spring Security:</p>
  <pre><code>public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
  
      private static final Logger logger = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class);
  
      @Override
      public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
          logger.error(&quot;Responding with unauthorized error. Message - {}&quot;, e.getMessage());
          httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getLocalizedMessage());  // &lt;- This line of code
      }
  }
  </code></pre>
  <p>In those circumstances, even using the <code>@RequestBody</code> annotation and/or make return a different page according to the obtained HTTP error code is useless.</p>
  <p>I cannot erase the lines of code of the authentication entry point due to the company's requirements. Also, instead of redirecting me to my error page, it opens the browser's download dialog.</p>
  <ol start="2">
  <li>According to <a href="https://www.logicbig.com/tutorials/spring-framework/spring-boot/servlet-error-handling-outside-mvc.html" rel="nofollow noreferrer">https://www.logicbig.com/tutorials/spring-framework/spring-boot/servlet-error-handling-outside-mvc.html</a>, I must define an error page register. Spring Web provides the <code>ErrorPageRegistrar</code> interface to do this:</li>
  </ol>
  <pre><code>@Bean
  public ErrorPageRegistrar errorPageRegistrar() {
      return registry -&gt; {
          ErrorPage e404=new ErrorPage(HttpStatus.NOT_FOUND, &quot;/error/&quot; + HttpStatus.NOT_FOUND.value());
          ErrorPage e401=new ErrorPage(HttpStatus.UNAUTHORIZED, &quot;/error/&quot; + HttpStatus.UNAUTHORIZED.value());
          ErrorPage e500=new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, &quot;/error/&quot; + HttpStatus.INTERNAL_SERVER_ERROR.value());
          ErrorPage egeneric=new ErrorPage(&quot;/error/error&quot;);
          registry.addErrorPages(e401, e404, e500, egeneric);
      };
  }
  </code></pre>
  <p>The obtained result is the same as overriding the Authentication entry point and go to the browser's download dialog in solution 1. Also, it's not very clear if the String argument in the <code>ErrorPage</code>'s constructor is a physical HTML file or a servlet mapping.</p>
  <ol start="3">
  <li>Define an error view resolver using Spring's ErrorViewResolver interface as described in <a href="https://forketyfork.medium.com/how-to-customize-error-page-selection-logic-in-spring-boot-8ea1a6ae122d" rel="nofollow noreferrer">https://forketyfork.medium.com/how-to-customize-error-page-selection-logic-in-spring-boot-8ea1a6ae122d</a>:</li>
  </ol>
  <pre><code>@Configuration
  public class ErrorPageConfig {
      private static final Logger logger = LoggerFactory.getLogger(ErrorPageConfig.class);
      @Bean
      public ErrorViewResolver errorViewResolver(ApplicationContext context, ResourceProperties properties){
          ErrorViewResolver resolver=(request, status, model) -&gt; {
              String pathFormat=&quot;error/%d&quot;;
              String path=&quot;&quot;;
              switch(status.value()) {
                  case 401: case 404: case 500:
                      path=String.format(pathFormat, status.value());
                      break;
                  default:
                      logger.info(&quot;Codigo de error obtenido {}&quot;, status.value());
                      path=&quot;error/error&quot;;
                      break;
              }
              return new ModelAndView(path);
          };
          return resolver;
      }
  }
  </code></pre>
  <p>It gives me the same result as solution 2.</p>
  <p>How can I resolve this problem?
  Thanks in advance</p>