2

Continuing the thread: Global exception page in Apache Tiles and Spring MVC

I have an error page defined in my web.xml:

<error-page>
    <error-code>404</error-code>
    <location>/WEB-INF/jsp/404.jsp</location>
</error-page>

I have noticed one more issue in Spring MVC:

a) if no @RequestMapping is matched then indeed, my custom error jsp is printed.

b) if a @RequestMapping is matched, but the method sets an error status eg.

response.setStatus(404);

then Tomcat's (7.0.29) default error page is chosen, not my jsp.

Why? How to make my 404 page be displayed always ?

Community
  • 1
  • 1
Prospolon
  • 361
  • 1
  • 4
  • 12

3 Answers3

5

I think what you're experiencing is caused by the line you mentioned: response.setStatus(404);

This method doesn't trigger the container's error page mechanism, it should be used when there is no error. To trigger the mechanism, you have to use sendError, which is recommended in the official docs.

BTW I've just found out that the behavior differs between Servlet Spec. 2.3 and 2.4 (read here). In 2.3 the two methods are said to do the very same thing, whereas in 2.4 they differ..............

emesx
  • 12,555
  • 10
  • 58
  • 91
  • Wow. after 3 hours trying to understand why my error pages were overided by Tomcat, I tried your solution.. and that was it. Just sending the status solved the problem. This is crazy, the framework is not doing its job there. – Guillaume F. Oct 24 '16 at 15:12
0

With spring MVC is preferable using build-in exception handler to show error page to the users.

Take a look this tutorial: http://doanduyhai.wordpress.com/2012/05/06/spring-mvc-part-v-exception-handling/

alberto-bottarini
  • 1,213
  • 9
  • 21
  • I use a handler to handle uncaught `Throwables` but this is not a case: I need to handle a 404 (both coming from an unresolved mapping and from some code setting the status) – Prospolon Jun 03 '13 at 12:01
0

You may want to take a look at ExceptionHandler.

It is really nice and flexible and allows you to implement logic to display different error pages and output different HTTP reponse codes depending on the exception (this is not always a requirement but is nice to know you could do that easily).

I paste here my code as I think it can be useful to solve common issues regarding this topic.

@ExceptionHandler(Exception.class)
public ModelAndView resolveException(Exception ex,
                                     HttpServletRequest request,
                                     HttpServletResponse response) {

    // I get an email if something goes wrong so that I can react.
    if (enableEmailErrorReporting)
        sendExceptionEmail(request.getRequestURL().toString(), ex);

    ModelAndView mav = getModelAndView(ex, request);

    setStatusCode(ex, response);

    return mav;

}

protected ModelAndView getModelAndView(Exception ex,
                                       HttpServletRequest request) {
    // Here you can implement custom logic to retrieve the correct
    // error page depending on the exception. You should extract
    // error page paths as properties or costants.
    return new ModelAndView("/WEB-INF/app/error.html");
}

// This is really nice.
// Exceptions can have status codes with the [`ResponseStatus`][2] annotation.
private void setStatusCode(Exception ex, HttpServletResponse response) {

    HttpStatus statusCode = HttpStatus.BAD_REQUEST;

    ResponseStatus responseStatus =
            AnnotationUtils.findAnnotation(ex.getClass(),
                                           ResponseStatus.class);

    if (responseStatus != null)
        statusCode = responseStatus.value();

    response.setStatus(statusCode.value());

}

The logic here is that a controller method throws an uncatched exception. Spring will invoke the method marked with ExceptionHandler (you can have one per controller, per exception, or a global default one, usually I make all my controllers inherit from a BaseController class where I define this method). Passed to the method are the exception itself and any other info you need to choose the right view to display. Even more, you can see if on the exception has been declared a specific HTTP response code (eg, 500 for unchecked exception, 400 for validation errors, etc...) and return that code along with your error page.

namero999
  • 2,882
  • 18
  • 24