diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotatedControllersBeanDefinitionParser.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotatedControllersBeanDefinitionParser.java index afc3368658e..af0f0fea810 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotatedControllersBeanDefinitionParser.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/AnnotatedControllersBeanDefinitionParser.java @@ -23,7 +23,11 @@ import org.springframework.beans.factory.parsing.CompositeComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.core.convert.ConversionService; import org.springframework.format.support.FormattingConversionServiceFactoryBean; +import org.springframework.util.ClassUtils; +import org.springframework.validation.Validator; +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; import org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping; @@ -32,8 +36,21 @@ import org.w3c.dom.Element; /** * {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses the {@code annotated-controllers} element to setup * @Controller configuration in a Spring MVC web application. - * + *

+ * Responsible for: + *

    + *
  1. Registering a DefaultAnnotationHandlerMapping bean for mapping HTTP Servlet Requests to @Controller methods using @RequestMapping annotations. + *
  2. Registering a AnnotationMethodHandlerAdapter bean for invoking annotated @Controller methods. + * Will configure the HandlerAdapter's webBindingInitializer property for centrally configuring @Controller DataBinder instances: + * + *
* @author Keith Donald + * @since 3.0 */ public class AnnotatedControllersBeanDefinitionParser implements BeanDefinitionParser { @@ -65,16 +82,36 @@ public class AnnotatedControllersBeanDefinitionParser implements BeanDefinitionP private BeanDefinition createWebBindingInitializer(Element element, Object source, ParserContext context) { BeanDefinitionBuilder builder = createBeanBuilder(ConfigurableWebBindingInitializer.class, source); + addConversionService(builder, element, source, context); + addValidator(builder, element, source, context); + return builder.getBeanDefinition(); + } + + private void addConversionService(BeanDefinitionBuilder builder, Element element, Object source, ParserContext context) { if (context.getRegistry().containsBeanDefinition("conversionService")) { builder.addPropertyReference("conversionService", "conversionService"); } else { - builder.addPropertyValue("conversionService", createFormattingConversionService(element, source, context)); + builder.addPropertyValue("conversionService", createConversionService(element, source, context)); } + } + + private void addValidator(BeanDefinitionBuilder builder, Element element, Object source, ParserContext context) { + if (context.getRegistry().containsBeanDefinition("validator")) { + builder.addPropertyReference("validator", "validator"); + } else { + if (ClassUtils.isPresent("javax.validation.Validator", AnnotatedControllersBeanDefinitionParser.class.getClassLoader())) { + builder.addPropertyValue("validator", createValidator(element, source, context)); + } + } + } + + private BeanDefinition createConversionService(Element element, Object source, ParserContext context) { + BeanDefinitionBuilder builder = createBeanBuilder(FormattingConversionServiceFactoryBean.class, source); return builder.getBeanDefinition(); } - - private BeanDefinition createFormattingConversionService(Element element, Object source, ParserContext context) { - BeanDefinitionBuilder builder = createBeanBuilder(FormattingConversionServiceFactoryBean.class, source); + + private BeanDefinition createValidator(Element element, Object source, ParserContext context) { + BeanDefinitionBuilder builder = createBeanBuilder(LocalValidatorFactoryBean.class, source); return builder.getBeanDefinition(); } 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 b05e3e03406..6538255ef37 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 @@ -11,8 +11,8 @@ import org.junit.Test; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.io.ClassPathResource; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.format.annotation.DateTimeFormat.Style; +import org.springframework.format.annotation.ISODateTimeFormat; +import org.springframework.format.annotation.ISODateTimeFormat.ISO; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; @@ -50,7 +50,7 @@ public class MvcNamespaceTests { // default web binding initializer behavior test MockHttpServletRequest request = new MockHttpServletRequest(); - request.addParameter("date", "Oct 31, 2009"); + request.addParameter("date", "2009-10-31"); MockHttpServletResponse response = new MockHttpServletResponse(); adapter.handle(request, response, handler); } @@ -59,8 +59,8 @@ public class MvcNamespaceTests { public static class TestController { @RequestMapping - public void testBind(@RequestParam @DateTimeFormat(dateStyle=ISO.MEDIUM) Date date) { - System.out.println(date); + public void testBind(@RequestParam @ISODateTimeFormat(ISO.DATE) Date date) { + } } }