SPR-7327 add <mvc:argument-resolvers> namespace element

This commit is contained in:
Rossen Stoyanchev 2011-02-03 15:22:00 +00:00
parent 182b6a437c
commit 7aaad37120
4 changed files with 76 additions and 11 deletions

View File

@ -119,12 +119,16 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver); bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);
ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext); ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
ManagedList<?> argumentResolvers = getArgumentResolvers(element, source, parserContext);
RootBeanDefinition annAdapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class); RootBeanDefinition annAdapterDef = new RootBeanDefinition(AnnotationMethodHandlerAdapter.class);
annAdapterDef.setSource(source); annAdapterDef.setSource(source);
annAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); annAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
annAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef); annAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
annAdapterDef.getPropertyValues().add("messageConverters", messageConverters); annAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
if (argumentResolvers != null) {
annAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
}
String annAdapterName = parserContext.getReaderContext().registerWithGeneratedName(annAdapterDef); String annAdapterName = parserContext.getReaderContext().registerWithGeneratedName(annAdapterDef);
RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class); RootBeanDefinition csInterceptorDef = new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
@ -211,6 +215,21 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
} }
} }
private ManagedList<?> getArgumentResolvers(Element element, Object source, ParserContext parserContext) {
Element resolversElement = DomUtils.getChildElementByTagName(element, "argument-resolvers");
if (resolversElement != null) {
ManagedList<BeanDefinitionHolder> argumentResolvers = new ManagedList<BeanDefinitionHolder>();
argumentResolvers.setSource(source);
for (Element resolver : DomUtils.getChildElementsByTagName(resolversElement, "bean")) {
BeanDefinitionHolder beanDef = parserContext.getDelegate().parseBeanDefinitionElement(resolver);
beanDef = parserContext.getDelegate().decorateBeanDefinitionIfRequired(resolver, beanDef);
argumentResolvers.add(beanDef);
}
return argumentResolvers;
}
return null;
}
private ManagedList<?> getMessageConverters(Element element, Object source, ParserContext parserContext) { private ManagedList<?> getMessageConverters(Element element, Object source, ParserContext parserContext) {
Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters"); Element convertersElement = DomUtils.getChildElementByTagName(element, "message-converters");
if (convertersElement != null) { if (convertersElement != null) {

View File

@ -31,6 +31,27 @@
<xsd:element ref="beans:bean" minOccurs="1" maxOccurs="unbounded"> <xsd:element ref="beans:bean" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The HttpMessageConverter bean definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="argument-resolvers">
<xsd:annotation>
<xsd:documentation><![CDATA[
Configures one or more WebArgumentResolver types to use for resolving custom arguments to handler methods.
Typically implemented to detect special parameter types, resolving well-known argument values for them.
Using this configuration element is optional.
Using it does not override the built-in support for resolving handler method arguments.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="beans:bean" minOccurs="1" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
The HttpMessageConverter bean definition. The HttpMessageConverter bean definition.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>

View File

@ -23,12 +23,15 @@ import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.MethodParameter;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.validation.MessageCodesResolver; import org.springframework.validation.MessageCodesResolver;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; 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.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver;
@ -67,6 +70,17 @@ public class AnnotationDrivenBeanDefinitionParserTests {
verifyMessageConverters(appContext.getBean(AnnotationMethodHandlerExceptionResolver.class)); verifyMessageConverters(appContext.getBean(AnnotationMethodHandlerExceptionResolver.class));
} }
@Test
public void testArgumentResolvers() {
AnnotationMethodHandlerAdapter adapter = appContext.getBean(AnnotationMethodHandlerAdapter.class);
assertNotNull(adapter);
Object resolvers = new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers");
assertNotNull(resolvers);
assertTrue(resolvers instanceof WebArgumentResolver[]);
assertEquals(2, ((WebArgumentResolver[]) resolvers).length);
assertTrue(((WebArgumentResolver[]) resolvers)[0] instanceof TestWebArgumentResolver);
assertTrue(((WebArgumentResolver[]) resolvers)[1] instanceof TestWebArgumentResolver);
}
private void verifyMessageConverters(Object bean) { private void verifyMessageConverters(Object bean) {
assertNotNull(bean); assertNotNull(bean);
@ -78,17 +92,25 @@ public class AnnotationDrivenBeanDefinitionParserTests {
assertTrue(((HttpMessageConverter<?>[]) converters)[1] instanceof ResourceHttpMessageConverter); assertTrue(((HttpMessageConverter<?>[]) converters)[1] instanceof ResourceHttpMessageConverter);
} }
private static class TestMessageCodesResolver implements MessageCodesResolver { }
public String[] resolveMessageCodes(String errorCode, String objectName) { class TestWebArgumentResolver implements WebArgumentResolver {
throw new IllegalStateException("Not expected to be invoked");
}
@SuppressWarnings("rawtypes")
public String[] resolveMessageCodes(String errorCode, String objectName, String field, Class fieldType) {
throw new IllegalStateException("Not expected to be invoked");
}
public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws Exception {
return null;
}
}
class TestMessageCodesResolver implements MessageCodesResolver {
public String[] resolveMessageCodes(String errorCode, String objectName) {
return new String[] { "test.foo.bar" };
}
@SuppressWarnings("rawtypes")
public String[] resolveMessageCodes(String errorCode, String objectName, String field, Class fieldType) {
return new String[] { "test.foo.bar" };
} }
} }

View File

@ -6,13 +6,16 @@
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"> http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<mvc:annotation-driven message-codes-resolver="messageCodesResolver"> <mvc:annotation-driven message-codes-resolver="messageCodesResolver">
<mvc:argument-resolvers>
<bean class="org.springframework.web.servlet.config.TestWebArgumentResolver"/>
<bean class="org.springframework.web.servlet.config.TestWebArgumentResolver"/>
</mvc:argument-resolvers>
<mvc:message-converters> <mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/> <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
</mvc:message-converters> </mvc:message-converters>
</mvc:annotation-driven> </mvc:annotation-driven>
<bean id="messageCodesResolver" <bean id="messageCodesResolver" class="org.springframework.web.servlet.config.TestMessageCodesResolver"/>
class="org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParserTests$TestMessageCodesResolver"/>
</beans> </beans>