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.google.gson.Gson;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.JacksonMapper;
import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
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.core.convert.converter.GenericConverter;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.lang.Nullable;
import org.springframework.messaging.converter.AbstractMessageConverter;
import org.springframework.messaging.converter.ByteArrayMessageConverter;
import org.springframework.messaging.converter.CompositeMessageConverter;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
@@ -138,33 +139,49 @@ public class ContextFunctionCatalogAutoConfiguration {
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Gson.class)
@ConditionalOnProperty(name = PREFERRED_MAPPER_PROPERTY, havingValue = "gson", matchIfMissing = false)
protected static class GsonConfiguration {
public static class JsonMapperConfiguration {
@Bean
public GsonMapper jsonMapper(@Nullable Gson gson) {
if (gson == null) {
public JsonMapper jsonMapper(ApplicationContext context) {
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();
}
return new GsonMapper(gson);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnProperty(name = PREFERRED_MAPPER_PROPERTY, havingValue = "jackson", matchIfMissing = true)
protected static class JacksonConfiguration {
@Bean
public JacksonMapper jsonMapper(@Nullable ObjectMapper mapper) {
if (mapper == null) {
private JsonMapper jackson(ApplicationContext context) {
ObjectMapper mapper;
try {
mapper = context.getBean(ObjectMapper.class);
}
catch (Exception e) {
mapper = new ObjectMapper();
}
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) {
this.context.registerBean(Gson.class, () -> new Gson());
}
this.context.registerBean(JsonMapper.class,
() -> new ContextFunctionCatalogAutoConfiguration.GsonConfiguration()
.jsonMapper(this.context.getBean(Gson.class)));
this.context.registerBean(JsonMapper.class, () -> new ContextFunctionCatalogAutoConfiguration.JsonMapperConfiguration().jsonMapper(this.context));
}
else if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
if (this.context.getBeanFactory().getBeanNamesForType(ObjectMapper.class, false, false).length == 0) {
this.context.registerBean(ObjectMapper.class, () -> new ObjectMapper());
}
this.context.registerBean(JsonMapper.class,
() -> new ContextFunctionCatalogAutoConfiguration.JacksonConfiguration()
.jsonMapper(this.context.getBean(ObjectMapper.class)));
this.context.registerBean(JsonMapper.class, () -> new ContextFunctionCatalogAutoConfiguration.JsonMapperConfiguration().jsonMapper(this.context));
}