From 116c6c95cd724ee1c28a7ee4938f9cd2dab0526e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 11 Jun 2020 20:52:43 +0200 Subject: [PATCH] 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 --- ...ntextFunctionCatalogAutoConfiguration.java | 57 ++++++++++++------- .../ContextFunctionCatalogInitializer.java | 8 +-- 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java index ed06b6d48..2f4f31043 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java @@ -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); } - } - } diff --git a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java index f9e272bbf..54118a601 100644 --- a/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java +++ b/spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogInitializer.java @@ -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)); }