Spring-Integration mit Jackson ObjectMapper und Java 8 Time (JSR-310)
Ich habe Probleme, einen "benutzerdefinierten" ObjectMapper zu konfigurieren, der von den DSL-Transformern von Spring Integration verwendet wird. Ich erhalte einjava.time.Instant
json Darstellungen, die ich auf Objekteigenschaften analysieren möchte. das heißt:
{"type": "TEST", "source": "TEST", "timestamp": {"epochSecond": 1454503381, "nano": 335000000}}
Die Nachricht ist eine Kafka-Nachricht, die eine Frage aufwirft: Soll ich einen benutzerdefinierten Serializer schreiben, der Kafka-Codierer / -Decodierer implementiert, um die Kafka-Nachricht in das richtige Objekt umwandeln zu können, oder muss die Spring-Integration dies automatisch tun?
fw / Abhängigkeiten und Version:
Spring Boot - 1.3.2.RELEASE
Spring Integration Java Dsl - 1.1.1.RELEASE
FasterXml Jackson - 2.6.5
Ich habe diese Java-Konfiguration dem Projekt gemäß der Jackson-Dokumentation hinzugefügt:https: //github.com/FasterXML/jackson-datatype-jsr31
@Configuration
public class IntegrationConfiguration {
@Bean
public JsonObjectMapper<JsonNode, JsonParser> jsonObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return new Jackson2JsonObjectMapper(mapper);
}
}
und das folgende Jackson JSR-310-Artefakt:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.6.5</version>
</dependency>
Basierend auf diesem Beitrag im Spring-Blog muss ich nicht einmal das neue Java8-Zeitmodul registrieren.https: //spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring#jackson-module
Dies ist die Ausnahme, die ich habe:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class java.time.Instant]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: {"type":"TEST","source":"TEST","timestamp":{"epochSecond":1454503381,"nano":335000000}}; line: 1, column: 71] (through reference chain: my.app.MyDto["timestamp"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1106)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:296)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2764)
at org.springframework.integration.support.json.Jackson2JsonObjectMapper.fromJson(Jackson2JsonObjectMapper.java:75)
at org.springframework.integration.support.json.Jackson2JsonObjectMapper.fromJson(Jackson2JsonObjectMapper.java:44)
at org.springframework.integration.support.json.AbstractJacksonJsonObjectMapper.fromJson(AbstractJacksonJsonObjectMapper.java:56)
at org.springframework.integration.json.JsonToObjectTransformer.doTransform(JsonToObjectTransformer.java:78)
at org.springframework.integration.transformer.AbstractTransformer.transform(AbstractTransformer.java:33)
... 74 more
AUFLÖSUNG
Das Problem war, dass ich erwartet hatte, dass Spring den Archetyp jackson-datatype-jsr310 erkennt und das JavaTimeModule registriert, aber es ist nicht das, was völlig in Ordnung ist. Wir können das auf zwei Arten beheben:
1. Die akzeptierte Antwort, wenn wir Spring Boot mit Spring Integration verwenden, wie es ist.
2. Wenn Sie die Spring Integration Dsl verwenden, behalten Sie die IntegrationConfiguration-Klasse mit der jsonObjectMapper () -Bean bei und verwenden Sie sie folgendermaßen:
@Autowired
private JsonObjectMapper jsonObjectMapper;
return IntegrationFlows
.from(inboundChannel())
.transform(Transformers.fromJson(myDto.class, jsonObjectMapper))
...