Consider subtypes in exception error page mapping
Fixes gh-417
This commit is contained in:
@@ -71,6 +71,8 @@ class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContainer imple
|
||||
|
||||
private final Map<Class<?>, String> exceptions = new HashMap<Class<?>, String>();
|
||||
|
||||
private final Map<Class<?>, Class<?>> subtypes = new HashMap<Class<?>, Class<?>>();
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
}
|
||||
@@ -118,14 +120,34 @@ class ErrorPageFilter extends AbstractConfigurableEmbeddedServletContainer imple
|
||||
private void handleException(HttpServletRequest request,
|
||||
HttpServletResponse response, ErrorWrapperResponse wrapped, Throwable ex)
|
||||
throws IOException, ServletException {
|
||||
String errorPath = getErrorPath(this.exceptions, ex.getClass());
|
||||
Class<?> type = ex.getClass();
|
||||
String errorPath = this.global;
|
||||
if (this.exceptions.containsKey(type)) {
|
||||
errorPath = this.exceptions.get(type);
|
||||
}
|
||||
else {
|
||||
if (this.subtypes.containsKey(type)) {
|
||||
errorPath = this.exceptions.get(this.subtypes.get(type));
|
||||
}
|
||||
else {
|
||||
Class<?> subtype = type;
|
||||
while (subtype != Object.class) {
|
||||
subtype = subtype.getSuperclass();
|
||||
if (this.exceptions.containsKey(subtype)) {
|
||||
this.subtypes.put(subtype, type);
|
||||
errorPath = this.exceptions.get(subtype);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errorPath == null) {
|
||||
rethrow(ex);
|
||||
return;
|
||||
}
|
||||
setErrorAttributes(request, 500, ex.getMessage());
|
||||
request.setAttribute(ERROR_EXCEPTION, ex);
|
||||
request.setAttribute(ERROR_EXCEPTION_TYPE, ex.getClass().getName());
|
||||
request.setAttribute(ERROR_EXCEPTION_TYPE, type.getName());
|
||||
wrapped.sendError(500, ex.getMessage());
|
||||
request.getRequestDispatcher(errorPath).forward(request, response);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ import static org.junit.Assert.assertThat;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ErrorWrapperEmbeddedServletContainerFactoryTests {
|
||||
public class ErrorPageFilterTests {
|
||||
|
||||
private ErrorPageFilter filter = new ErrorPageFilter();
|
||||
|
||||
@@ -119,4 +119,27 @@ public class ErrorWrapperEmbeddedServletContainerFactoryTests {
|
||||
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE),
|
||||
equalTo((Object) RuntimeException.class.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subClassExceptionError() throws Exception {
|
||||
this.filter.addErrorPages(new ErrorPage(RuntimeException.class, "/500"));
|
||||
this.chain = new MockFilterChain() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
super.doFilter(request, response);
|
||||
throw new IllegalStateException("BAD");
|
||||
}
|
||||
};
|
||||
this.filter.doFilter(this.request, this.response, this.chain);
|
||||
assertThat(((HttpServletResponseWrapper) this.chain.getResponse()).getStatus(),
|
||||
equalTo(500));
|
||||
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE),
|
||||
equalTo((Object) 500));
|
||||
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_MESSAGE),
|
||||
equalTo((Object) "BAD"));
|
||||
assertThat(this.request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE),
|
||||
equalTo((Object) IllegalStateException.class.getName()));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user