Skip to content

Commit de8a2a7

Browse files
committed
Turn (Jackson|Gson)AutoConfiguration into true auto-configuration
Previously JacksonAutoConfiguration and GsonAutoConfiguration were not actually auto-configuration classes. They were only processed due to being imported by HttpMessageConvertersAutoConfiguration. In addition to being misleadingly named, this meant that they could not be included or excluded individually and were also tightly coupled to HTTP message conversion. This commit updates spring.factories to make both JacksonAutoConfiguration and GsonAutoConfiguration actual auto-configuration classes. As a result, they can now be enabled or disabled individually and are no longer coupled to HTTP message conversion. Closes spring-projectsgh-1562
1 parent 02e33c1 commit de8a2a7

3 files changed

Lines changed: 95 additions & 34 deletions

File tree

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfiguration.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@
2121

2222
import org.springframework.beans.factory.annotation.Autowired;
2323
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2425
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2526
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
26-
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
27-
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
2827
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2928
import org.springframework.context.annotation.Bean;
3029
import org.springframework.context.annotation.Configuration;
31-
import org.springframework.context.annotation.Import;
3230
import org.springframework.http.converter.HttpMessageConverter;
3331
import org.springframework.http.converter.json.GsonHttpMessageConverter;
3432
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@@ -44,10 +42,10 @@
4442
* @author Piotr Maj
4543
* @author Oliver Gierke
4644
* @author David Liu
45+
* @author Andy Wilkinson
4746
*/
4847
@Configuration
4948
@ConditionalOnClass(HttpMessageConverter.class)
50-
@Import({ JacksonAutoConfiguration.class, GsonAutoConfiguration.class })
5149
public class HttpMessageConvertersAutoConfiguration {
5250

5351
@Autowired(required = false)
@@ -61,8 +59,9 @@ public HttpMessageConverters messageConverters() {
6159

6260
@Configuration
6361
@ConditionalOnClass(ObjectMapper.class)
62+
@ConditionalOnBean(ObjectMapper.class)
6463
@EnableConfigurationProperties(HttpMapperProperties.class)
65-
protected static class ObjectMappers {
64+
protected static class MappingJackson2HttpMessageConverterConfiguration {
6665

6766
@Autowired
6867
private HttpMapperProperties properties = new HttpMapperProperties();
@@ -81,7 +80,8 @@ public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
8180

8281
@Configuration
8382
@ConditionalOnClass(Gson.class)
84-
protected static class GsonConfiguration {
83+
@ConditionalOnBean(Gson.class)
84+
protected static class GsonHttpMessageConverterConfiguration {
8585

8686
@Bean
8787
@ConditionalOnMissingBean

spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfigura
1616
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
1717
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
1818
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
19+
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
1920
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
2021
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
22+
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
2123
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
2224
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
2325
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\

spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/HttpMessageConvertersAutoConfigurationTests.java

Lines changed: 87 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
package org.springframework.boot.autoconfigure.web;
1818

19+
import java.util.Arrays;
20+
import java.util.List;
21+
1922
import org.junit.After;
2023
import org.junit.Test;
2124
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -36,6 +39,7 @@
3639
* @author Dave Syer
3740
* @author Oliver Gierke
3841
* @author David Liu
42+
* @author Andy Wilkinson
3943
*/
4044
public class HttpMessageConvertersAutoConfigurationTests {
4145

@@ -49,63 +53,118 @@ public void close() {
4953
}
5054

5155
@Test
52-
public void customJacksonConverter() throws Exception {
56+
public void noObjectMapperMeansNoConverter() throws Exception {
57+
this.context.register(HttpMessageConvertersAutoConfiguration.class);
58+
this.context.refresh();
59+
assertTrue(this.context.getBeansOfType(ObjectMapper.class).isEmpty());
60+
assertTrue(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class)
61+
.isEmpty());
62+
}
63+
64+
@Test
65+
public void defaultJacksonConverter() throws Exception {
5366
this.context.register(JacksonConfig.class,
5467
HttpMessageConvertersAutoConfiguration.class);
5568
this.context.refresh();
56-
MappingJackson2HttpMessageConverter converter = this.context
57-
.getBean(MappingJackson2HttpMessageConverter.class);
58-
assertEquals(this.context.getBean(ObjectMapper.class),
59-
converter.getObjectMapper());
60-
HttpMessageConverters converters = this.context
61-
.getBean(HttpMessageConverters.class);
62-
assertTrue(converters.getConverters().contains(converter));
69+
70+
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
71+
"mappingJackson2HttpMessageConverter");
72+
73+
assertConverterBeanRegisteredWithHttpMessageConverters(MappingJackson2HttpMessageConverter.class);
6374
}
6475

65-
@Configuration
66-
protected static class JacksonConfig {
76+
@Test
77+
public void customJacksonConverter() throws Exception {
78+
this.context.register(JacksonConfig.class, JacksonConverterConfig.class,
79+
HttpMessageConvertersAutoConfiguration.class);
80+
this.context.refresh();
6781

68-
@Bean
69-
public MappingJackson2HttpMessageConverter jacksonMessageConverter() {
70-
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
71-
converter.setObjectMapper(objectMapper());
72-
return converter;
73-
}
82+
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
83+
"customJacksonMessageConverter");
84+
}
7485

75-
@Bean
76-
public ObjectMapper objectMapper() {
77-
return new ObjectMapper();
78-
}
86+
@Test
87+
public void noGson() throws Exception {
88+
this.context.register(HttpMessageConvertersAutoConfiguration.class);
89+
this.context.refresh();
90+
assertTrue(this.context.getBeansOfType(Gson.class).isEmpty());
91+
assertTrue(this.context.getBeansOfType(GsonHttpMessageConverter.class).isEmpty());
92+
}
93+
94+
@Test
95+
public void defaultGsonConverter() throws Exception {
96+
this.context.register(GsonConfig.class,
97+
HttpMessageConvertersAutoConfiguration.class);
98+
this.context.refresh();
99+
assertConverterBeanExists(GsonHttpMessageConverter.class,
100+
"gsonHttpMessageConverter");
79101

102+
assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class);
80103
}
81104

82105
@Test
83106
public void customGsonConverter() throws Exception {
84-
this.context.register(GsonConfig.class,
107+
this.context.register(GsonConfig.class, GsonConverterConfig.class,
85108
HttpMessageConvertersAutoConfiguration.class);
86109
this.context.refresh();
87-
GsonHttpMessageConverter converter = this.context
88-
.getBean(GsonHttpMessageConverter.class);
89-
assertEquals(this.context.getBean(Gson.class), converter.getGson());
110+
assertConverterBeanExists(GsonHttpMessageConverter.class,
111+
"customGsonMessageConverter");
112+
113+
assertConverterBeanRegisteredWithHttpMessageConverters(GsonHttpMessageConverter.class);
114+
}
115+
116+
private void assertConverterBeanExists(Class<?> type, String beanName) {
117+
assertEquals(1, this.context.getBeansOfType(type).size());
118+
List<String> beanNames = Arrays.asList(this.context.getBeanDefinitionNames());
119+
assertTrue(beanName + " not found in " + beanNames, beanNames.contains(beanName));
120+
}
121+
122+
private void assertConverterBeanRegisteredWithHttpMessageConverters(Class<?> type) {
123+
124+
Object converter = this.context.getBean(type);
90125
HttpMessageConverters converters = this.context
91126
.getBean(HttpMessageConverters.class);
92127
assertTrue(converters.getConverters().contains(converter));
93128
}
94129

95130
@Configuration
96-
protected static class GsonConfig {
131+
protected static class JacksonConfig {
132+
@Bean
133+
public ObjectMapper objectMapper() {
134+
return new ObjectMapper();
135+
}
136+
}
137+
138+
@Configuration
139+
protected static class JacksonConverterConfig {
97140

98141
@Bean
99-
public GsonHttpMessageConverter gsonMessageConverter() {
100-
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
101-
converter.setGson(gson());
142+
public MappingJackson2HttpMessageConverter customJacksonMessageConverter(
143+
ObjectMapper objectMapper) {
144+
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
145+
converter.setObjectMapper(objectMapper);
102146
return converter;
103147
}
148+
}
149+
150+
@Configuration
151+
protected static class GsonConfig {
104152

105153
@Bean
106154
public Gson gson() {
107155
return new Gson();
108156
}
109157
}
110158

159+
@Configuration
160+
protected static class GsonConverterConfig {
161+
162+
@Bean
163+
public GsonHttpMessageConverter customGsonMessageConverter(Gson gson) {
164+
GsonHttpMessageConverter converter = new GsonHttpMessageConverter();
165+
converter.setGson(gson);
166+
return converter;
167+
}
168+
}
169+
111170
}

0 commit comments

Comments
 (0)