GH-537 Fix JsonMapper creation

This fix insures that 'spring.http.converters.preferred-json-mapper' property is only used as mechanism to break tie in the event both jackson and gson are available in classpath or AC

Resolves #537
This commit is contained in:
Oleg Zhurakousky
2020-06-11 20:52:43 +02:00
parent 59cb91103e
commit 116c6c95cd
2 changed files with 39 additions and 26 deletions

View File

@@ -27,7 +27,6 @@ import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson; import com.google.gson.Gson;
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.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -39,6 +38,7 @@ import org.springframework.cloud.function.context.catalog.FunctionInspector;
import org.springframework.cloud.function.json.GsonMapper; import org.springframework.cloud.function.json.GsonMapper;
import org.springframework.cloud.function.json.JacksonMapper; import org.springframework.cloud.function.json.JacksonMapper;
import org.springframework.cloud.function.json.JsonMapper; import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
@@ -47,13 +47,14 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.FilterType;
import org.springframework.core.convert.converter.GenericConverter; import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.lang.Nullable;
import org.springframework.messaging.converter.AbstractMessageConverter; import org.springframework.messaging.converter.AbstractMessageConverter;
import org.springframework.messaging.converter.ByteArrayMessageConverter; import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/** /**
@@ -138,33 +139,49 @@ public class ContextFunctionCatalogAutoConfiguration {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Gson.class) public static class JsonMapperConfiguration {
@ConditionalOnProperty(name = PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
protected static class GsonConfiguration {
@Bean @Bean
public GsonMapper jsonMapper(@Nullable Gson gson) { public JsonMapper jsonMapper(ApplicationContext context) {
if (gson == null) { String preferredMapper = context.getEnvironment().getProperty(PREFERRED_MAPPER_PROPERTY);
if (StringUtils.hasText(preferredMapper)) {
if ("gson".equals(preferredMapper) && ClassUtils.isPresent("com.google.gson.Gson", null)) {
return gson(context);
}
else if ("jackson".equals(preferredMapper) && ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
return jackson(context);
}
}
else {
if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
return jackson(context);
}
else if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
return gson(context);
}
}
throw new IllegalStateException("Failed to configure JsonMapper. Neither jackson nor gson are present on the claspath");
}
private JsonMapper gson(ApplicationContext context) {
Gson gson;
try {
gson = context.getBean(Gson.class);
}
catch (Exception e) {
gson = new Gson(); gson = new Gson();
} }
return new GsonMapper(gson); return new GsonMapper(gson);
} }
} private JsonMapper jackson(ApplicationContext context) {
ObjectMapper mapper;
@Configuration(proxyBeanMethods = false) try {
@ConditionalOnClass(ObjectMapper.class) mapper = context.getBean(ObjectMapper.class);
@ConditionalOnProperty(name = PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true) }
protected static class JacksonConfiguration { catch (Exception e) {
@Bean
public JacksonMapper jsonMapper(@Nullable ObjectMapper mapper) {
if (mapper == null) {
mapper = new ObjectMapper(); mapper = new ObjectMapper();
} }
return new JacksonMapper(mapper); return new JacksonMapper(mapper);
} }
} }
} }

View File

@@ -136,17 +136,13 @@ public class ContextFunctionCatalogInitializer implements ApplicationContextInit
if (this.context.getBeanFactory().getBeanNamesForType(Gson.class, false, false).length == 0) { if (this.context.getBeanFactory().getBeanNamesForType(Gson.class, false, false).length == 0) {
this.context.registerBean(Gson.class, () -> new Gson()); this.context.registerBean(Gson.class, () -> new Gson());
} }
this.context.registerBean(JsonMapper.class, this.context.registerBean(JsonMapper.class, () -> new ContextFunctionCatalogAutoConfiguration.JsonMapperConfiguration().jsonMapper(this.context));
() -> new ContextFunctionCatalogAutoConfiguration.GsonConfiguration()
.jsonMapper(this.context.getBean(Gson.class)));
} }
else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) { else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class, false, false).length == 0) { if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class, false, false).length == 0) {
this.context.registerBean(ObjectMapper.class, () -> new ObjectMapper()); this.context.registerBean(ObjectMapper.class, () -> new ObjectMapper());
} }
this.context.registerBean(JsonMapper.class, this.context.registerBean(JsonMapper.class, () -> new ContextFunctionCatalogAutoConfiguration.JsonMapperConfiguration().jsonMapper(this.context));
() -> new ContextFunctionCatalogAutoConfiguration.JacksonConfiguration()
.jsonMapper(this.context.getBean(ObjectMapper.class)));
} }