diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java index 9531af8433..c121f575bf 100644 --- a/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java +++ b/spring-web/src/main/java/org/springframework/web/method/annotation/ExceptionHandlerMethodResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +31,6 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils.MethodFilter; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.util.NestedServletException; /** * Discovers {@linkplain ExceptionHandler @ExceptionHandler} methods in a given class, @@ -39,6 +38,7 @@ import org.springframework.web.util.NestedServletException; * to the exception types supported by a given {@link Method}. * * @author Rossen Stoyanchev + * @author Juergen Hoeller * @since 3.1 */ public class ExceptionHandlerMethodResolver { @@ -126,8 +126,11 @@ public class ExceptionHandlerMethodResolver { */ public Method resolveMethod(Exception exception) { Method method = resolveMethodByExceptionType(exception.getClass()); - if (method == null && exception instanceof NestedServletException && exception.getCause() != null) { - method = resolveMethodByExceptionType(exception.getCause().getClass()); + if (method == null) { + Throwable cause = exception.getCause(); + if (cause != null) { + method = resolveMethodByExceptionType(cause.getClass()); + } } return method; } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java index 5a4c7d9248..7f9bc06665 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodExceptionResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHan /** * Checks if the handler is a {@link HandlerMethod} and then delegates to the - * base class implementation of {@link #shouldApplyTo(HttpServletRequest, Object)} + * base class implementation of {@code #shouldApplyTo(HttpServletRequest, Object)} * passing the bean of the {@code HandlerMethod}. Otherwise returns {@code false}. */ @Override @@ -54,8 +54,7 @@ public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHan @Override protected final ModelAndView doResolveException( - HttpServletRequest request, HttpServletResponse response, - Object handler, Exception ex) { + HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { return doResolveHandlerMethodException(request, response, (HandlerMethod) handler, ex); } @@ -75,7 +74,6 @@ public abstract class AbstractHandlerMethodExceptionResolver extends AbstractHan * @return a corresponding ModelAndView to forward to, or {@code null} for default processing */ protected abstract ModelAndView doResolveHandlerMethodException( - HttpServletRequest request, HttpServletResponse response, - HandlerMethod handlerMethod, Exception ex); + HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception ex); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index 63938c7f82..84c851af13 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -65,6 +65,7 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionRes * {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}. * * @author Rossen Stoyanchev + * @author Juergen Hoeller * @since 3.1 */ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver @@ -364,10 +365,10 @@ public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExce if (logger.isDebugEnabled()) { logger.debug("Invoking @ExceptionHandler method: " + exceptionHandlerMethod); } - if (exception.getCause() != null) { - // Expose root cause as provided argument as well - exceptionHandlerMethod.invokeAndHandle( - webRequest, mavContainer, exception, exception.getCause(), handlerMethod); + Throwable cause = exception.getCause(); + if (cause != null) { + // Expose cause as provided argument as well + exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception, cause, handlerMethod); } else { // Otherwise, just the given exception as-is diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java index be2926fdf6..e41f7dd629 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java @@ -25,6 +25,7 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.beans.FatalBeanException; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -70,10 +71,10 @@ public class ExceptionHandlerExceptionResolverTests { @BeforeClass public static void setupOnce() { - ExceptionHandlerExceptionResolver r = new ExceptionHandlerExceptionResolver(); - r.afterPropertiesSet(); - RESOLVER_COUNT = r.getArgumentResolvers().getResolvers().size(); - HANDLER_COUNT = r.getReturnValueHandlers().getHandlers().size(); + ExceptionHandlerExceptionResolver resolver = new ExceptionHandlerExceptionResolver(); + resolver.afterPropertiesSet(); + RESOLVER_COUNT = resolver.getArgumentResolvers().getResolvers().size(); + HANDLER_COUNT = resolver.getReturnValueHandlers().getHandlers().size(); } @Before @@ -220,9 +221,7 @@ public class ExceptionHandlerExceptionResolverTests { assertEquals("TestExceptionResolver: IllegalStateException", this.response.getContentAsString()); } - // SPR-12605 - - @Test + @Test // SPR-12605 public void resolveExceptionWithHandlerMethodArg() throws Exception { AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext(MyConfig.class); this.resolver.setApplicationContext(cxt); @@ -253,6 +252,22 @@ public class ExceptionHandlerExceptionResolverTests { assertEquals(err.toString(), this.response.getContentAsString()); } + @Test + public void resolveExceptionWithAssertionErrorAsRootCause() throws Exception { + AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext(MyConfig.class); + this.resolver.setApplicationContext(cxt); + this.resolver.afterPropertiesSet(); + + AssertionError err = new AssertionError("argh"); + FatalBeanException ex = new FatalBeanException("wrapped", err); + HandlerMethod handlerMethod = new HandlerMethod(new ResponseBodyController(), "handle"); + ModelAndView mav = this.resolver.resolveException(this.request, this.response, handlerMethod, ex); + + assertNotNull("Exception was not handled", mav); + assertTrue(mav.isEmpty()); + assertEquals(err.toString(), this.response.getContentAsString()); + } + @Test public void resolveExceptionControllerAdviceHandler() throws Exception { AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext(MyControllerAdviceConfig.class);