From 24834f6d2fd8f47100b904036249187c1e2444f6 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 24 Nov 2014 15:22:14 -0500 Subject: [PATCH] Add extendMessageConverters to WebMvcConfigurer Issue: SPR-12450 --- .../DelegatingWebMvcConfiguration.java | 5 +++++ .../WebMvcConfigurationSupport.java | 4 ++++ .../config/annotation/WebMvcConfigurer.java | 20 +++++++++++++++---- .../annotation/WebMvcConfigurerAdapter.java | 8 ++++++++ .../annotation/WebMvcConfigurerComposite.java | 7 +++++++ .../DelegatingWebMvcConfigurationTests.java | 13 ++++++++++-- ...MvcConfigurationSupportExtensionTests.java | 13 +++++++++--- 7 files changed, 61 insertions(+), 9 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java index 16dc2e186d1..899c440d61c 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java @@ -105,6 +105,11 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { this.configurers.configureMessageConverters(converters); } + @Override + protected void extendMessageConverters(List> converters) { + this.configurers.extendMessageConverters(converters); + } + @Override protected void addFormatters(FormatterRegistry registry) { this.configurers.addFormatters(registry); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index 1aa538baac9..31b31b2f1e7 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -629,6 +629,7 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv if (this.messageConverters.isEmpty()) { addDefaultHttpMessageConverters(this.messageConverters); } + extendMessageConverters(this.messageConverters); } return this.messageConverters; } @@ -646,6 +647,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv protected void configureMessageConverters(List> converters) { } + protected void extendMessageConverters(List> converters) { + } + /** * Adds a set of default HttpMessageConverter instances to the given list. * Subclasses can call this method from {@link #configureMessageConverters(List)}. diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java index 68e8ebb8b38..b1bf08e2203 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java @@ -53,14 +53,26 @@ public interface WebMvcConfigurer { void addFormatters(FormatterRegistry registry); /** - * Configure the {@link HttpMessageConverter}s to use in argument resolvers - * and return value handlers that support reading and/or writing to the - * body of the request and response. If no message converters are added to - * the list, default converters are added instead. + * Configure the {@link HttpMessageConverter}s to use for reading or writing + * to the body of the request or response. If no converters are added, a + * default list of converters is registered. + *

Note that adding converters to the list, turns off + * default converter registration. To simply add a converter without impacting + * default registration, consider using the method + * {@link #extendMessageConverters(java.util.List)} instead. * @param converters initially an empty list of converters */ void configureMessageConverters(List> converters); + /** + * A hook for extending or modifying the list of converters after it has been + * configured. This may be useful for example to allow default converters to + * be registered and then insert a custom converter through this method. + * @param converters the list of configured converters to extend. + * @since 4.1.3 + */ + void extendMessageConverters(List> converters); + /** * Provide a custom {@link Validator} instead of the one created by default. * The default implementation, assuming JSR-303 is on the classpath, is: diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java index e40f6c20106..7f4c7c34a8f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java @@ -51,6 +51,14 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { public void configureMessageConverters(List> converters) { } + /** + * {@inheritDoc} + *

This implementation is empty. + */ + @Override + public void extendMessageConverters(List> converters) { + } + /** * {@inheritDoc} *

This implementation returns {@code null} diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java index c524092d54b..af08decd7fe 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java @@ -78,6 +78,13 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { } } + @Override + public void extendMessageConverters(List> converters) { + for (WebMvcConfigurer delegate : this.delegates) { + delegate.extendMessageConverters(converters); + } + } + @Override public void addArgumentResolvers(List argumentResolvers) { for (WebMvcConfigurer delegate : this.delegates) { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java index d3ecd600038..12aa38ac7b2 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java @@ -29,6 +29,7 @@ import org.mockito.MockitoAnnotations; import org.springframework.core.convert.ConversionService; import org.springframework.format.support.FormattingConversionService; +import org.springframework.http.HttpMessage; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.util.PathMatcher; @@ -115,18 +116,26 @@ public class DelegatingWebMvcConfigurationTests { @Test public void configureMessageConverters() { + final HttpMessageConverter customConverter = mock(HttpMessageConverter.class); + final StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); List configurers = new ArrayList(); configurers.add(new WebMvcConfigurerAdapter() { @Override public void configureMessageConverters(List> converters) { - converters.add(new StringHttpMessageConverter()); + converters.add(stringConverter); + } + @Override + public void extendMessageConverters(List> converters) { + converters.add(0, customConverter); } }); delegatingConfig = new DelegatingWebMvcConfiguration(); delegatingConfig.setConfigurers(configurers); RequestMappingHandlerAdapter adapter = delegatingConfig.requestMappingHandlerAdapter(); - assertEquals("Only one custom converter should be registered", 1, adapter.getMessageConverters().size()); + assertEquals("Only one custom converter should be registered", 2, adapter.getMessageConverters().size()); + assertSame(customConverter, adapter.getMessageConverters().get(0)); + assertSame(stringConverter, adapter.getMessageConverters().get(1)); } @Test diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java index 0ea7f16d585..bc93d4ef7d5 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java @@ -33,6 +33,7 @@ import org.springframework.format.FormatterRegistry; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockServletContext; @@ -165,9 +166,10 @@ public class WebMvcConfigurationSupportExtensionTests { assertEquals("converted", actual); // Message converters - assertEquals(1, adapter.getMessageConverters().size()); - assertEquals(MappingJackson2HttpMessageConverter.class, adapter.getMessageConverters().get(0).getClass()); - ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter)adapter.getMessageConverters().get(0)).getObjectMapper(); + assertEquals(2, adapter.getMessageConverters().size()); + assertEquals(StringHttpMessageConverter.class, adapter.getMessageConverters().get(0).getClass()); + assertEquals(MappingJackson2HttpMessageConverter.class, adapter.getMessageConverters().get(1).getClass()); + ObjectMapper objectMapper = ((MappingJackson2HttpMessageConverter)adapter.getMessageConverters().get(1)).getObjectMapper(); assertFalse(objectMapper.getDeserializationConfig().isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)); assertFalse(objectMapper.getSerializationConfig().isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)); assertFalse(objectMapper.getDeserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); @@ -301,6 +303,11 @@ public class WebMvcConfigurationSupportExtensionTests { converters.add(new MappingJackson2HttpMessageConverter()); } + @Override + public void extendMessageConverters(List> converters) { + converters.add(0, new StringHttpMessageConverter()); + } + @Override public Validator getValidator() { return new Validator() {