parent
97aeaa4a32
commit
8d63b7458c
|
@ -43,7 +43,7 @@ class GsonHttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConditionalOnBean(Gson.class)
|
@ConditionalOnBean(Gson.class)
|
||||||
@Conditional(PreferGsonOrMissingJacksonAndJsonbCondition.class)
|
@Conditional(PreferGsonOrJacksonAndJsonbUnavailableCondition.class)
|
||||||
protected static class GsonHttpMessageConverterConfiguration {
|
protected static class GsonHttpMessageConverterConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -56,27 +56,28 @@ class GsonHttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PreferGsonOrMissingJacksonAndJsonbCondition extends AnyNestedCondition {
|
private static class PreferGsonOrJacksonAndJsonbUnavailableCondition
|
||||||
|
extends AnyNestedCondition {
|
||||||
|
|
||||||
PreferGsonOrMissingJacksonAndJsonbCondition() {
|
PreferGsonOrJacksonAndJsonbUnavailableCondition() {
|
||||||
super(ConfigurationPhase.REGISTER_BEAN);
|
super(ConfigurationPhase.REGISTER_BEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
|
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson")
|
||||||
static class GsonPreferred {
|
static class GsonPreferred {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Conditional(JacksonAndJsonbMissing.class)
|
@Conditional(JacksonAndJsonbUnavailable.class)
|
||||||
static class JacksonJsonbMissing {
|
static class JacksonJsonbUnavailable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class JacksonAndJsonbMissing extends NoneNestedConditions {
|
private static class JacksonAndJsonbUnavailable extends NoneNestedConditions {
|
||||||
|
|
||||||
JacksonAndJsonbMissing() {
|
JacksonAndJsonbUnavailable() {
|
||||||
super(ConfigurationPhase.REGISTER_BEAN);
|
super(ConfigurationPhase.REGISTER_BEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ class GsonHttpMessageConvertersConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jsonb")
|
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jsonb")
|
||||||
static class JsonbMissing {
|
static class JsonbPreferred {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
|
|
||||||
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.http.converter.json.GsonHttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
|
||||||
|
@ -55,40 +55,24 @@ class JsonbHttpMessageConvertersConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PreferJsonbOrMissingJacksonAndGsonCondition extends AnyNestedCondition {
|
private static class PreferJsonbOrMissingJacksonAndGsonCondition
|
||||||
|
extends AnyNestedCondition {
|
||||||
|
|
||||||
PreferJsonbOrMissingJacksonAndGsonCondition() {
|
PreferJsonbOrMissingJacksonAndGsonCondition() {
|
||||||
super(ConfigurationPhase.REGISTER_BEAN);
|
super(ConfigurationPhase.REGISTER_BEAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jsonb", matchIfMissing = false)
|
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "jsonb")
|
||||||
static class JsonbPreferred {
|
static class JsonbPreferred {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Conditional(JacksonAndGsonMissing.class)
|
@ConditionalOnMissingBean({ MappingJackson2HttpMessageConverter.class, GsonHttpMessageConverter.class })
|
||||||
static class JacksonGsonMissing {
|
static class JacksonAndGsonMissing {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class JacksonAndGsonMissing extends NoneNestedConditions {
|
|
||||||
|
|
||||||
JacksonAndGsonMissing() {
|
|
||||||
super(ConfigurationPhase.REGISTER_BEAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ConditionalOnBean(MappingJackson2HttpMessageConverter.class)
|
|
||||||
static class JacksonMissing {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ConditionalOnProperty(name = HttpMessageConvertersAutoConfiguration.PREFERRED_MAPPER_PROPERTY, havingValue = "gson")
|
|
||||||
static class GsonMissing {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@
|
||||||
{
|
{
|
||||||
"name": "spring.http.converters.preferred-json-mapper",
|
"name": "spring.http.converters.preferred-json-mapper",
|
||||||
"type": "java.lang.String",
|
"type": "java.lang.String",
|
||||||
"description": "Preferred JSON mapper to use for HTTP message conversion. Set to \"gson\" to force the use of Gson when both it and Jackson are on the classpath."
|
"description": "Preferred JSON mapper to use for HTTP message conversion, auto-detected according to the environment by default."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spring.jersey.type",
|
"name": "spring.jersey.type",
|
||||||
|
|
|
@ -16,28 +16,29 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.http;
|
package org.springframework.boot.autoconfigure.http;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.json.bind.Jsonb;
|
import javax.json.bind.Jsonb;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
import org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration;
|
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.test.util.TestPropertyValues;
|
import org.springframework.boot.test.context.HidePackagesClassLoader;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
|
||||||
import org.springframework.hateoas.ResourceSupport;
|
import org.springframework.hateoas.ResourceSupport;
|
||||||
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
|
import org.springframework.hateoas.mvc.TypeConstrainedMappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
|
@ -59,240 +60,216 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*/
|
*/
|
||||||
public class HttpMessageConvertersAutoConfigurationTests {
|
public class HttpMessageConvertersAutoConfigurationTests {
|
||||||
|
|
||||||
private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(
|
||||||
|
HttpMessageConvertersAutoConfiguration.class));
|
||||||
|
|
||||||
@After
|
@Test
|
||||||
public void close() {
|
public void jacksonNotAvailable() {
|
||||||
if (this.context != null) {
|
this.contextRunner.run((context) -> {
|
||||||
this.context.close();
|
assertThat(context).doesNotHaveBean(ObjectMapper.class);
|
||||||
}
|
assertThat(context).doesNotHaveBean(MappingJackson2HttpMessageConverter.class);
|
||||||
|
assertThat(context).doesNotHaveBean(MappingJackson2XmlHttpMessageConverter.class);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noObjectMapperMeansNoConverter() throws Exception {
|
public void jacksonDefaultConverter() {
|
||||||
this.context.register(HttpMessageConvertersAutoConfiguration.class);
|
this.contextRunner.withUserConfiguration(JacksonObjectMapperConfig.class)
|
||||||
this.context.refresh();
|
.run(assertConverter(MappingJackson2HttpMessageConverter.class,
|
||||||
assertThat(this.context.getBeansOfType(ObjectMapper.class)).isEmpty();
|
"mappingJackson2HttpMessageConverter"));
|
||||||
assertThat(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class))
|
|
||||||
.isEmpty();
|
|
||||||
assertThat(
|
|
||||||
this.context.getBeansOfType(MappingJackson2XmlHttpMessageConverter.class))
|
|
||||||
.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultJacksonConverter() throws Exception {
|
public void jacksonConverterWithBuilder() {
|
||||||
this.context.register(JacksonObjectMapperConfig.class,
|
this.contextRunner.withUserConfiguration(JacksonObjectMapperBuilderConfig.class)
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
.run(assertConverter(MappingJackson2HttpMessageConverter.class,
|
||||||
this.context.refresh();
|
"mappingJackson2HttpMessageConverter"));
|
||||||
|
|
||||||
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
|
|
||||||
"mappingJackson2HttpMessageConverter");
|
|
||||||
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
MappingJackson2HttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultJacksonConvertersWithBuilder() throws Exception {
|
public void jacksonXmlConverterWithBuilder() {
|
||||||
this.context.register(JacksonObjectMapperBuilderConfig.class,
|
this.contextRunner.withUserConfiguration(JacksonObjectMapperBuilderConfig.class)
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
.run(assertConverter(MappingJackson2XmlHttpMessageConverter.class,
|
||||||
this.context.refresh();
|
"mappingJackson2XmlHttpMessageConverter"));
|
||||||
|
|
||||||
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
|
|
||||||
"mappingJackson2HttpMessageConverter");
|
|
||||||
assertConverterBeanExists(MappingJackson2XmlHttpMessageConverter.class,
|
|
||||||
"mappingJackson2XmlHttpMessageConverter");
|
|
||||||
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
MappingJackson2HttpMessageConverter.class);
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
MappingJackson2XmlHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customJacksonConverter() throws Exception {
|
public void jacksonCustomConverter() {
|
||||||
this.context.register(JacksonObjectMapperConfig.class,
|
this.contextRunner.withUserConfiguration(JacksonObjectMapperConfig.class,
|
||||||
JacksonConverterConfig.class,
|
JacksonConverterConfig.class
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
).run(assertConverter(MappingJackson2HttpMessageConverter.class,
|
||||||
this.context.refresh();
|
"customJacksonMessageConverter"));
|
||||||
|
|
||||||
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
|
|
||||||
"customJacksonMessageConverter");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noGson() throws Exception {
|
public void gsonNotAvailable() {
|
||||||
this.context.register(HttpMessageConvertersAutoConfiguration.class);
|
this.contextRunner.run((context) -> {
|
||||||
this.context.refresh();
|
assertThat(context).doesNotHaveBean(Gson.class);
|
||||||
assertThat(this.context.getBeansOfType(Gson.class).isEmpty()).isTrue();
|
assertThat(context).doesNotHaveBean(GsonHttpMessageConverter.class);
|
||||||
assertThat(this.context.getBeansOfType(GsonHttpMessageConverter.class).isEmpty())
|
});
|
||||||
.isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultGsonConverter() throws Exception {
|
public void gsonDefaultConverter() {
|
||||||
this.context.register(GsonAutoConfiguration.class,
|
this.contextRunner.withConfiguration(AutoConfigurations.of(
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
GsonAutoConfiguration.class)
|
||||||
this.context.refresh();
|
).run(assertConverter(GsonHttpMessageConverter.class,
|
||||||
assertConverterBeanExists(GsonHttpMessageConverter.class,
|
"gsonHttpMessageConverter"));
|
||||||
"gsonHttpMessageConverter");
|
|
||||||
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
GsonHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void jacksonIsPreferredByDefaultWhenBothGsonAndJacksonAreAvailable() {
|
public void gsonCustomConverter() {
|
||||||
this.context.register(GsonAutoConfiguration.class, JacksonAutoConfiguration.class,
|
this.contextRunner.withUserConfiguration(GsonConverterConfig.class)
|
||||||
JsonbAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class);
|
.withConfiguration(AutoConfigurations.of(GsonAutoConfiguration.class))
|
||||||
this.context.refresh();
|
.run(assertConverter(GsonHttpMessageConverter.class,
|
||||||
assertConverterBeanExists(MappingJackson2HttpMessageConverter.class,
|
"customGsonMessageConverter"));
|
||||||
"mappingJackson2HttpMessageConverter");
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
MappingJackson2HttpMessageConverter.class);
|
|
||||||
assertThat(this.context.getBeansOfType(GsonHttpMessageConverter.class)).isEmpty();
|
|
||||||
assertThat(this.context.getBeansOfType(JsonbHttpMessageConverter.class)).isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void gsonCanBePreferredWhenBothGsonAndJacksonAreAvailable() {
|
public void gsonCanBePreferred() {
|
||||||
this.context.register(GsonAutoConfiguration.class, JacksonAutoConfiguration.class,
|
allOptionsRunner().withPropertyValues(
|
||||||
JsonbAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class);
|
"spring.http.converters.preferred-json-mapper:gson").run((context) -> {
|
||||||
TestPropertyValues.of("spring.http.converters.preferred-json-mapper:gson")
|
assertConverterBeanExists(context, GsonHttpMessageConverter.class,
|
||||||
.applyTo(this.context);
|
"gsonHttpMessageConverter");
|
||||||
this.context.refresh();
|
assertConverterBeanRegisteredWithHttpMessageConverters(context,
|
||||||
assertConverterBeanExists(GsonHttpMessageConverter.class,
|
GsonHttpMessageConverter.class);
|
||||||
"gsonHttpMessageConverter");
|
assertThat(context).doesNotHaveBean(JsonbHttpMessageConverter.class);
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
assertThat(context).doesNotHaveBean(MappingJackson2HttpMessageConverter.class);
|
||||||
GsonHttpMessageConverter.class);
|
});
|
||||||
assertThat(this.context.getBeansOfType(JsonbHttpMessageConverter.class))
|
|
||||||
.isEmpty();
|
|
||||||
assertThat(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class))
|
|
||||||
.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customGsonConverter() throws Exception {
|
public void jsonbNotAvailable() {
|
||||||
this.context.register(GsonAutoConfiguration.class, GsonConverterConfig.class,
|
this.contextRunner.run((context) -> {
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
assertThat(context).doesNotHaveBean(Jsonb.class);
|
||||||
this.context.refresh();
|
assertThat(context).doesNotHaveBean(JsonbHttpMessageConverter.class);
|
||||||
assertConverterBeanExists(GsonHttpMessageConverter.class,
|
});
|
||||||
"customGsonMessageConverter");
|
|
||||||
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
GsonHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noJsonb() throws Exception {
|
public void jsonbDefaultConverter() {
|
||||||
this.context.register(HttpMessageConvertersAutoConfiguration.class);
|
this.contextRunner.withConfiguration(AutoConfigurations.of(
|
||||||
this.context.refresh();
|
JsonbAutoConfiguration.class)
|
||||||
assertThat(this.context.getBeansOfType(Jsonb.class).isEmpty()).isTrue();
|
).run(assertConverter(JsonbHttpMessageConverter.class,
|
||||||
assertThat(this.context.getBeansOfType(JsonbHttpMessageConverter.class).isEmpty())
|
"jsonbHttpMessageConverter"));
|
||||||
.isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultJsonbConverter() throws Exception {
|
public void jsonbCustomConverter() {
|
||||||
this.context.register(JsonbAutoConfiguration.class,
|
this.contextRunner.withUserConfiguration(JsonbConverterConfig.class)
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
.withConfiguration(AutoConfigurations.of(JsonbAutoConfiguration.class))
|
||||||
this.context.refresh();
|
.run(assertConverter(JsonbHttpMessageConverter.class,
|
||||||
assertConverterBeanExists(JsonbHttpMessageConverter.class,
|
"customJsonbMessageConverter"));
|
||||||
"jsonbHttpMessageConverter");
|
|
||||||
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
JsonbHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void jsonbCanBePreferredWhenBothGsonAndJacksonAreAvailable() {
|
public void jsonbCanBePreferred() {
|
||||||
this.context.register(GsonAutoConfiguration.class, JacksonAutoConfiguration.class,
|
allOptionsRunner().withPropertyValues(
|
||||||
JsonbAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class);
|
"spring.http.converters.preferred-json-mapper:jsonb").run((context) -> {
|
||||||
TestPropertyValues.of("spring.http.converters.preferred-json-mapper:jsonb")
|
assertConverterBeanExists(context, JsonbHttpMessageConverter.class,
|
||||||
.applyTo(this.context);
|
"jsonbHttpMessageConverter");
|
||||||
this.context.refresh();
|
assertConverterBeanRegisteredWithHttpMessageConverters(context,
|
||||||
assertConverterBeanExists(JsonbHttpMessageConverter.class,
|
JsonbHttpMessageConverter.class);
|
||||||
"jsonbHttpMessageConverter");
|
assertThat(context).doesNotHaveBean(GsonHttpMessageConverter.class);
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
assertThat(context).doesNotHaveBean(MappingJackson2HttpMessageConverter.class);
|
||||||
JsonbHttpMessageConverter.class);
|
});
|
||||||
assertThat(this.context.getBeansOfType(GsonHttpMessageConverter.class))
|
|
||||||
.isEmpty();
|
|
||||||
assertThat(this.context.getBeansOfType(MappingJackson2HttpMessageConverter.class))
|
|
||||||
.isEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customJsonbConverter() throws Exception {
|
public void stringDefaultConverter() {
|
||||||
this.context.register(JsonbAutoConfiguration.class, JsonbConverterConfig.class,
|
this.contextRunner.run(assertConverter(StringHttpMessageConverter.class,
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
"stringHttpMessageConverter"));
|
||||||
this.context.refresh();
|
|
||||||
assertConverterBeanExists(JsonbHttpMessageConverter.class,
|
|
||||||
"customJsonbMessageConverter");
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
JsonbHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultStringConverter() throws Exception {
|
public void sringCustomConverter() {
|
||||||
this.context.register(HttpMessageConvertersAutoConfiguration.class);
|
this.contextRunner.withUserConfiguration(StringConverterConfig.class)
|
||||||
this.context.refresh();
|
.run(assertConverter(StringHttpMessageConverter.class,
|
||||||
assertConverterBeanExists(StringHttpMessageConverter.class,
|
"customStringMessageConverter"));
|
||||||
"stringHttpMessageConverter");
|
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
|
||||||
StringHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void customStringConverter() throws Exception {
|
public void typeConstrainedConverterDoesNotPreventAutoConfigurationOfJacksonConverter() {
|
||||||
this.context.register(StringConverterConfig.class,
|
this.contextRunner.withUserConfiguration(JacksonObjectMapperBuilderConfig.class,
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
TypeConstrainedConverterConfiguration.class).run((context) -> {
|
||||||
this.context.refresh();
|
BeanDefinition beanDefinition = ((GenericApplicationContext) context.getSourceApplicationContext())
|
||||||
assertConverterBeanExists(StringHttpMessageConverter.class,
|
.getBeanDefinition("mappingJackson2HttpMessageConverter");
|
||||||
"customStringMessageConverter");
|
assertThat(beanDefinition.getFactoryBeanName()).isEqualTo(
|
||||||
|
MappingJackson2HttpMessageConverterConfiguration.class.getName());
|
||||||
assertConverterBeanRegisteredWithHttpMessageConverters(
|
});
|
||||||
StringHttpMessageConverter.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void typeConstrainedConverterDoesNotPreventAutoConfigurationOfJacksonConverter()
|
public void typeConstrainedConverterFromSpringDataDoesNotPreventAutoConfigurationOfJacksonConverter() {
|
||||||
throws Exception {
|
this.contextRunner.withUserConfiguration(JacksonObjectMapperBuilderConfig.class,
|
||||||
this.context.register(JacksonObjectMapperBuilderConfig.class,
|
RepositoryRestMvcConfiguration.class).run((context) -> {
|
||||||
TypeConstrainedConverterConfiguration.class,
|
BeanDefinition beanDefinition = ((GenericApplicationContext) context.getSourceApplicationContext())
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
.getBeanDefinition("mappingJackson2HttpMessageConverter");
|
||||||
this.context.refresh();
|
assertThat(beanDefinition.getFactoryBeanName()).isEqualTo(
|
||||||
|
MappingJackson2HttpMessageConverterConfiguration.class.getName());
|
||||||
BeanDefinition beanDefinition = this.context
|
});
|
||||||
.getBeanDefinition("mappingJackson2HttpMessageConverter");
|
|
||||||
assertThat(beanDefinition.getFactoryBeanName()).isEqualTo(
|
|
||||||
MappingJackson2HttpMessageConverterConfiguration.class.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void typeConstrainedConverterFromSpringDataDoesNotPreventAutoConfigurationOfJacksonConverter()
|
public void jacksonIsPreferredByDefault() {
|
||||||
throws Exception {
|
allOptionsRunner().run((context) -> {
|
||||||
this.context.register(JacksonObjectMapperBuilderConfig.class,
|
assertConverterBeanExists(context, MappingJackson2HttpMessageConverter.class,
|
||||||
RepositoryRestMvcConfiguration.class,
|
"mappingJackson2HttpMessageConverter");
|
||||||
HttpMessageConvertersAutoConfiguration.class);
|
assertConverterBeanRegisteredWithHttpMessageConverters(context,
|
||||||
this.context.refresh();
|
MappingJackson2HttpMessageConverter.class);
|
||||||
BeanDefinition beanDefinition = this.context
|
assertThat(context).doesNotHaveBean(GsonHttpMessageConverter.class);
|
||||||
.getBeanDefinition("mappingJackson2HttpMessageConverter");
|
assertThat(context).doesNotHaveBean(JsonbHttpMessageConverter.class);
|
||||||
assertThat(beanDefinition.getFactoryBeanName()).isEqualTo(
|
});
|
||||||
MappingJackson2HttpMessageConverterConfiguration.class.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertConverterBeanExists(Class<?> type, String beanName) {
|
@Test
|
||||||
assertThat(this.context.getBeansOfType(type)).hasSize(1);
|
public void gsonIsPreferredIfJacksonIsNotAvailable() {
|
||||||
List<String> beanNames = Arrays.asList(this.context.getBeanDefinitionNames());
|
allOptionsRunner()
|
||||||
assertThat(beanNames).contains(beanName);
|
.withClassLoader(new HidePackagesClassLoader(
|
||||||
|
ObjectMapper.class.getPackage().getName())).run((context) -> {
|
||||||
|
assertConverterBeanExists(context, GsonHttpMessageConverter.class,
|
||||||
|
"gsonHttpMessageConverter");
|
||||||
|
assertThat(context).doesNotHaveBean(JsonbHttpMessageConverter.class);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertConverterBeanRegisteredWithHttpMessageConverters(Class<?> type) {
|
@Test
|
||||||
Object converter = this.context.getBean(type);
|
public void jsonbIsPreferredIfJacksonAndGsonAreNotAvailable() {
|
||||||
HttpMessageConverters converters = this.context
|
allOptionsRunner()
|
||||||
.getBean(HttpMessageConverters.class);
|
.withClassLoader(new HidePackagesClassLoader(
|
||||||
assertThat(converters.getConverters().contains(converter)).isTrue();
|
ObjectMapper.class.getPackage().getName(),
|
||||||
|
Gson.class.getPackage().getName()))
|
||||||
|
.run(assertConverter(JsonbHttpMessageConverter.class,
|
||||||
|
"jsonbHttpMessageConverter"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApplicationContextRunner allOptionsRunner() {
|
||||||
|
return this.contextRunner.withConfiguration(AutoConfigurations.of(
|
||||||
|
GsonAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||||
|
JsonbAutoConfiguration.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ContextConsumer<AssertableApplicationContext> assertConverter(
|
||||||
|
Class<? extends HttpMessageConverter> converterType, String beanName) {
|
||||||
|
return context -> {
|
||||||
|
assertConverterBeanExists(context, converterType, beanName);
|
||||||
|
assertConverterBeanRegisteredWithHttpMessageConverters(context, converterType);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertConverterBeanExists(AssertableApplicationContext context,
|
||||||
|
Class<?> type, String beanName) {
|
||||||
|
assertThat(context).hasSingleBean(type);
|
||||||
|
assertThat(context).hasBean(beanName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertConverterBeanRegisteredWithHttpMessageConverters(
|
||||||
|
AssertableApplicationContext context, Class<? extends HttpMessageConverter> type) {
|
||||||
|
HttpMessageConverter converter = context.getBean(type);
|
||||||
|
HttpMessageConverters converters = context.getBean(HttpMessageConverters.class);
|
||||||
|
assertThat(converters.getConverters()).contains(converter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
|
|
@ -18,11 +18,10 @@ package org.springframework.boot.autoconfigure.jsonb;
|
||||||
|
|
||||||
import javax.json.bind.Jsonb;
|
import javax.json.bind.Jsonb;
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||||
|
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@ -33,26 +32,16 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
*/
|
*/
|
||||||
public class JsonbAutoConfigurationTests {
|
public class JsonbAutoConfigurationTests {
|
||||||
|
|
||||||
AnnotationConfigApplicationContext context;
|
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||||
|
.withConfiguration(AutoConfigurations.of(JsonbAutoConfiguration.class));
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
this.context = new AnnotationConfigApplicationContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {
|
|
||||||
if (this.context != null) {
|
|
||||||
this.context.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void jsonbRegistration() {
|
public void jsonbRegistration() {
|
||||||
this.context.register(JsonbAutoConfiguration.class);
|
this.contextRunner.run((context) -> {
|
||||||
this.context.refresh();
|
assertThat(context).hasSingleBean(Jsonb.class);
|
||||||
Jsonb jsonb = this.context.getBean(Jsonb.class);
|
Jsonb jsonb = context.getBean(Jsonb.class);
|
||||||
assertThat(jsonb.toJson(new DataObject())).isEqualTo("{\"data\":\"hello\"}");
|
assertThat(jsonb.toJson(new DataObject())).isEqualTo("{\"data\":\"hello\"}");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DataObject {
|
public class DataObject {
|
||||||
|
|
|
@ -297,7 +297,7 @@ content into your application; rather pick only the properties that you need.
|
||||||
spring.hateoas.use-hal-as-default-json-media-type=true # Specify if application/hal+json responses should be sent to requests that accept application/json.
|
spring.hateoas.use-hal-as-default-json-media-type=true # Specify if application/hal+json responses should be sent to requests that accept application/json.
|
||||||
|
|
||||||
# HTTP message conversion
|
# HTTP message conversion
|
||||||
spring.http.converters.preferred-json-mapper=jackson # Preferred JSON mapper to use for HTTP message conversion. Set to "gson" to force the use of Gson when both it and Jackson are on the classpath.
|
spring.http.converters.preferred-json-mapper= # Preferred JSON mapper to use for HTTP message conversion, auto-detected according to the environment by default.
|
||||||
|
|
||||||
# HTTP encoding ({sc-spring-boot-autoconfigure}/http/HttpEncodingProperties.{sc-ext}[HttpEncodingProperties])
|
# HTTP encoding ({sc-spring-boot-autoconfigure}/http/HttpEncodingProperties.{sc-ext}[HttpEncodingProperties])
|
||||||
spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly.
|
spring.http.encoding.charset=UTF-8 # Charset of HTTP requests and responses. Added to the "Content-Type" header if not set explicitly.
|
||||||
|
|
|
@ -5675,16 +5675,21 @@ TIP: It's also possible to use the `@AutoConfigure...` annotations with the stan
|
||||||
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-json-tests]]
|
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-json-tests]]
|
||||||
==== Auto-configured JSON tests
|
==== Auto-configured JSON tests
|
||||||
To test that Object JSON serialization and deserialization is working as expected you can
|
To test that Object JSON serialization and deserialization is working as expected you can
|
||||||
use the `@JsonTest` annotation. `@JsonTest` will auto-configure Jackson `ObjectMapper`,
|
use the `@JsonTest` annotation. `@JsonTest` will auto-configure the available supported
|
||||||
any `@JsonComponent` beans and any Jackson `Modules`. It also configures `Gson`
|
json mapper:
|
||||||
if you happen to be using that instead of, or as well as, Jackson. If you need to
|
|
||||||
configure elements of the auto-configuration you can use the `@AutoConfigureJsonTesters`
|
* Jackson `ObjectMapper`, any `@JsonComponent` beans and any Jackson `Modules`
|
||||||
annotation.
|
* `Gson`
|
||||||
|
* `Jsonb`
|
||||||
|
|
||||||
|
If you need to configure elements of the auto-configuration you can use the
|
||||||
|
`@AutoConfigureJsonTesters` annotation.
|
||||||
|
|
||||||
Spring Boot includes AssertJ based helpers that work with the JSONassert and JsonPath
|
Spring Boot includes AssertJ based helpers that work with the JSONassert and JsonPath
|
||||||
libraries to check that JSON is as expected. The `JacksonTester`, `GsonTester` and
|
libraries to check that JSON is as expected. The `JacksonTester`, `GsonTester`,
|
||||||
`BasicJsonTester` classes can be used for Jackson, Gson and Strings respectively. Any
|
`JsonbTester` and `BasicJsonTester` classes can be used for Jackson, Gson, Jsonb and
|
||||||
helper fields on the test class can be `@Autowired` when using `@JsonTest`.
|
Strings respectively. Any helper fields on the test class can be `@Autowired` when using
|
||||||
|
`@JsonTest`.
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
|
@ -6237,9 +6242,9 @@ A list of the auto-configuration that is enabled by `@DataLdapTest` can be
|
||||||
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-client]]
|
[[boot-features-testing-spring-boot-applications-testing-autoconfigured-rest-client]]
|
||||||
==== Auto-configured REST clients
|
==== Auto-configured REST clients
|
||||||
The `@RestClientTest` annotation can be used if you want to test REST clients. By default
|
The `@RestClientTest` annotation can be used if you want to test REST clients. By default
|
||||||
it will auto-configure Jackson and GSON support, configure a `RestTemplateBuilder` and
|
it will auto-configure Jackson, GSON and Jsonb support, configure a `RestTemplateBuilder`
|
||||||
add support for `MockRestServiceServer`. The specific beans that you want to test should
|
and add support for `MockRestServiceServer`. The specific beans that you want to test
|
||||||
be specified using `value` or `components` attribute of `@RestClientTest`:
|
should be specified using `value` or `components` attribute of `@RestClientTest`:
|
||||||
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
|
|
|
@ -126,7 +126,7 @@ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
|
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
|
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
|
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration.\
|
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
|
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
|
||||||
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
|
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
|
||||||
|
|
Loading…
Reference in New Issue