Alan
Alan

Reputation: 822

can we modify method for error handling with status codes?

I'm working on a Spring Boot project. I'm checking out the code with class named ExceptionHandlerController provided at this post and tried it in my project. It works, but for errors with status codes 400 or 500 series I need to include the status code. When I try a simple invalid url in the browser address field, the view page, error.jsp, does render but the status code is not being accessed based on the model information. I've included the HttpServletResponse parameter to obtain the status code, but the code and message doesn't show on a 404 error. The defaultErrorHanddler method doesn't even fire on a 404 error. How do we force the method to fire on 400 and 500 errors?

ExceptionHandlerController:

@ControllerAdvice
public class ExceptionHandlerController
{
   public static final String DEFAULT_ERROR_VIEW = "error";

   private static final HashMap<Integer, String> statusCodes = new HashMap<Integer, String>();

   static {
       statusCodes.put(HttpServletResponse.SC_OK, "OK");
       statusCodes.put(HttpServletResponse.SC_CREATED, "Created");
       statusCodes.put(HttpServletResponse.SC_ACCEPTED, "Accepted");
       statusCodes.put(HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION, "Non-authoritative Information");
       statusCodes.put(HttpServletResponse.SC_NO_CONTENT, "No Content");
       statusCodes.put(HttpServletResponse.SC_RESET_CONTENT, "Reset Content");
       statusCodes.put(HttpServletResponse.SC_PARTIAL_CONTENT, "Partial Content");         
       statusCodes.put(HttpServletResponse.SC_BAD_REQUEST, "Bad Request");
       statusCodes.put(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
       statusCodes.put(HttpServletResponse.SC_PAYMENT_REQUIRED, "Payment Required");
       statusCodes.put(HttpServletResponse.SC_FORBIDDEN, "Forbidden");
       statusCodes.put(HttpServletResponse.SC_NOT_FOUND, "Not Found");
       statusCodes.put(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method Not Allowed");
       statusCodes.put(HttpServletResponse.SC_NOT_ACCEPTABLE, "Not Acceptable");
       statusCodes.put(HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required");
       statusCodes.put(HttpServletResponse.SC_REQUEST_TIMEOUT, "Request Timeout");
       statusCodes.put(HttpServletResponse.SC_CONFLICT, "Conflict");
       statusCodes.put(HttpServletResponse.SC_GONE, "Gone");       
       statusCodes.put(HttpServletResponse.SC_LENGTH_REQUIRED, "Length Required");
       statusCodes.put(HttpServletResponse.SC_PRECONDITION_FAILED, "Precondition Failed");
       statusCodes.put(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE, "Request entity Too Large");
       statusCodes.put(HttpServletResponse.SC_REQUEST_URI_TOO_LONG, "Request-URI Too Long");
       statusCodes.put(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
       statusCodes.put(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, "Requested Range Not Satisfiable");
       statusCodes.put(HttpServletResponse.SC_EXPECTATION_FAILED, "Expectation Failed");
       statusCodes.put(HttpServletResponse.SC_PRECONDITION_FAILED, "Precondition Required");           
       statusCodes.put(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
       statusCodes.put(HttpServletResponse.SC_NOT_IMPLEMENTED, "Not Implemented");
       statusCodes.put(HttpServletResponse.SC_BAD_GATEWAY, "Bad Gateway");
       statusCodes.put(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
       statusCodes.put(HttpServletResponse.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
       statusCodes.put(HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported");

   }  


   @ExceptionHandler(value={Exception.class, RuntimeException.class})
   public ModelAndView defaultErrorHanddler(HttpServletRequest request, Exception e, HttpServletResponse response)
   {
       ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
       int scode = response.getStatus();
       System.out.println("scode: " + scode);
       mav.addObject("statuscode", String.valueOf(scode));
       mav.addObject("message", statusCodes.get(scode));
       mav.addObject("datetime", new Date());
       mav.addObject("exception", e);
       mav.addObject("url", request.getRequestURL());
       return mav;
   }
}

error.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML>
<html>
<head>
<title></title>
...
</head>
<body>
<div class="container">
<h1>Error Details</h1> 
    <p>Status Code: ${statuscode}</p>
    <p>Message: ${message}</p>
    <p>TimeStamp: ${datetime}</p>
    <p>Exception: ${exception}</p>
    <p>URL: ${url}</p>
    <p><a href="/">Home Page</a></p>    
</div>
</body>
</html>

Upvotes: 0

Views: 415

Answers (2)

Abhijit Sarkar
Abhijit Sarkar

Reputation: 24558

Add HttpServletResponse as a parameter to defaultErrorHandler method and call response.setStatusCode.

Edit:

For 404 to be treated as an exception, if using Spring Boot, set spring.mvc.throwExceptionIfNoHandlerFound = true. If not using Spring Boot, see this thread.

Upvotes: 1

Szymon Stepniak
Szymon Stepniak

Reputation: 42204

Alternatively you can annotate your method with @ResponseStatus, for example:

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = {Exception.class, RuntimeException.class})
public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
        ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);

    mav.addObject("datetime", new Date());
    mav.addObject("exception", e);
    mav.addObject("url", request.getRequestURL());
    return mav;
}

Upvotes: 2

Related Questions