INT-4318: Register Jackson modules if available
JIRA: https://jira.spring.io/browse/INT-4318 Do not `ObjectMApper.findAndRegisterModules()` unconditionally. If there is no the target module library in classpath, we end up with the `NoClassDefFoundError` * Copy-paste the well-known modules registration logic from the `org.springframework.http.converter.json.Jackson2ObjectMapperBuilder` since we can't add `spring-web` dependency to the `SI-core`
This commit is contained in:
committed by
Gary Russell
parent
32fdd2119f
commit
a3160f80f6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @param <J> - The expected type of Java Type representation.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractJacksonJsonObjectMapper<N, P, J> extends JsonObjectMapperAdapter<N, P>
|
||||
@@ -51,6 +52,10 @@ public abstract class AbstractJacksonJsonObjectMapper<N, P, J> extends JsonObjec
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
protected ClassLoader getClassLoader() {
|
||||
return this.classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T fromJson(Object json, Class<T> valueType) throws Exception {
|
||||
return this.fromJson(json, this.constructType(valueType));
|
||||
|
||||
@@ -25,18 +25,22 @@ import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.integration.mapping.support.JsonHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.Module;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Jackson 2 JSON-processor (@link https://github.com/FasterXML) {@linkplain JsonObjectMapper} implementation.
|
||||
* Jackson 2 JSON-processor (@link https://github.com/FasterXML)
|
||||
* {@linkplain JsonObjectMapper} implementation.
|
||||
* Delegates <code>toJson</code> and <code>fromJson</code>
|
||||
* to the {@linkplain com.fasterxml.jackson.databind.ObjectMapper}
|
||||
* <p>
|
||||
@@ -44,13 +48,17 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
* <ul>
|
||||
* <li>{@link MapperFeature#DEFAULT_VIEW_INCLUSION} is disabled</li>
|
||||
* <li>{@link DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES} is disabled</li>
|
||||
* <li>{@link ObjectMapper#findAndRegisterModules()} is performed</li>
|
||||
* <li>The well-known modules are registered through the classpath scan</li>
|
||||
* </ul>
|
||||
*
|
||||
* See {@code org.springframework.http.converter.json.Jackson2ObjectMapperBuilder}
|
||||
* in the spring-web for more information.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Vikas Prasad
|
||||
*
|
||||
* @since 3.0
|
||||
*
|
||||
*/
|
||||
public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<JsonNode, JsonParser, JavaType> {
|
||||
|
||||
@@ -60,7 +68,7 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
this.objectMapper = new ObjectMapper();
|
||||
this.objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
|
||||
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
this.objectMapper.findAndRegisterModules();
|
||||
registerWellKnownModulesIfAvailable();
|
||||
}
|
||||
|
||||
public Jackson2JsonObjectMapper(ObjectMapper objectMapper) {
|
||||
@@ -68,6 +76,10 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
public ObjectMapper getObjectMapper() {
|
||||
return this.objectMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toJson(Object value) throws Exception {
|
||||
return this.objectMapper.writeValueAsString(value);
|
||||
@@ -138,4 +150,58 @@ public class Jackson2JsonObjectMapper extends AbstractJacksonJsonObjectMapper<Js
|
||||
return this.objectMapper.constructType(type);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerWellKnownModulesIfAvailable() {
|
||||
try {
|
||||
Class<? extends Module> jdk7Module = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.jdk7.Jdk7Module", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(jdk7Module));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// jackson-datatype-jdk7 not available
|
||||
}
|
||||
|
||||
try {
|
||||
Class<? extends Module> jdk8Module = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.jdk8.Jdk8Module", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(jdk8Module));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// jackson-datatype-jdk8 not available
|
||||
}
|
||||
|
||||
try {
|
||||
Class<? extends Module> javaTimeModule = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(javaTimeModule));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// jackson-datatype-jsr310 not available
|
||||
}
|
||||
|
||||
// Joda-Time present?
|
||||
if (ClassUtils.isPresent("org.joda.time.LocalDate", getClassLoader())) {
|
||||
try {
|
||||
Class<? extends Module> jodaModule = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.datatype.joda.JodaModule", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(jodaModule));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// jackson-datatype-joda not available
|
||||
}
|
||||
}
|
||||
|
||||
// Kotlin present?
|
||||
if (ClassUtils.isPresent("kotlin.Unit", getClassLoader())) {
|
||||
try {
|
||||
Class<? extends Module> kotlinModule = (Class<? extends Module>)
|
||||
ClassUtils.forName("com.fasterxml.jackson.module.kotlin.KotlinModule", getClassLoader());
|
||||
this.objectMapper.registerModule(BeanUtils.instantiateClass(kotlinModule));
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
//jackson-module-kotlin not available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,9 +31,7 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.DatabindContext;
|
||||
import com.fasterxml.jackson.databind.DeserializationConfig;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.cfg.MapperConfig;
|
||||
import com.fasterxml.jackson.databind.jsontype.NamedType;
|
||||
@@ -56,7 +54,7 @@ public final class JacksonJsonUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an {@link com.fasterxml.jackson.databind.ObjectMapper} if available,
|
||||
* Return an {@link ObjectMapper} if available,
|
||||
* supplied with Message specific serializers and deserializers.
|
||||
* Also configured to store typo info in the {@code @class} property.
|
||||
* @param trustedPackages the trusted Java packages for deserialization.
|
||||
@@ -64,11 +62,9 @@ public final class JacksonJsonUtils {
|
||||
* @throws IllegalStateException if an implementation is not available.
|
||||
* @since 4.3.10
|
||||
*/
|
||||
public static com.fasterxml.jackson.databind.ObjectMapper messagingAwareMapper(String... trustedPackages) {
|
||||
public static ObjectMapper messagingAwareMapper(String... trustedPackages) {
|
||||
if (JacksonPresent.isJackson2Present()) {
|
||||
ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
||||
mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
ObjectMapper mapper = new Jackson2JsonObjectMapper().getObjectMapper();
|
||||
|
||||
mapper.setDefaultTyping(new WhitelistTypeResolverBuilder(trustedPackages));
|
||||
|
||||
@@ -84,13 +80,14 @@ public final class JacksonJsonUtils {
|
||||
MutableMessageJacksonDeserializer mutableMessageDeserializer = new MutableMessageJacksonDeserializer();
|
||||
mutableMessageDeserializer.setMapper(mapper);
|
||||
|
||||
mapper.registerModule(new SimpleModule()
|
||||
SimpleModule simpleModule = new SimpleModule()
|
||||
.addSerializer(new MessageHeadersJacksonSerializer())
|
||||
.addDeserializer(GenericMessage.class, genericMessageDeserializer)
|
||||
.addDeserializer(ErrorMessage.class, errorMessageDeserializer)
|
||||
.addDeserializer(AdviceMessage.class, adviceMessageDeserializer)
|
||||
.addDeserializer(MutableMessage.class, mutableMessageDeserializer)
|
||||
);
|
||||
.addDeserializer(MutableMessage.class, mutableMessageDeserializer);
|
||||
|
||||
mapper.registerModule(simpleModule);
|
||||
return mapper;
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user