Controller based error pages spring thymeleaf
Asked Answered
P

2

3

I've managed to build static error pages and redirect to them with this bean:

    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {

        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                if (optiuniEnvironment.equals("development")) {
                    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, "/404.html");

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

However, now I want to build a custom page, that uses the functionality of the controller.

So in my controller I have something like

    @RequestMapping("/404.html")
    String pageNotFound(Model model, HttpServletRequest request)
    {
        return "404";
    }

and wish to redirect to it if I encounter the HttpStatus 404.

I believe the answer is configuring the DispatcherServlet, but not sure. Any ideas? Thanks!

(if possible, please use java-based configurations, not xml)

Psychopathy answered 18/5, 2017 at 14:2 Comment(2)
Why not implementing Exception handler, if you are using spring?Roger
That's pretty much the question. What (and maybe how) to use. I'll take a look at exception handler.Psychopathy
P
2

Solution for SpringBoot version: 1.2 - even if not the best - it's good enough for now.

Created a GlobalErrorController

@RestController
@Profile("prod")
public class GlobalErrorController implements ErrorController {

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public void error(HttpServletResponse response) throws IOException {
        int status = response.getStatus();
        switch (status) {
            case 404:
                response.sendRedirect("/404");
                break;
            case 401:
                response.sendRedirect("/401");
                break;
            case 403:
                response.sendRedirect("/401");
                break;
            default:
                response.sendRedirect("/404");
        }

    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}

And in my HomeController I added:

@RequestMapping("404")
String get404ErrorPage() {
    return "404";
}

@RequestMapping("401")
String get401ErrorPage() {
    return "401";
}

I chose this approach because I need in the error pages some functionality from the controller.

Other solutions are more than welcome!

Psychopathy answered 19/5, 2017 at 13:57 Comment(0)
R
6

You can handle these error using following methods:

  1. Using Exception Handler method in same controller:

@ExceptionHandler(NoHandlerFoundException.class)
public String handle404Exception(NoHandlerFoundException ex) {
     //do whatever you want
     return "viewName";
}
  1. Create Exception controller

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(NoHandlerFoundException.class)
    public String handle404Exception(NoHandlerFoundExceptionex) {
         //do whatever you want
         return "viewName";
    }
}

If using Spring Boot, set following properties in application.properties

server.error.whitelabel.enabled=false
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
  1. Adding Error Page Registrar:

@Bean
public ErrorPageRegistrar errorPageRegistrar(){
    return new CustomErrorPageRegistrar();
}

private static class CustomErrorPageRegistrar implements ErrorPageRegistrar {

    // Register your error pages and url paths.
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
    }

}

and define your controller endpoint for respective urls (eg. /400)

Roger answered 18/5, 2017 at 14:44 Comment(3)
I assume your solution works, however I am using spring boot 1.2.0.RELEASE and cannot update now, so this property is not available. Still, thanks for the input.Psychopathy
@Psychopathy check the third option(added it now), it might work!Roger
Hey Afridi, I tried the first two solutions and did not work (I was unable to use the resource.add-mappings=false property though, as it ruined my entire app). It did not redirect me to the classic whitelabel page, but did not redirect me to the custom one either. For the 3rd one I believe spring boot spring boot 1.4 is needed (I have 1.2). Still, inspired from this, I found a solution, even if not the best. I'll post it soon.Psychopathy
P
2

Solution for SpringBoot version: 1.2 - even if not the best - it's good enough for now.

Created a GlobalErrorController

@RestController
@Profile("prod")
public class GlobalErrorController implements ErrorController {

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public void error(HttpServletResponse response) throws IOException {
        int status = response.getStatus();
        switch (status) {
            case 404:
                response.sendRedirect("/404");
                break;
            case 401:
                response.sendRedirect("/401");
                break;
            case 403:
                response.sendRedirect("/401");
                break;
            default:
                response.sendRedirect("/404");
        }

    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}

And in my HomeController I added:

@RequestMapping("404")
String get404ErrorPage() {
    return "404";
}

@RequestMapping("401")
String get401ErrorPage() {
    return "401";
}

I chose this approach because I need in the error pages some functionality from the controller.

Other solutions are more than welcome!

Psychopathy answered 19/5, 2017 at 13:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.