From d718a803165f96d7f38335fabf6194180cc6999b Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 4 Feb 2015 17:34:14 +0000 Subject: [PATCH] Make it easier to use Gson and the Actuator at the same time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the recommendation when a user wanted to use Gson was to exclude Jackson from the classpath and add Gson. This worked fine until the user also want to use the Actuator which requires Jackson. To get over this hurdle the user could leave Jackson on the classpath and perform their own HttpMessageConverter configuration and register a GsonHttpMessageConverter instead of or before any Jackson-based converter. A little complicated, but it worked. This commit makes things easier by updating the auto-configuration for HTTP message converters to prefer Gson when both Gson and Jackson are on the classpath, i.e. in the presence of both, a GsonHttpMessageConverter will be auto-configured and a MappingJackson2HttpMessageConverter won’t be. This allows an application to easily use Gson while allowing the Actuator to continue to use Jackson. Closes gh-2247 --- ...ttpMessageConvertersAutoConfiguration.java | 6 ++-- ...ssageConvertersAutoConfigurationTests.java | 36 +++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) 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 8aa36063cc..28ac65b490 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 @@ -25,7 +25,7 @@ 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.condition.ConditionalOnMissingClass; +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; @@ -55,7 +55,7 @@ import com.google.gson.Gson; */ @Configuration @ConditionalOnClass(HttpMessageConverter.class) -@AutoConfigureAfter(JacksonAutoConfiguration.class) +@AutoConfigureAfter({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class }) public class HttpMessageConvertersAutoConfiguration { @Autowired(required = false) @@ -70,6 +70,7 @@ public class HttpMessageConvertersAutoConfiguration { @Configuration @ConditionalOnClass(ObjectMapper.class) @ConditionalOnBean(ObjectMapper.class) + @ConditionalOnMissingBean(GsonHttpMessageConverter.class) @EnableConfigurationProperties(HttpMapperProperties.class) @SuppressWarnings("deprecation") protected static class MappingJackson2HttpMessageConverterConfiguration { @@ -119,7 +120,6 @@ public class HttpMessageConvertersAutoConfiguration { @Configuration @ConditionalOnClass(Gson.class) - @ConditionalOnMissingClass(name = "com.fasterxml.jackson.core.JsonGenerator") @ConditionalOnBean(Gson.class) protected static class GsonHttpMessageConverterConfiguration { 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 12efcdb479..4232d37f46 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 @@ -22,6 +22,8 @@ import java.util.List; import org.junit.After; import org.junit.Test; import org.springframework.beans.DirectFieldAccessor; +import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -118,17 +120,32 @@ public class HttpMessageConvertersAutoConfigurationTests { @Test public void defaultGsonConverter() throws Exception { - this.context.register(GsonConfig.class, + this.context.register(GsonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); - // Shouldn't be registered because we have Jackson - assertEquals(0, this.context.getBeansOfType(GsonHttpMessageConverter.class) - .size()); + assertConverterBeanExists(GsonHttpMessageConverter.class, + "gsonHttpMessageConverter"); + + assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class); + } + + @Test + public void gsonIsPreferredWhenBothGsonAndJacksonAreAvailable() { + this.context.register(GsonAutoConfiguration.class, + JacksonAutoConfiguration.class, + HttpMessageConvertersAutoConfiguration.class); + this.context.refresh(); + assertConverterBeanExists(GsonHttpMessageConverter.class, + "gsonHttpMessageConverter"); + assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class); + assertEquals(0, + this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class) + .size()); } @Test public void customGsonConverter() throws Exception { - this.context.register(GsonConfig.class, GsonConverterConfig.class, + this.context.register(GsonAutoConfiguration.class, GsonConverterConfig.class, HttpMessageConvertersAutoConfiguration.class); this.context.refresh(); assertConverterBeanExists(GsonHttpMessageConverter.class, @@ -227,15 +244,6 @@ public class HttpMessageConvertersAutoConfigurationTests { } } - @Configuration - protected static class GsonConfig { - - @Bean - public Gson gson() { - return new Gson(); - } - } - @Configuration protected static class GsonConverterConfig {