Add MessageCodesResolver hook to WebMvcConfigurer

This change makes it possible to provide a custom MessageCodesResolver
through the MVC Java config whether using @EnableWebMvc and extending
WebMVcConfigurerAdapter or sub-classing directly from
WebMvcConfigurationSupport.

Issue: SPR-9223
This commit is contained in:
Rossen Stoyanchev
2012-05-15 17:02:06 -04:00
parent 1cec0f9c65
commit 2af294ab26
8 changed files with 208 additions and 128 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.
@@ -35,6 +35,7 @@ import org.junit.Test;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
@@ -72,6 +73,7 @@ public class DelegatingWebMvcConfigurationTests {
configurer.configureMessageConverters(capture(converters));
expect(configurer.getValidator()).andReturn(null);
expect(configurer.getMessageCodesResolver()).andReturn(null);
configurer.addFormatters(capture(conversionService));
configurer.addArgumentResolvers(capture(resolvers));
configurer.addReturnValueHandlers(capture(handlers));
@@ -91,7 +93,7 @@ public class DelegatingWebMvcConfigurationTests {
verify(configurer);
}
@Test
@Test
public void configureMessageConverters() {
List<WebMvcConfigurer> configurers = new ArrayList<WebMvcConfigurer>();
configurers.add(new WebMvcConfigurerAdapter() {
@@ -102,11 +104,11 @@ public class DelegatingWebMvcConfigurationTests {
});
mvcConfiguration = new DelegatingWebMvcConfiguration();
mvcConfiguration.setConfigurers(configurers);
RequestMappingHandlerAdapter adapter = mvcConfiguration.requestMappingHandlerAdapter();
assertEquals("Only one custom converter should be registered", 1, adapter.getMessageConverters().size());
}
@Test
public void getCustomValidator() {
expect(configurer.getValidator()).andReturn(new LocalValidatorFactoryBean());
@@ -118,6 +120,17 @@ public class DelegatingWebMvcConfigurationTests {
verify(configurer);
}
@Test
public void getCustomMessageCodesResolver() {
expect(configurer.getMessageCodesResolver()).andReturn(new DefaultMessageCodesResolver());
replay(configurer);
mvcConfiguration.setConfigurers(Arrays.asList(configurer));
mvcConfiguration.getMessageCodesResolver();
verify(configurer);
}
@Test
public void handlerExceptionResolver() throws Exception {
Capture<List<HttpMessageConverter<?>>> converters = new Capture<List<HttpMessageConverter<?>>>();
@@ -139,7 +152,7 @@ public class DelegatingWebMvcConfigurationTests {
verify(configurer);
}
@Test
@Test
public void configureExceptionResolvers() throws Exception {
List<WebMvcConfigurer> configurers = new ArrayList<WebMvcConfigurer>();
configurers.add(new WebMvcConfigurerAdapter() {
@@ -149,10 +162,10 @@ public class DelegatingWebMvcConfigurationTests {
}
});
mvcConfiguration.setConfigurers(configurers);
HandlerExceptionResolverComposite composite =
HandlerExceptionResolverComposite composite =
(HandlerExceptionResolverComposite) mvcConfiguration.handlerExceptionResolver();
assertEquals("Only one custom converter is expected", 1, composite.getExceptionResolvers().size());
}
}

View File

@@ -40,7 +40,9 @@ import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.Errors;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -190,6 +192,9 @@ public class WebMvcConfigurationSupportTests {
initializer.getValidator().validate(null, bindingResult);
assertEquals("invalid", bindingResult.getAllErrors().get(0).getCode());
String[] codes = initializer.getMessageCodesResolver().resolveMessageCodes("invalid", null);
assertEquals("custom.invalid", codes[0]);
@SuppressWarnings("unchecked")
List<HandlerMethodArgumentResolver> argResolvers= (List<HandlerMethodArgumentResolver>)
new DirectFieldAccessor(adapter).getPropertyValue("customArgumentResolvers");
@@ -248,8 +253,11 @@ public class WebMvcConfigurationSupportTests {
}
/**
* The purpose of this class is to test that an implementation of a {@link WebMvcConfigurer}
* can also apply customizations by extension from {@link WebMvcConfigurationSupport}.
* Since WebMvcConfigurationSupport does not implement WebMvcConfigurer, the purpose
* of this test class is also to ensure the two are in sync with each other. Effectively
* that ensures that application config classes that use the combo {@code @EnableWebMvc}
* plus WebMvcConfigurer can switch to extending WebMvcConfigurationSupport directly for
* more advanced configuration needs.
*/
private class WebConfig extends WebMvcConfigurationSupport implements WebMvcConfigurer {
@@ -299,6 +307,17 @@ public class WebMvcConfigurationSupportTests {
registry.addInterceptor(new LocaleChangeInterceptor());
}
@SuppressWarnings("serial")
@Override
public MessageCodesResolver getMessageCodesResolver() {
return new DefaultMessageCodesResolver() {
@Override
public String[] resolveMessageCodes(String errorCode, String objectName) {
return new String[] { "custom." + errorCode };
}
};
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/path");
@@ -313,6 +332,7 @@ public class WebMvcConfigurationSupportTests {
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable("default");
}
}
}