I have recently implemented Spring Security in my Spring 4 / Hibernate Web application to handle logging in/out and different user roles.
After a lot of reading it appears to work pretty fine now, but I noticed that exceptions thrown due to a wrong Spring Security configuration were not handled gracefully using my custom handler but shown as an ugly Tomcat error page (showing HTTP Status 500 - UserDetailsService is required followed by a stacktrace).
Solving the particular error was not difficult (adding userDetailsService(userDetailsService) in the RememberMe configuration) but the fact remains that some exceptions thrown are not handled by the ControllerAdvice shown below handling MaxUploadSizeExceededException and all other runtime exceptions:
@ControllerAdvice
public class ExceptionHandlingControllerAdvice {
public static final String DEFAULT_ERROR_VIEW = "genericerror";
@ExceptionHandler(value = MaxUploadSizeExceededException.class)
public View maxUploadSizeExceededExceptionHandler(
HttpServletRequest req) throws IOException {
String redirectUrl = req.getRequestURL().toString();
RedirectView rv = new RedirectView(redirectUrl);
FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(req);
if (outputFlashMap != null) {
outputFlashMap.put(KeyConstants.FLASH_ERROR_KEY, "Bestand is te groot");
}
return rv;
}
@ExceptionHandler(value = RuntimeException.class)
public View defaultErrorHandler(HttpServletRequest req, Exception e) {
RedirectView rv = new RedirectView("/error", true); //context relative
StackTraceElement[] steArray = e.getStackTrace();
StringBuilder stackTrace = new StringBuilder();
for (StackTraceElement element: steArray) {
stackTrace.append(element.toString() + "\n");
}
FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(req);
if (outputFlashMap != null) {
outputFlashMap.put("url", req.getRequestURL());
outputFlashMap.put("excClassName", e.getClass().getName());
outputFlashMap.put("excMessage", e.getMessage());
outputFlashMap.put("excStacktrace", stackTrace.toString());
}
e.printStackTrace();
return rv;
}
}
But the exception thrown by the incomplete configured Security is probably not caught by this mechanism because the login POST request is intercepted by Spring Security before any controller method is called. I would like to show ALL exceptions in graceful way on a custom error page, also the ones thrown before a Controller comes into place.
I cannot find much information about that, all error handling techniques described in the Spring manual (http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-exceptionhandlers) seems to use a Controller advice.
Is there a convenient way to handle ALL exceptions in a generic way? And makes that my Controller advice class to handle exceptions superfluous?