Skip to content

Commit e3b968d

Browse files
committed
GH-1196 Recactor registratio of Kotlin module
Resolves #1196
1 parent ba2db77 commit e3b968d

File tree

3 files changed

+29
-18
lines changed

3 files changed

+29
-18
lines changed

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/ContextFunctionCatalogAutoConfiguration.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525
import java.util.stream.Collectors;
2626

2727
import com.fasterxml.jackson.databind.DeserializationFeature;
28+
import com.fasterxml.jackson.databind.Module;
2829
import com.fasterxml.jackson.databind.ObjectMapper;
2930
import com.fasterxml.jackson.databind.SerializationFeature;
3031
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
3132
import com.google.gson.Gson;
3233
import io.cloudevents.spring.messaging.CloudEventMessageConverter;
3334

35+
import org.springframework.beans.BeanUtils;
3436
import org.springframework.beans.factory.BeanFactory;
3537
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
3638
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@@ -59,6 +61,7 @@
5961
import org.springframework.context.annotation.Configuration;
6062
import org.springframework.context.annotation.FilterType;
6163
import org.springframework.context.expression.BeanFactoryResolver;
64+
import org.springframework.core.KotlinDetector;
6265
import org.springframework.core.ResolvableType;
6366
import org.springframework.core.convert.converter.GenericConverter;
6467
import org.springframework.core.convert.support.ConfigurableConversionService;
@@ -216,6 +219,7 @@ private JsonMapper gson(ApplicationContext context) {
216219
return new GsonMapper(gson);
217220
}
218221

222+
@SuppressWarnings("unchecked")
219223
private JsonMapper jackson(ApplicationContext context) {
220224
ObjectMapper mapper;
221225
try {
@@ -226,6 +230,19 @@ private JsonMapper jackson(ApplicationContext context) {
226230
mapper.registerModule(new JavaTimeModule());
227231
}
228232

233+
if (KotlinDetector.isKotlinPresent()) {
234+
try {
235+
if (!mapper.getRegisteredModuleIds().contains("com.fasterxml.jackson.module.kotlin.KotlinModule")) {
236+
Class<? extends Module> kotlinModuleClass = (Class<? extends Module>)
237+
ClassUtils.forName("com.fasterxml.jackson.module.kotlin.KotlinModule", ClassUtils.getDefaultClassLoader());
238+
Module kotlinModule = BeanUtils.instantiateClass(kotlinModuleClass);
239+
mapper.registerModule(kotlinModule);
240+
}
241+
}
242+
catch (ClassNotFoundException ex) {
243+
// jackson-module-kotlin not available
244+
}
245+
}
229246
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
230247
mapper.configure(DeserializationFeature.FAIL_ON_TRAILING_TOKENS, true);
231248
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

spring-cloud-function-context/src/main/java/org/springframework/cloud/function/context/config/KotlinLambdaToFunctionAutoConfiguration.java

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import java.util.function.Function;
2323
import java.util.function.Supplier;
2424

25-
import com.fasterxml.jackson.module.kotlin.KotlinModule;
2625
import kotlin.Unit;
2726
import kotlin.jvm.functions.Function0;
2827
import kotlin.jvm.functions.Function1;
@@ -37,14 +36,10 @@
3736
import org.springframework.beans.factory.BeanFactory;
3837
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3938
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
40-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
41-
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
4239
import org.springframework.cloud.function.context.FunctionRegistration;
4340
import org.springframework.cloud.function.context.catalog.FunctionTypeUtils;
44-
import org.springframework.context.annotation.Bean;
4541
import org.springframework.context.annotation.Configuration;
4642
import org.springframework.core.ResolvableType;
47-
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
4843
import org.springframework.util.ObjectUtils;
4944

5045
/**
@@ -62,19 +57,6 @@ public class KotlinLambdaToFunctionAutoConfiguration {
6257

6358
protected final Log logger = LogFactory.getLog(getClass());
6459

65-
@Bean
66-
@ConditionalOnMissingBean
67-
@ConditionalOnClass(name = {"org.springframework.http.converter.json.Jackson2ObjectMapperBuilder",
68-
"com.fasterxml.jackson.module.kotlin.KotlinModule"})
69-
Jackson2ObjectMapperBuilderCustomizer customizer() {
70-
return new Jackson2ObjectMapperBuilderCustomizer() {
71-
@Override
72-
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
73-
jacksonObjectMapperBuilder.modulesToInstall(KotlinModule.class);
74-
}
75-
};
76-
}
77-
7860

7961
@SuppressWarnings({ "unchecked", "rawtypes" })
8062
public static final class KotlinFunctionWrapper implements Function<Object, Object>, Supplier<Object>, Consumer<Object>,

spring-cloud-function-context/src/test/java/org/springframework/cloud/function/utils/JsonMapperTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.cloud.function.utils;
1818

19+
import java.lang.reflect.Field;
1920
import java.nio.charset.StandardCharsets;
2021
import java.time.ZonedDateTime;
2122
import java.util.Date;
@@ -38,6 +39,7 @@
3839
import org.springframework.context.ApplicationContext;
3940
import org.springframework.context.annotation.Configuration;
4041
import org.springframework.core.ResolvableType;
42+
import org.springframework.util.ReflectionUtils;
4143

4244
import static org.assertj.core.api.Assertions.assertThat;
4345

@@ -84,6 +86,16 @@ public void testJsonDateTimeConversion() {
8486
assertThat(convertedJson).contains("\"zonedDateTime\":\"2024-10-16T16:13:29.964361+02:00\"");
8587
}
8688

89+
@Test
90+
public void testKotlinModuleRegistration() throws Exception {
91+
ApplicationContext context = SpringApplication.run(EmptyConfiguration.class);
92+
JsonMapper jsonMapper = context.getBean(JsonMapper.class);
93+
Field mapperField = ReflectionUtils.findField(jsonMapper.getClass(), "mapper");
94+
mapperField.setAccessible(true);
95+
ObjectMapper mapper = (ObjectMapper) mapperField.get(jsonMapper);
96+
assertThat(mapper.getRegisteredModuleIds()).contains("com.fasterxml.jackson.module.kotlin.KotlinModule");
97+
}
98+
8799
@ParameterizedTest
88100
@MethodSource("params")
89101
public void vanillaArray(JsonMapper mapper) {

0 commit comments

Comments
 (0)