Reputation: 822
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
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
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