From 90bd433083551a984fe6382e1c316731b222a434 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 10 Jun 2020 18:56:57 +0100 Subject: [PATCH] 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 --- ...ttpMessageConvertersAutoConfiguration.java | 12 +++---- ...ssageConvertersAutoConfigurationTests.java | 35 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.java index 96c3db64b7..255f69751c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfiguration.java @@ -30,12 +30,13 @@ import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration; import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration; -import org.springframework.boot.autoconfigure.web.ServerProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.web.servlet.server.Encoding; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; @@ -71,14 +72,13 @@ public class HttpMessageConvertersAutoConfiguration { @Configuration(proxyBeanMethods = false) @ConditionalOnClass(StringHttpMessageConverter.class) - @EnableConfigurationProperties(ServerProperties.class) protected static class StringHttpMessageConverterConfiguration { @Bean @ConditionalOnMissingBean - public StringHttpMessageConverter stringHttpMessageConverter(ServerProperties serverProperties) { - StringHttpMessageConverter converter = new StringHttpMessageConverter( - serverProperties.getServlet().getEncoding().getCharset()); + public StringHttpMessageConverter stringHttpMessageConverter(Environment environment) { + Encoding encoding = Binder.get(environment).bindOrCreate("server.servlet.encoding", Encoding.class); + StringHttpMessageConverter converter = new StringHttpMessageConverter(encoding.getCharset()); converter.setWriteAcceptCharset(false); return converter; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java index 4b8286d986..f850fe9a60 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/http/HttpMessageConvertersAutoConfigurationTests.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.http; +import java.nio.charset.StandardCharsets; + import javax.json.bind.Jsonb; 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.jackson.JacksonAutoConfiguration; 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.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -237,6 +240,38 @@ class HttpMessageConvertersAutoConfigurationTests { .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() { return this.contextRunner.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class));