From 4c1f73ed83049cedbc91a218284c9eb8c2b286ad Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 6 Apr 2011 20:28:47 +0000 Subject: [PATCH] SPR-8217 update MVC namespace to use HandlerMethod infrastructure --- .../config/MvcAnnotationDrivenExecutor.java | 49 +++---- .../RequestMappingHandlerMethodAdapter.java | 12 +- ...MappingHandlerMethodExceptionResolver.java | 4 +- .../ModelAndViewMethodReturnValueHandler.java | 13 +- .../support/ViewMethodReturnValueHandler.java | 3 + ...tationDrivenBeanDefinitionParserTests.java | 16 +-- .../MvcAnnotationDrivenFeatureTests.java | 3 +- .../web/servlet/config/MvcNamespaceTests.java | 122 ++++++++++-------- ...HandlerMethodAdapterIntegrationTests.java} | 2 +- ...uestMappingHandlerMethodAdapterTests.java} | 4 +- .../ModelAttributeMethodProcessor.java | 8 +- .../support/ModelMethodProcessor.java | 9 +- .../support/WebArgumentResolverAdapter.java | 22 ++-- 13 files changed, 156 insertions(+), 111 deletions(-) rename org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/{RequestMappingHandlerAdapterIntegrationTests.java => RequestMappingHandlerMethodAdapterIntegrationTests.java} (99%) rename org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/{RequestMappingHandlerAdapterTests.java => RequestMappingHandlerMethodAdapterTests.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 c739f09913..51f63254b3 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 @@ -40,10 +40,10 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor; import org.springframework.web.servlet.handler.MappedInterceptor; -import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; -import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver; -import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping; 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.RequestMappingHandlerMethodMapping; import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver; /** @@ -78,11 +78,11 @@ final class MvcAnnotationDrivenExecutor extends AbstractSpecificationExecutor messageConverters = getMessageConverters(spec, registrar); - RootBeanDefinition annAdapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class); - annAdapterDef.setSource(source); - annAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - annAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef); - annAdapterDef.getPropertyValues().add("messageConverters", messageConverters); + RootBeanDefinition methodAdapterDef = new RootBeanDefinition(RequestMappingHandlerMethodAdapter.class); + methodAdapterDef.setSource(source); + methodAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + methodAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef); + methodAdapterDef.getPropertyValues().add("messageConverters", messageConverters); if (!spec.argumentResolvers().isEmpty()) { - annAdapterDef.getPropertyValues().add("customArgumentResolvers", spec.argumentResolvers()); + methodAdapterDef.getPropertyValues().add("customArgumentResolvers", spec.argumentResolvers()); } - String annAdapterName = registrar.registerWithGeneratedName(annAdapterDef); + String methodAdapterName = registrar.registerWithGeneratedName(methodAdapterDef); RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class); csInterceptorDef.setSource(source); @@ -117,12 +117,13 @@ final class MvcAnnotationDrivenExecutor extends AbstractSpecificationExecutor[] getMessageConverters() { + return messageConverters; + } + /** * Specify a WebBindingInitializer which will apply pre-configured * configuration to every DataBinder that this controller uses. @@ -313,7 +321,7 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda if (customArgumentResolvers != null) { for (WebArgumentResolver customResolver : customArgumentResolvers) { - argumentResolvers.registerArgumentResolver(new WebArgumentResolverAdapter(customResolver)); + argumentResolvers.registerArgumentResolver(new ServletWebArgumentResolverAdapter(customResolver)); } } @@ -343,7 +351,7 @@ public class RequestMappingHandlerMethodAdapter extends AbstractHandlerMethodAda if (customArgumentResolvers != null) { for (WebArgumentResolver customResolver : customArgumentResolvers) { - initBinderArgumentResolvers.registerArgumentResolver(new WebArgumentResolverAdapter(customResolver)); + initBinderArgumentResolvers.registerArgumentResolver(new ServletWebArgumentResolverAdapter(customResolver)); } } 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/RequestMappingHandlerMethodExceptionResolver.java index a914f83a17..d2461cbd70 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/RequestMappingHandlerMethodExceptionResolver.java @@ -43,7 +43,6 @@ import org.springframework.web.method.HandlerMethodSelector; import org.springframework.web.method.annotation.ExceptionMethodMapping; import org.springframework.web.method.annotation.support.ModelAttributeMethodProcessor; import org.springframework.web.method.annotation.support.ModelMethodProcessor; -import org.springframework.web.method.annotation.support.WebArgumentResolverAdapter; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; @@ -57,6 +56,7 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ModelAndVie import org.springframework.web.servlet.mvc.method.annotation.support.RequestResponseBodyMethodProcessor; import org.springframework.web.servlet.mvc.method.annotation.support.ServletRequestMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.support.ServletResponseMethodArgumentResolver; +import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebArgumentResolverAdapter; import org.springframework.web.servlet.mvc.method.annotation.support.ViewMethodReturnValueHandler; /** @@ -185,7 +185,7 @@ public class RequestMappingHandlerMethodExceptionResolver extends AbstractHandle if (customArgumentResolvers != null) { for (WebArgumentResolver customResolver : customArgumentResolvers) { - argumentResolvers.registerArgumentResolver(new WebArgumentResolverAdapter(customResolver)); + argumentResolvers.registerArgumentResolver(new ServletWebArgumentResolverAdapter(customResolver)); } } } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java index ae958845f9..88ec49dcb2 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ModelAndViewMethodReturnValueHandler.java @@ -42,10 +42,15 @@ public class ModelAndViewMethodReturnValueHandler implements HandlerMethodReturn MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { - ModelAndView mav = (ModelAndView) returnValue; - mavContainer.setView(mav.getView()); - mavContainer.setViewName(mav.getViewName()); - mavContainer.addModelAttributes(mav.getModel()); + if (returnValue != null) { + ModelAndView mav = (ModelAndView) returnValue; + mavContainer.setView(mav.getView()); + mavContainer.setViewName(mav.getViewName()); + mavContainer.addModelAttributes(mav.getModel()); + } + else { + // TODO + } } } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java index eb1cf66b8d..67347bb0f6 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/support/ViewMethodReturnValueHandler.java @@ -43,6 +43,9 @@ public class ViewMethodReturnValueHandler implements HandlerMethodReturnValueHan MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { + if (returnValue == null) { + return; + } if (returnValue instanceof String) { mavContainer.setViewName((String) returnValue); } 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 1c2be54e33..8830b91ae6 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 @@ -33,8 +33,8 @@ import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.bind.support.WebArgumentResolver; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.support.GenericWebApplicationContext; -import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; -import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodExceptionResolver; /** * Test fixture for the configuration in mvc-config-annotation-driven.xml. @@ -52,7 +52,7 @@ public class AnnotationDrivenBeanDefinitionParserTests { @Test public void testMessageCodesResolver() { loadBeanDefinitions("mvc-config-message-codes-resolver.xml"); - AnnotationMethodHandlerAdapter adapter = appContext.getBean(AnnotationMethodHandlerAdapter.class); + RequestMappingHandlerMethodAdapter adapter = appContext.getBean(RequestMappingHandlerMethodAdapter.class); assertNotNull(adapter); Object initializer = new DirectFieldAccessor(adapter).getPropertyValue("webBindingInitializer"); assertNotNull(initializer); @@ -64,21 +64,21 @@ public class AnnotationDrivenBeanDefinitionParserTests { @Test public void testMessageConverters() { loadBeanDefinitions("mvc-config-message-converters.xml"); - verifyMessageConverters(appContext.getBean(AnnotationMethodHandlerAdapter.class), true); - verifyMessageConverters(appContext.getBean(AnnotationMethodHandlerExceptionResolver.class), true); + verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodAdapter.class), true); + verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodExceptionResolver.class), true); } @Test public void testMessageConvertersWithoutDefaultRegistrations() { loadBeanDefinitions("mvc-config-message-converters-defaults-off.xml"); - verifyMessageConverters(appContext.getBean(AnnotationMethodHandlerAdapter.class), false); - verifyMessageConverters(appContext.getBean(AnnotationMethodHandlerExceptionResolver.class), false); + verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodAdapter.class), false); + verifyMessageConverters(appContext.getBean(RequestMappingHandlerMethodExceptionResolver.class), false); } @Test public void testArgumentResolvers() { loadBeanDefinitions("mvc-config-argument-resolvers.xml"); - AnnotationMethodHandlerAdapter adapter = appContext.getBean(AnnotationMethodHandlerAdapter.class); + RequestMappingHandlerMethodAdapter adapter = appContext.getBean(RequestMappingHandlerMethodAdapter.class); assertNotNull(adapter); Object resolvers = new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers"); assertNotNull(resolvers); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcAnnotationDrivenFeatureTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcAnnotationDrivenFeatureTests.java index a1f3d633cc..d0802f010b 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcAnnotationDrivenFeatureTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcAnnotationDrivenFeatureTests.java @@ -36,6 +36,7 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.bind.support.WebArgumentResolver; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter; /** * Integration tests for the {@link MvcAnnotationDriven} feature specification. @@ -50,7 +51,7 @@ public class MvcAnnotationDrivenFeatureTests { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(MvcFeature.class, MvcBeans.class); ctx.refresh(); - AnnotationMethodHandlerAdapter adapter = ctx.getBean(AnnotationMethodHandlerAdapter.class); + RequestMappingHandlerMethodAdapter adapter = ctx.getBean(RequestMappingHandlerMethodAdapter.class); assertNotNull(adapter); Object initializer = new DirectFieldAccessor(adapter).getPropertyValue("webBindingInitializer"); assertNotNull(initializer); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java index 5efa42cac8..f583d7717d 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java @@ -16,15 +16,23 @@ package org.springframework.web.servlet.config; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Method; import java.util.Date; import java.util.Locale; + import javax.servlet.RequestDispatcher; import javax.validation.Valid; import javax.validation.constraints.NotNull; import org.junit.Before; import org.junit.Test; - import org.springframework.beans.TypeMismatchException; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.i18n.LocaleContextHolder; @@ -47,6 +55,8 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.method.support.InvocableHandlerMethod; import org.springframework.web.servlet.HandlerExecutionChain; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; @@ -56,14 +66,12 @@ import org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapt import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter; import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter; -import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; -import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodAdapter; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMethodMapping; import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler; import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; import org.springframework.web.servlet.theme.ThemeChangeInterceptor; -import static org.junit.Assert.*; - /** * @author Keith Donald * @author Arjen Poutsma @@ -72,12 +80,20 @@ import static org.junit.Assert.*; public class MvcNamespaceTests { private GenericWebApplicationContext appContext; + + private TestController handler; + + private HandlerMethod handlerMethod; @Before - public void setUp() { + public void setUp() throws Exception { appContext = new GenericWebApplicationContext(); appContext.setServletContext(new TestMockServletContext()); LocaleContextHolder.setLocale(Locale.US); + + handler = new TestController(); + Method method = TestController.class.getMethod("testBind", Date.class, TestBean.class, BindingResult.class); + handlerMethod = new InvocableHandlerMethod(handler, method); } @Test @@ -87,13 +103,12 @@ public class MvcNamespaceTests { assertEquals(8, appContext.getBeanDefinitionCount()); appContext.refresh(); - DefaultAnnotationHandlerMapping mapping = appContext.getBean(DefaultAnnotationHandlerMapping.class); + RequestMappingHandlerMethodMapping mapping = appContext.getBean(RequestMappingHandlerMethodMapping.class); assertNotNull(mapping); assertEquals(0, mapping.getOrder()); - TestController handler = new TestController(); - mapping.setDefaultHandler(handler); + mapping.setDefaultHandler(handlerMethod); - AnnotationMethodHandlerAdapter adapter = appContext.getBean(AnnotationMethodHandlerAdapter.class); + RequestMappingHandlerMethodAdapter adapter = appContext.getBean(RequestMappingHandlerMethodAdapter.class); assertNotNull(adapter); HttpMessageConverter[] messageConverters = adapter.getMessageConverters(); @@ -105,18 +120,18 @@ public class MvcNamespaceTests { assertNotNull(appContext.getBean(Validator.class)); // default web binding initializer behavior test - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); request.addParameter("date", "2009-10-31"); MockHttpServletResponse response = new MockHttpServletResponse(); HandlerExecutionChain chain = mapping.getHandler(request); - assertEquals(2, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor); - ConversionServiceExposingInterceptor interceptor = (ConversionServiceExposingInterceptor) chain.getInterceptors()[1]; - interceptor.preHandle(request, response, handler); + assertEquals(1, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[0] instanceof ConversionServiceExposingInterceptor); + ConversionServiceExposingInterceptor interceptor = (ConversionServiceExposingInterceptor) chain.getInterceptors()[0]; + interceptor.preHandle(request, response, handlerMethod); assertSame(appContext.getBean(ConversionService.class), request.getAttribute(ConversionService.class.getName())); - adapter.handle(request, response, handler); + adapter.handle(request, response, handlerMethod); assertTrue(handler.recordedValidationError); } @@ -127,27 +142,26 @@ public class MvcNamespaceTests { assertEquals(8, appContext.getBeanDefinitionCount()); appContext.refresh(); - DefaultAnnotationHandlerMapping mapping = appContext.getBean(DefaultAnnotationHandlerMapping.class); + RequestMappingHandlerMethodMapping mapping = appContext.getBean(RequestMappingHandlerMethodMapping.class); assertNotNull(mapping); - TestController handler = new TestController(); - mapping.setDefaultHandler(handler); + mapping.setDefaultHandler(handlerMethod); // default web binding initializer behavior test - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); request.setRequestURI("/accounts/12345"); request.addParameter("date", "2009-10-31"); MockHttpServletResponse response = new MockHttpServletResponse(); HandlerExecutionChain chain = mapping.getHandler(request); - assertEquals(2, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor); - ConversionServiceExposingInterceptor interceptor = (ConversionServiceExposingInterceptor) chain.getInterceptors()[1]; + assertEquals(1, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[0] instanceof ConversionServiceExposingInterceptor); + ConversionServiceExposingInterceptor interceptor = (ConversionServiceExposingInterceptor) chain.getInterceptors()[0]; interceptor.preHandle(request, response, handler); assertSame(appContext.getBean("conversionService"), request.getAttribute(ConversionService.class.getName())); - AnnotationMethodHandlerAdapter adapter = appContext.getBean(AnnotationMethodHandlerAdapter.class); + RequestMappingHandlerMethodAdapter adapter = appContext.getBean(RequestMappingHandlerMethodAdapter.class); assertNotNull(adapter); - adapter.handle(request, response, handler); + adapter.handle(request, response, handlerMethod); } @Test @@ -157,16 +171,14 @@ public class MvcNamespaceTests { assertEquals(8, appContext.getBeanDefinitionCount()); appContext.refresh(); - AnnotationMethodHandlerAdapter adapter = appContext.getBean(AnnotationMethodHandlerAdapter.class); + RequestMappingHandlerMethodAdapter adapter = appContext.getBean(RequestMappingHandlerMethodAdapter.class); assertNotNull(adapter); - TestController handler = new TestController(); - // default web binding initializer behavior test MockHttpServletRequest request = new MockHttpServletRequest(); request.addParameter("date", "2009-10-31"); MockHttpServletResponse response = new MockHttpServletResponse(); - adapter.handle(request, response, handler); + adapter.handle(request, response, handlerMethod); assertTrue(appContext.getBean(TestValidator.class).validatorInvoked); assertFalse(handler.recordedValidationError); @@ -179,30 +191,30 @@ public class MvcNamespaceTests { assertEquals(11, appContext.getBeanDefinitionCount()); appContext.refresh(); - DefaultAnnotationHandlerMapping mapping = appContext.getBean(DefaultAnnotationHandlerMapping.class); + RequestMappingHandlerMethodMapping mapping = appContext.getBean(RequestMappingHandlerMethodMapping.class); assertNotNull(mapping); - mapping.setDefaultHandler(new TestController()); + mapping.setDefaultHandler(handlerMethod); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); request.setRequestURI("/accounts/12345"); request.addParameter("locale", "en"); request.addParameter("theme", "green"); HandlerExecutionChain chain = mapping.getHandler(request); - assertEquals(4, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor); - assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor); - assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor); + assertEquals(3, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[0] instanceof ConversionServiceExposingInterceptor); + assertTrue(chain.getInterceptors()[1] instanceof LocaleChangeInterceptor); + assertTrue(chain.getInterceptors()[2] instanceof ThemeChangeInterceptor); request.setRequestURI("/logged/accounts/12345"); chain = mapping.getHandler(request); - assertEquals(5, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[4] instanceof WebRequestHandlerInterceptorAdapter); + assertEquals(4, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[3] instanceof WebRequestHandlerInterceptorAdapter); request.setRequestURI("/foo/logged"); chain = mapping.getHandler(request); - assertEquals(5, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[4] instanceof WebRequestHandlerInterceptorAdapter); + assertEquals(4, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[3] instanceof WebRequestHandlerInterceptorAdapter); } @Test @@ -314,20 +326,20 @@ public class MvcNamespaceTests { assertEquals(10, appContext.getBeanDefinitionCount()); appContext.refresh(); - DefaultAnnotationHandlerMapping mapping = appContext.getBean(DefaultAnnotationHandlerMapping.class); + RequestMappingHandlerMethodMapping mapping = appContext.getBean(RequestMappingHandlerMethodMapping.class); assertNotNull(mapping); - mapping.setDefaultHandler(new TestController()); + mapping.setDefaultHandler(handlerMethod); - MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); HandlerExecutionChain chain = mapping.getHandler(request); - assertEquals(4, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor); - assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor); - assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor); - LocaleChangeInterceptor interceptor = (LocaleChangeInterceptor) chain.getInterceptors()[2]; + assertEquals(3, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[0] instanceof ConversionServiceExposingInterceptor); + assertTrue(chain.getInterceptors()[1] instanceof LocaleChangeInterceptor); + assertTrue(chain.getInterceptors()[2] instanceof ThemeChangeInterceptor); + LocaleChangeInterceptor interceptor = (LocaleChangeInterceptor) chain.getInterceptors()[1]; assertEquals("lang", interceptor.getParamName()); - ThemeChangeInterceptor interceptor2 = (ThemeChangeInterceptor) chain.getInterceptors()[3]; + ThemeChangeInterceptor interceptor2 = (ThemeChangeInterceptor) chain.getInterceptors()[2]; assertEquals("style", interceptor2.getParamName()); } @@ -338,18 +350,18 @@ public class MvcNamespaceTests { assertEquals(12, appContext.getBeanDefinitionCount()); appContext.refresh(); - DefaultAnnotationHandlerMapping mapping = appContext.getBean(DefaultAnnotationHandlerMapping.class); + RequestMappingHandlerMethodMapping mapping = appContext.getBean(RequestMappingHandlerMethodMapping.class); assertNotNull(mapping); - mapping.setDefaultHandler(new TestController()); + mapping.setDefaultHandler(handlerMethod); MockHttpServletRequest request = new MockHttpServletRequest(); request.setMethod("GET"); HandlerExecutionChain chain = mapping.getHandler(request); - assertEquals(4, chain.getInterceptors().length); - assertTrue(chain.getInterceptors()[1] instanceof ConversionServiceExposingInterceptor); - assertTrue(chain.getInterceptors()[2] instanceof LocaleChangeInterceptor); - assertTrue(chain.getInterceptors()[3] instanceof ThemeChangeInterceptor); + assertEquals(3, chain.getInterceptors().length); + assertTrue(chain.getInterceptors()[0] instanceof ConversionServiceExposingInterceptor); + assertTrue(chain.getInterceptors()[1] instanceof LocaleChangeInterceptor); + assertTrue(chain.getInterceptors()[2] instanceof ThemeChangeInterceptor); SimpleUrlHandlerMapping mapping2 = appContext.getBean(SimpleUrlHandlerMapping.class); assertNotNull(mapping2); diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterIntegrationTests.java similarity index 99% rename from org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java rename to org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterIntegrationTests.java index 0a43b12da1..6dd785d902 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterIntegrationTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterIntegrationTests.java @@ -96,7 +96,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl * * @author Rossen Stoyanchev */ -public class RequestMappingHandlerAdapterIntegrationTests { +public class RequestMappingHandlerMethodAdapterIntegrationTests { private RequestMappingHandlerMethodAdapter handlerAdapter; diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterTests.java similarity index 95% rename from org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java rename to org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterTests.java index 42fd1650c5..7f506f5f01 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapterTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMethodAdapterTests.java @@ -36,12 +36,12 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl * Test fixture for {@link RequestMappingHandlerMethodAdapter} unit tests. * * The tests in this class focus on {@link RequestMappingHandlerMethodAdapter} functionality exclusively. - * Also see {@link RequestMappingHandlerAdapterIntegrationTests} for higher-level tests invoking + * Also see {@link RequestMappingHandlerMethodAdapterIntegrationTests} for higher-level tests invoking * {@link Controller @Controller} methods. * * @author Rossen Stoyanchev */ -public class RequestMappingHandlerAdapterTests { +public class RequestMappingHandlerMethodAdapterTests { private RequestMappingHandlerMethodAdapter handlerAdapter; diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java index 65e3ab512c..016be5a2cf 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java +++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelAttributeMethodProcessor.java @@ -64,7 +64,7 @@ public class ModelAttributeMethodProcessor if (parameter.hasParameterAnnotation(ModelAttribute.class)) { return true; } - else if (this.resolveArgumentsWithoutAnnotations && !parameter.hasParameterAnnotations()) { + else if (this.resolveArgumentsWithoutAnnotations) { return !BeanUtils.isSimpleProperty(parameter.getParameterType()); } else { @@ -164,8 +164,10 @@ public class ModelAttributeMethodProcessor MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { - String name = ModelFactory.getNameForReturnValue(returnValue, returnType); - mavContainer.addModelAttribute(name, returnValue); + if (returnValue != null) { + String name = ModelFactory.getNameForReturnValue(returnValue, returnType); + mavContainer.addModelAttribute(name, returnValue); + } } } \ No newline at end of file diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java index 6bfe819a28..6292afb4b7 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java +++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/ModelMethodProcessor.java @@ -74,12 +74,19 @@ public class ModelMethodProcessor implements HandlerMethodArgumentResolver, Hand MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { + if (returnValue == null) { + return; + } if (returnValue instanceof Model) { mavContainer.addModelAttributes((Model) returnValue); } - else { + else if (returnValue instanceof Map){ mavContainer.addModelAttributes((Map) returnValue); } + else { + // should not happen + throw new UnsupportedOperationException(); + } } } diff --git a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java index c956e1ea44..40963fabf4 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java +++ b/org.springframework.web/src/main/java/org/springframework/web/method/annotation/support/WebArgumentResolverAdapter.java @@ -16,6 +16,8 @@ package org.springframework.web.method.annotation.support; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.core.MethodParameter; import org.springframework.ui.ModelMap; import org.springframework.util.Assert; @@ -31,9 +33,13 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; * Adapts a {@link WebArgumentResolver} into the {@link HandlerMethodArgumentResolver} contract. * * @author Arjen Poutsma + * @author Rossen Stoyanchev + * @since 3.1 */ public class WebArgumentResolverAdapter implements HandlerMethodArgumentResolver { + private final Log logger = LogFactory.getLog(this.getClass()); + private final WebArgumentResolver adaptee; public WebArgumentResolverAdapter(WebArgumentResolver adaptee) { @@ -43,14 +49,8 @@ public class WebArgumentResolverAdapter implements HandlerMethodArgumentResolver public boolean supportsParameter(MethodParameter parameter) { try { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - Object result ; - if (requestAttributes instanceof NativeWebRequest) { - result = adaptee.resolveArgument(parameter, (NativeWebRequest) requestAttributes); - } - else { - result = adaptee.resolveArgument(parameter, null); - } + NativeWebRequest webRequest = getWebRequest(); + Object result = adaptee.resolveArgument(parameter, webRequest); if (result == WebArgumentResolver.UNRESOLVED) { return false; } @@ -60,9 +60,15 @@ public class WebArgumentResolverAdapter implements HandlerMethodArgumentResolver } catch (Exception ex) { // ignore + logger.trace("Error in checking support for parameter [" + parameter + "], message: " + ex.getMessage()); return false; } } + + protected NativeWebRequest getWebRequest() { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + return (requestAttributes instanceof NativeWebRequest) ? (NativeWebRequest) requestAttributes : null; + } public boolean usesResponseArgument(MethodParameter parameter) { return false;