Allow child contexts to configure server properties

Previously, HttpMessageConvertersAutoConfiguration registered
ServerProperties. When this happened in a parent context, any child
contexts would skip registering ServerProperties due to its presence
in the parent context. This prevents the child contexts from
configuring their own server properties.

This commit updates HttpMessageConvertersAutoConfiguration to
bind server.servlet.encoding directly instead of enabling
ServerProperties. With ServerProperties no longer enabled in a parent
context, child contexts are now able to configure their own server
properties.

Fixes gh-21789
This commit is contained in:
Andy Wilkinson
2020-06-10 18:56:57 +01:00
parent 6c926f7849
commit 90bd433083
2 changed files with 41 additions and 6 deletions

View File

@@ -30,12 +30,13 @@ import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration; import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.server.Encoding;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter;
@@ -71,14 +72,13 @@ public class HttpMessageConvertersAutoConfiguration {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(StringHttpMessageConverter.class) @ConditionalOnClass(StringHttpMessageConverter.class)
@EnableConfigurationProperties(ServerProperties.class)
protected static class StringHttpMessageConverterConfiguration { protected static class StringHttpMessageConverterConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public StringHttpMessageConverter stringHttpMessageConverter(ServerProperties serverProperties) { public StringHttpMessageConverter stringHttpMessageConverter(Environment environment) {
StringHttpMessageConverter converter = new StringHttpMessageConverter( Encoding encoding = Binder.get(environment).bindOrCreate("server.servlet.encoding", Encoding.class);
serverProperties.getServlet().getEncoding().getCharset()); StringHttpMessageConverter converter = new StringHttpMessageConverter(encoding.getCharset());
converter.setWriteAcceptCharset(false); converter.setWriteAcceptCharset(false);
return converter; return converter;
} }

View File

@@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.http; package org.springframework.boot.autoconfigure.http;
import java.nio.charset.StandardCharsets;
import javax.json.bind.Jsonb; import javax.json.bind.Jsonb;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -28,6 +30,7 @@ import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
import org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration; import org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration; import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -237,6 +240,38 @@ class HttpMessageConvertersAutoConfigurationTests {
.run((context) -> assertThat(context).doesNotHaveBean(HttpMessageConverters.class)); .run((context) -> assertThat(context).doesNotHaveBean(HttpMessageConverters.class));
} }
@Test
void whenEncodingCharsetIsNotConfiguredThenStringMessageConverterUsesUtf8() {
new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
.run((context) -> {
assertThat(context).hasSingleBean(StringHttpMessageConverter.class);
assertThat(context.getBean(StringHttpMessageConverter.class).getDefaultCharset())
.isEqualTo(StandardCharsets.UTF_8);
});
}
@Test
void whenEncodingCharsetIsConfiguredThenStringMessageConverterUsesSpecificCharset() {
new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
.withPropertyValues("server.servlet.encoding.charset=UTF-16").run((context) -> {
assertThat(context).hasSingleBean(StringHttpMessageConverter.class);
assertThat(context.getBean(StringHttpMessageConverter.class).getDefaultCharset())
.isEqualTo(StandardCharsets.UTF_16);
});
}
@Test // gh-21789
void whenAutoConfigurationIsActiveThenServerPropertiesConfigurationPropertiesAreNotEnabled() {
new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(HttpMessageConvertersAutoConfiguration.class))
.run((context) -> {
assertThat(context).hasSingleBean(HttpMessageConverters.class);
assertThat(context).doesNotHaveBean(ServerProperties.class);
});
}
private ApplicationContextRunner allOptionsRunner() { private ApplicationContextRunner allOptionsRunner() {
return this.contextRunner.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class, return this.contextRunner.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class,
JacksonAutoConfiguration.class, JsonbAutoConfiguration.class)); JacksonAutoConfiguration.class, JsonbAutoConfiguration.class));