43

In my Spring Boot application, I'm trying to configure custom error pages, for example for 404, I have added a following Bean to my application configuration:

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"));
        }
    };
}

Also, I have created a following simple Thymeleaf template:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>404 Not Found</title>
        <meta charset="utf-8" />
    </head>
    <body>
        <h3>404 Not Found</h3>
        <h1 th:text="${errorCode}">404</h1>
        <p th:utext="${errorMessage}">Error java.lang.NullPointerException</p>
        <a href="/" th:href="@{/}">Back to Home Page</a>
    </body>
</html>

and added it into /resources/templates/ folder. Right now on the 404 error I can see only white screen.

What am I doing wrong and how to correctly setup my 404 page? Also, is it possible to use templates and not only static pages for custom error pages?

Mahozad
  • 18,032
  • 13
  • 118
  • 133
brunoid
  • 2,121
  • 2
  • 12
  • 22

9 Answers9

63

In Spring Boot 1.4.x you can add a custom error page:

If you want to display a custom HTML error page for a given status code, you add a file to an /error folder. Error pages can either be static HTML (i.e. added under any of the static resource folders) or built using templates. The name of the file should be the exact status code or a series mask.

For example, to map 404 to a static HTML file, your folder structure would look like this:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>
approxiblue
  • 6,982
  • 16
  • 51
  • 59
brunoid
  • 2,121
  • 2
  • 12
  • 22
  • 8
    I've tried putting my 404.html under resources/public/error , under /resources/error and still it's not being picked up with SB 1.4. I'm getting the generic 404 message. Any ideas how to troubleshoot? – Gabriel Kohen Jan 27 '17 at 14:05
  • I am using spring boot starter security. 1. when I am not logged in, I can visit error page (using master page - sidebar is shown but no links), I want that user can not visit error page unless logged in --> when not logged in, localhost:8080/error should redirect to the login page (spring security behavior), 2. when logged in, visiting localhost:8080/error causing problem --> sidebar menu links are not shown – MD TAREQ HASSAN Mar 12 '18 at 14:17
  • Hiya, this is working great locally but I can't seem to get it to work in our deployed app on PCF, any ideas? – Rebecca Douglas Mar 29 '18 at 16:25
50

You're using Thymeleaf, And Thymeleaf can handle error without a controller.

For a generic error page this Thymeleaf page need to be named as error.html
and should be placed under src/main/resources > templates > error.html

Thymleaf error.html

For specific error pages, you need to create files named as the http error code in a folder named error, like: src/main/resources/templates/error/404.html.

GoutamS
  • 3,535
  • 1
  • 21
  • 25
8

new ErrorPage(HttpStatus.NOT_FOUND, "/404.html")

That /404.html represents the URL Path to Redirect, not the template name. Since, you insist to use a template, you should create a controller that handles the /404.html and renders your 404.html resides in src/main/resources/templates:

@Controller
public class NotFoundController {
    @RequestMapping("/404.html")
    public String render404(Model model) {
        // Add model attributes
        return "404";
    }
}

You could also replace these just view render-er controllers with a View Controller:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/404.html").setViewName("404");
    }
}

Also, is it possible to use templates and not only static pages for custom error pages ?

Yes, it's possible. But Not Found pages are usually static and using a template instead of Plain Old HTMLs wouldn't make that much of a sense.

Ali Dehghani
  • 46,221
  • 15
  • 164
  • 151
6

There is no need for the EmbeddedServletContainerCustomizer bean. Simply putting the corresponding error page (such as 404.html in case of 404) in the public directory should be enough (as pointed by @brunoid).

Also note that you can also put a generic error.html page that'll get displayed whenever your application encounters an error or exception.

A simple example (in Freemarker) -

<html lang="en">
<head>
</head>
<body>
    <div class="container">
        <div class="jumbotron alert-danger">
            <h1>Oops. Something went wrong</h1>
            <h2>${status} ${error}</h2>
        </div>
    </div>
</body>

</html>

This'll display proper error status and corresponding error message. And since you are using Spring Boot, you can always override the status and error messages that get displayed on your error page.

Naiyer
  • 424
  • 7
  • 8
  • Freemarker (http://freemarker.org) is a view technology (like JSP or Thymeleaf). You don't need to use Freemarker for this to work. You can use JSP. – Naiyer Feb 25 '17 at 22:15
6

If you are using Thymeleaf like suggested in the question, you could use a template similar to the one from the previous reply, but appropriate for Thymeleaf rather than Freemarker. I have also added bootstrap for the styling:

<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
<title>Error Page</title>
<link href="/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css" rel="stylesheet" media="screen"/>
<script src="/webjars/jquery/3.2.1/jquery.min.js"></script>
<script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="jumbotron alert-danger">
    <h1>Oops... something went wrong.</h1>
    <h2 th:text="${status + ' ' + error}"></h2>
</div>
</div>
</body>
</html>

You should place this code in a file called error.html and place it in your thymeleaf templates directory. There is no need to add an additional controller for it to work.

OlgaMaciaszek
  • 3,662
  • 1
  • 28
  • 32
5

Check if you have thymeleaf present in the classpath, or add below code and reimport the project.

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Himadri Mandal
  • 325
  • 2
  • 11
3

We have to add new

 @Controller
public class MyErrorController implements ErrorController  {

    @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 "error404";
        }
        else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
            return "error500";
        }
    }
    return "error";
}

    @Override
    public String getErrorPath() {
        return "/error";
    }
}
Vipul Gulhane
  • 761
  • 11
  • 16
  • `getErrorPath` is deprecated. – e-info128 Jun 17 '20 at 21:39
  • 1
    This approach also lets you have more control over the error page. In response to the previous comment, the 'getErrorPath()' can simply return null, since it is deprecated but not removed from the interface. – Adam Wise Mar 30 '21 at 17:15
1

enter image description hereIt's very easy to do in Spring Boot Application. Spring Boot all most done all thing for us.

1)In Path src/main/resources/templates make folder which has name 'error'

2)Next create html file in this folder, save it as '404.html'.

You done evey thing here.

Spring Boot Automatically show this page if it got 404 page not found error.

Note: Before going to this, make sure that you added Thymeleaf repository in your pom. xml

-1

Thymeleaf can handle error without a controller. create error.html to resources folder.