From c91ab1ad6e1b177023e35e092088ace6e2021cce Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 3 May 2011 15:39:13 +0000 Subject: [PATCH] Resolve custom args after annotated args, set PATH_WITHIN_HANDLER_MAPPING attribute, and rename resolver for @ExceptionHandler methods --- .../config/MvcAnnotationDrivenExecutor.java | 4 +- .../handler/AbstractHandlerMethodMapping.java | 2 + ...=> ExceptionHandlerExceptionResolver.java} | 6 +- .../RequestMappingHandlerMethodAdapter.java | 123 ++++++++---------- .../RequestMappingHandlerMethodMapping.java | 1 + ...tationDrivenBeanDefinitionParserTests.java | 6 +- ...ceptionHandlerExceptionResolverTests.java} | 10 +- .../annotation/ServletHandlerMethodTests.java | 2 +- .../UriTemplateServletHandlerMethodTests.java | 2 +- 9 files changed, 74 insertions(+), 82 deletions(-) rename org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/{RequestMappingHandlerMethodExceptionResolver.java => ExceptionHandlerExceptionResolver.java} (98%) rename org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/{RequestMappingHandlerMethodExceptionResolverTests.java => ExceptionHandlerExceptionResolverTests.java} (95%) diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/MvcAnnotationDrivenExecutor.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/MvcAnnotationDrivenExecutor.java index 51f63254b3d..1337ec4660f 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/MvcAnnotationDrivenExecutor.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/MvcAnnotationDrivenExecutor.java @@ -42,7 +42,7 @@ import org.springframework.web.servlet.handler.ConversionServiceExposingIntercep import org.springframework.web.servlet.handler.MappedInterceptor; import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodMapping; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; @@ -118,7 +118,7 @@ final class MvcAnnotationDrivenExecutor extends AbstractSpecificationExecutor extends AbstractHandlerMap * @param request the current request */ protected void handleMatch(T mapping, String lookupPath, HttpServletRequest request) { + request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, lookupPath); } /** diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodExceptionResolver.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java similarity index 98% rename from org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodExceptionResolver.java rename to org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java index 683da2a81e3..3d8f09f04db 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodExceptionResolver.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java @@ -79,7 +79,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodR * @author Rossen Stoyanchev * @since 3.1 */ -public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandlerMethodExceptionResolver implements +public class ExceptionHandlerExceptionResolver extends AbstractHandlerMethodExceptionResolver implements InitializingBean { private List customArgumentResolvers; @@ -96,9 +96,9 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle private HandlerMethodReturnValueHandlerComposite returnValueHandlers; /** - * Creates an instance of {@link RequestMappingHandlerMethodExceptionResolver}. + * Creates an instance of {@link ExceptionHandlerExceptionResolver}. */ - public RequestMappingHandlerMethodExceptionResolver() { + public ExceptionHandlerExceptionResolver() { StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316 diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java index 11ec8651dab..d0d613d86bd 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapter.java @@ -331,95 +331,84 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda } public void afterPropertiesSet() throws Exception { + initArgumentResolvers(); + initReturnValueHandlers(); + initInitBinderArgumentResolvers(); + } + + private void initArgumentResolvers() { if (argumentResolvers == null) { argumentResolvers = new HandlerMethodArgumentResolverComposite(); - argumentResolvers.addResolvers(customArgumentResolvers); - argumentResolvers.addResolvers(getDefaultArgumentResolvers(messageConverters, beanFactory)); } - if (returnValueHandlers == null) { - returnValueHandlers = new HandlerMethodReturnValueHandlerComposite(); - returnValueHandlers.addHandlers(customReturnValueHandlers); - returnValueHandlers.addHandlers(getDefaultReturnValueHandlers(messageConverters, modelAndViewResolvers)); - } + // Annotation-based resolvers + argumentResolvers.addResolver(new RequestParamMethodArgumentResolver(beanFactory, false)); + argumentResolvers.addResolver(new RequestParamMapMethodArgumentResolver()); + argumentResolvers.addResolver(new PathVariableMethodArgumentResolver()); + argumentResolvers.addResolver(new ServletModelAttributeMethodProcessor(false)); + argumentResolvers.addResolver(new RequestResponseBodyMethodProcessor(messageConverters)); + argumentResolvers.addResolver(new RequestHeaderMethodArgumentResolver(beanFactory)); + argumentResolvers.addResolver(new RequestHeaderMapMethodArgumentResolver()); + argumentResolvers.addResolver(new ServletCookieValueMethodArgumentResolver(beanFactory)); + argumentResolvers.addResolver(new ExpressionValueMethodArgumentResolver(beanFactory)); + // Custom resolvers + argumentResolvers.addResolvers(customArgumentResolvers); + + // Type-based resolvers + argumentResolvers.addResolver(new ServletRequestMethodArgumentResolver()); + argumentResolvers.addResolver(new ServletResponseMethodArgumentResolver()); + argumentResolvers.addResolver(new HttpEntityMethodProcessor(messageConverters)); + argumentResolvers.addResolver(new ModelMethodProcessor()); + argumentResolvers.addResolver(new ErrorsMethodArgumentResolver()); + + // Default-mode resolution + argumentResolvers.addResolver(new RequestParamMethodArgumentResolver(beanFactory, true)); + argumentResolvers.addResolver(new ServletModelAttributeMethodProcessor(true)); + } + + private void initInitBinderArgumentResolvers() { if (initBinderArgumentResolvers == null) { initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite(); - initBinderArgumentResolvers.addResolvers(customArgumentResolvers); - initBinderArgumentResolvers.addResolvers(getDefaultInitBinderArgumentResolvers(beanFactory)); } - } - - public static List getDefaultArgumentResolvers( - List> messageConverters, ConfigurableBeanFactory beanFactory) { - - List resolvers = new ArrayList(); // Annotation-based resolvers - resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, false)); - resolvers.add(new RequestParamMapMethodArgumentResolver()); - resolvers.add(new PathVariableMethodArgumentResolver()); - resolvers.add(new ServletModelAttributeMethodProcessor(false)); - resolvers.add(new RequestResponseBodyMethodProcessor(messageConverters)); - resolvers.add(new RequestHeaderMethodArgumentResolver(beanFactory)); - resolvers.add(new RequestHeaderMapMethodArgumentResolver()); - resolvers.add(new ServletCookieValueMethodArgumentResolver(beanFactory)); - resolvers.add(new ExpressionValueMethodArgumentResolver(beanFactory)); + initBinderArgumentResolvers.addResolver(new RequestParamMethodArgumentResolver(beanFactory, false)); + initBinderArgumentResolvers.addResolver(new RequestParamMapMethodArgumentResolver()); + initBinderArgumentResolvers.addResolver(new PathVariableMethodArgumentResolver()); + initBinderArgumentResolvers.addResolver(new ExpressionValueMethodArgumentResolver(beanFactory)); + + // Custom resolvers + argumentResolvers.addResolvers(customArgumentResolvers); // Type-based resolvers - resolvers.add(new ServletRequestMethodArgumentResolver()); - resolvers.add(new ServletResponseMethodArgumentResolver()); - resolvers.add(new HttpEntityMethodProcessor(messageConverters)); - resolvers.add(new ModelMethodProcessor()); - resolvers.add(new ErrorsMethodArgumentResolver()); + initBinderArgumentResolvers.addResolver(new ServletRequestMethodArgumentResolver()); + initBinderArgumentResolvers.addResolver(new ServletResponseMethodArgumentResolver()); // Default-mode resolution - resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, true)); - resolvers.add(new ServletModelAttributeMethodProcessor(true)); - - return resolvers; - } - - public static List getDefaultInitBinderArgumentResolvers( - ConfigurableBeanFactory beanFactory) { - - List resolvers = new ArrayList(); - - // Annotation-based resolvers - resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, false)); - resolvers.add(new RequestParamMapMethodArgumentResolver()); - resolvers.add(new PathVariableMethodArgumentResolver()); - resolvers.add(new ExpressionValueMethodArgumentResolver(beanFactory)); - - // Type-based resolvers - resolvers.add(new ServletRequestMethodArgumentResolver()); - resolvers.add(new ServletResponseMethodArgumentResolver()); - - // Default-mode resolution - resolvers.add(new RequestParamMethodArgumentResolver(beanFactory, true)); - - return resolvers; + initBinderArgumentResolvers.addResolver(new RequestParamMethodArgumentResolver(beanFactory, true)); } - public static List getDefaultReturnValueHandlers( - List> messageConverters, List modelAndViewResolvers) { - - List handlers = new ArrayList(); + private void initReturnValueHandlers() { + if (returnValueHandlers == null) { + returnValueHandlers = new HandlerMethodReturnValueHandlerComposite(); + } // Annotation-based handlers - handlers.add(new RequestResponseBodyMethodProcessor(messageConverters)); - handlers.add(new ModelAttributeMethodProcessor(false)); + returnValueHandlers.addHandler(new RequestResponseBodyMethodProcessor(messageConverters)); + returnValueHandlers.addHandler(new ModelAttributeMethodProcessor(false)); + + // Custom return value handlers + returnValueHandlers.addHandlers(customReturnValueHandlers); // Type-based handlers - handlers.add(new ModelAndViewMethodReturnValueHandler()); - handlers.add(new ModelMethodProcessor()); - handlers.add(new ViewMethodReturnValueHandler()); - handlers.add(new HttpEntityMethodProcessor(messageConverters)); + returnValueHandlers.addHandler(new ModelAndViewMethodReturnValueHandler()); + returnValueHandlers.addHandler(new ModelMethodProcessor()); + returnValueHandlers.addHandler(new ViewMethodReturnValueHandler()); + returnValueHandlers.addHandler(new HttpEntityMethodProcessor(messageConverters)); // Default handler - handlers.add(new DefaultMethodReturnValueHandler(modelAndViewResolvers)); - - return handlers; + returnValueHandlers.addHandler(new DefaultMethodReturnValueHandler(modelAndViewResolvers)); } @Override diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java index 05add0002ae..985079c5d3c 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodMapping.java @@ -157,6 +157,7 @@ public class RequestMappingHandlerMethodMapping extends AbstractHandlerMethodMap @Override protected void handleMatch(RequestMappingInfo mapping, String lookupPath, HttpServletRequest request) { + super.handleMatch(mapping, lookupPath, request); String pattern = mapping.getPatterns().iterator().next(); Map uriTemplateVariables = pathMatcher.extractUriTemplateVariables(pattern, lookupPath); request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java index 77cca9fc67f..f753c8a9e45 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParserTests.java @@ -39,7 +39,7 @@ import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter; /** @@ -71,14 +71,14 @@ public class AnnotationDrivenBeanDefinitionParserTests { public void testMessageConverters() { loadBeanDefinitions("mvc-config-message-converters.xml"); verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodAdapter.class), true); - verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodExceptionResolver.class), true); + verifyMessageConverters(appContext.getBean(ExceptionHandlerExceptionResolver.class), true); } @Test public void testMessageConvertersWithoutDefaultRegistrations() { loadBeanDefinitions("mvc-config-message-converters-defaults-off.xml"); verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodAdapter.class), false); - verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodExceptionResolver.class), false); + verifyMessageConverters(appContext.getBean(ExceptionHandlerExceptionResolver.class), false); } @SuppressWarnings("unchecked") diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodExceptionResolverTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java similarity index 95% rename from org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodExceptionResolverTests.java rename to org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java index 435785d4011..8ef768be648 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodExceptionResolverTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolverTests.java @@ -43,18 +43,18 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.support.InvocableHandlerMethod; import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; /** - * Test fixture with {@link RequestMappingHandlerMethodExceptionResolver}. + * Test fixture with {@link ExceptionHandlerExceptionResolver}. * * @author Rossen Stoyanchev * @author Arjen Poutsma * @since 3.1 */ -public class RequestMappingHandlerMethodExceptionResolverTests { +public class ExceptionHandlerExceptionResolverTests { - private RequestMappingHandlerMethodExceptionResolver exceptionResolver; + private ExceptionHandlerExceptionResolver exceptionResolver; private MockHttpServletRequest request; @@ -62,7 +62,7 @@ public class RequestMappingHandlerMethodExceptionResolverTests { @Before public void setUp() throws Exception { - exceptionResolver = new RequestMappingHandlerMethodExceptionResolver(); + exceptionResolver = new ExceptionHandlerExceptionResolver(); exceptionResolver.afterPropertiesSet(); request = new MockHttpServletRequest(); response = new MockHttpServletResponse(); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java index 63b09829256..7987abb925d 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletHandlerMethodTests.java @@ -2636,7 +2636,7 @@ public class ServletHandlerMethodTests { Class adapterType = RequestMappingHandlerMethodAdapter.class; wac.registerBeanDefinition("handlerAdapter", new RootBeanDefinition(adapterType)); - Class resolverType = RequestMappingHandlerMethodExceptionResolver.class; + Class resolverType = ExceptionHandlerExceptionResolver.class; wac.registerBeanDefinition("requestMappingResolver", new RootBeanDefinition(resolverType)); resolverType = ResponseStatusExceptionResolver.class; diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java index 9fa67d3bd35..bf82e6fe14a 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletHandlerMethodTests.java @@ -607,7 +607,7 @@ public class UriTemplateServletHandlerMethodTests { Class adapterType = RequestMappingHandlerMethodAdapter.class; wac.registerBeanDefinition("handlerAdapter", new RootBeanDefinition(adapterType)); - Class resolverType = RequestMappingHandlerMethodExceptionResolver.class; + Class resolverType = ExceptionHandlerExceptionResolver.class; wac.registerBeanDefinition("requestMappingResolver", new RootBeanDefinition(resolverType)); resolverType = ResponseStatusExceptionResolver.class;