diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfiguration.java index 3f149066a6..68b5b910d7 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfiguration.java @@ -21,14 +21,12 @@ import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; -import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; @@ -44,10 +42,10 @@ import com.google.gson.Gson; * @author Piotr Maj * @author Oliver Gierke * @author David Liu + * @author Andy Wilkinson */ @Configuration @ConditionalOnClass(HttpMessageConverter.class) -@Import({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class }) public class HttpMessageConvertersAutoConfiguration { @Autowired(required = false) @@ -61,8 +59,9 @@ public class HttpMessageConvertersAutoConfiguration { @Configuration @ConditionalOnClass(ObjectMapper.class) + @ConditionalOnBean(ObjectMapper.class) @EnableConfigurationProperties(HttpMapperProperties.class) - protected static class ObjectMappers { + protected static class MappingJackson2HttpMessageConverterConfiguration { @Autowired private HttpMapperProperties properties = new HttpMapperProperties(); @@ -81,7 +80,8 @@ public class HttpMessageConvertersAutoConfiguration { @Configuration @ConditionalOnClass(Gson.class) - protected static class GsonConfiguration { + @ConditionalOnBean(Gson.class) + protected static class GsonHttpMessageConverterConfiguration { @Bean @ConditionalOnMissingBean diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 8fe6706801..a997d9f8b7 100644 --- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -16,8 +16,10 @@ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfigura org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ +org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ +org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\ diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfigurationTests.java index 60eb767f28..1c4368101c 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfigurationTests.java @@ -16,6 +16,9 @@ package org.springframework.boot.autoconfigure.web; +import java.util.Arrays; +import java.util.List; + import org.junit.After; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -36,6 +39,7 @@ import static org.junit.Assert.assertTrue; * @author Dave Syer * @author Oliver Gierke * @author David Liu + * @author Andy Wilkinson */ public class HttpMessageConvertersAutoConfigurationTests { @@ -49,14 +53,75 @@ public class HttpMessageConvertersAutoConfigurationTests { } @Test - public void customJacksonConverter() throws Exception { + public void noObjectMapperMeansNoConverter() throws Exception { + this.context.register(HttpMessageConvertersAutoConfiguration.class); + this.context.refresh(); + assertTrue(this.context.getBeansOfType(ObjectMapper.class).isEmpty()); + assertTrue(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class) + .isEmpty()); + } + + @Test + public void defaultJacksonConverter() throws Exception { this.context.register(JacksonConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); - MappingJackson2HttpMessageConverter converter = this.context - .getBean(MappingJackson2HttpMessageConverter.class); - assertEquals(this.context.getBean(ObjectMapper.class), - converter.getObjectMapper()); + + assertConverterBeanExists(MappingJackson2HttpMessageConverter.class, + "mappingJackson2HttpMessageConverter"); + + assertConverterBeanRegisteredWithHttpMessageConverters(MappingJackson2HttpMessageConverter.class); + } + + @Test + public void customJacksonConverter() throws Exception { + this.context.register(JacksonConfig.class, JacksonConverterConfig.class, + HttpMessageConvertersAutoConfiguration.class); + this.context.refresh(); + + assertConverterBeanExists(MappingJackson2HttpMessageConverter.class, + "customJacksonMessageConverter"); + } + + @Test + public void noGson() throws Exception { + this.context.register(HttpMessageConvertersAutoConfiguration.class); + this.context.refresh(); + assertTrue(this.context.getBeansOfType(Gson.class).isEmpty()); + assertTrue(this.context.getBeansOfType(GsonHttpMessageConverter.class).isEmpty()); + } + + @Test + public void defaultGsonConverter() throws Exception { + this.context.register(GsonConfig.class, + HttpMessageConvertersAutoConfiguration.class); + this.context.refresh(); + assertConverterBeanExists(GsonHttpMessageConverter.class, + "gsonHttpMessageConverter"); + + assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class); + } + + @Test + public void customGsonConverter() throws Exception { + this.context.register(GsonConfig.class, GsonConverterConfig.class, + HttpMessageConvertersAutoConfiguration.class); + this.context.refresh(); + assertConverterBeanExists(GsonHttpMessageConverter.class, + "customGsonMessageConverter"); + + assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class); + } + + private void assertConverterBeanExists(Class type, String beanName) { + assertEquals(1, this.context.getBeansOfType(type).size()); + List beanNames = Arrays.asList(this.context.getBeanDefinitionNames()); + assertTrue(beanName + " not found in " + beanNames, beanNames.contains(beanName)); + } + + private void assertConverterBeanRegisteredWithHttpMessageConverters(Class type) { + + Object converter = this.context.getBean(type); HttpMessageConverters converters = this.context .getBean(HttpMessageConverters.class); assertTrue(converters.getConverters().contains(converter)); @@ -64,48 +129,42 @@ public class HttpMessageConvertersAutoConfigurationTests { @Configuration protected static class JacksonConfig { - - @Bean - public MappingJackson2HttpMessageConverter jacksonMessageConverter() { - MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); - converter.setObjectMapper(objectMapper()); - return converter; - } - @Bean public ObjectMapper objectMapper() { return new ObjectMapper(); } - } - @Test - public void customGsonConverter() throws Exception { - this.context.register(GsonConfig.class, - HttpMessageConvertersAutoConfiguration.class); - this.context.refresh(); - GsonHttpMessageConverter converter = this.context - .getBean(GsonHttpMessageConverter.class); - assertEquals(this.context.getBean(Gson.class), converter.getGson()); - HttpMessageConverters converters = this.context - .getBean(HttpMessageConverters.class); - assertTrue(converters.getConverters().contains(converter)); + @Configuration + protected static class JacksonConverterConfig { + + @Bean + public MappingJackson2HttpMessageConverter customJacksonMessageConverter( + ObjectMapper objectMapper) { + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + converter.setObjectMapper(objectMapper); + return converter; + } } @Configuration protected static class GsonConfig { - @Bean - public GsonHttpMessageConverter gsonMessageConverter() { - GsonHttpMessageConverter converter = new GsonHttpMessageConverter(); - converter.setGson(gson()); - return converter; - } - @Bean public Gson gson() { return new Gson(); } } + @Configuration + protected static class GsonConverterConfig { + + @Bean + public GsonHttpMessageConverter customGsonMessageConverter(Gson gson) { + GsonHttpMessageConverter converter = new GsonHttpMessageConverter(); + converter.setGson(gson); + return converter; + } + } + }