SpringBootでKafkaを使い始めたばかりで、JSONオブジェクトを送信して消費したいと思っています。
Kafkaトピックからのメッセージを消費しようとすると、次のエラーが発生します。
org.Apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition dev.orders-0 at offset 9903. If needed, please seek past the record to continue consumption.
Caused by: Java.lang.IllegalArgumentException: The class 'co.orders.feedme.feed.domain.OrderItem' is not in the trusted packages: [Java.util, Java.lang]. If you believe this class is safe to deserialize, please provide its name. If the serialization is only done by a trusted source, you can also enable trust all (*).
at org.springframework.kafka.support.converter.DefaultJackson2JavaTypeMapper.getClassIdType(DefaultJackson2JavaTypeMapper.Java:139) ~[spring-kafka-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.kafka.support.converter.DefaultJackson2JavaTypeMapper.toJavaType(DefaultJackson2JavaTypeMapper.Java:113) ~[spring-kafka-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.kafka.support.serializer.JsonDeserializer.deserialize(JsonDeserializer.Java:218) ~[spring-kafka-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.Apache.kafka.clients.consumer.internals.Fetcher.parseRecord(Fetcher.Java:923) ~[kafka-clients-1.0.1.jar:na]
at org.Apache.kafka.clients.consumer.internals.Fetcher.access$2600(Fetcher.Java:93) ~[kafka-clients-1.0.1.jar:na]
Application.propertiesで次のプロパティを定義して、信頼できるパッケージのリストにパッケージを追加しようとしました。
spring.kafka.consumer.properties.spring.json.trusted.packages = co.orders.feedme.feed.domain
これは何の違いももたらさないようです。 SpringのKafka JsonDeserializerの信頼できるパッケージのリストにパッケージを追加する正しい方法は何ですか?
信頼できるパッケージの問題が解決されたので、次の問題では、過負荷を利用できます。
DefaultKafkaConsumerFactory(Map<String, Object> configs,
Deserializer<K> keyDeserializer,
Deserializer<V> valueDeserializer)
と春のカフカのJsonDeserializer「ラッパー」
JsonDeserializer(Class<T> targetType, ObjectMapper objectMapper)
上記を組み合わせると、Javaの場合:
new DefaultKafkaConsumerFactory<>(properties,
new IntegerDeserializer(),
new JsonDeserializer<>(Foo.class,
new ObjectMapper()
.registerModules(new KotlinModule(), new JavaTimeModule()).setSerializationInclusion(JsonInclude.Include.NON_NULL)
.setDateFormat(new ISO8601DateFormat()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false))));
基本的に、独自のデシリアライザーを使用するようにファクトリに指示し、Jsonの場合は独自のObjectMapperを提供することができます。そこで、Kotlinモジュールを登録したり、日付形式やその他のものをカスタマイズしたりできます。
わかりました。ドキュメントをもう少し詳しく読んで、質問に対する答えを見つけました。私はKotlinを使用しているので、消費者の作成は次のようになります。
@Bean
fun consumerFactory(): ConsumerFactory<String, FeedItem> {
val configProps = HashMap<String, Any>()
configProps[ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers
configProps[ConsumerConfig.GROUP_ID_CONFIG] = "feedme"
configProps[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.Java
configProps[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.Java
configProps[JsonDeserializer.TRUSTED_PACKAGES] = "co.orders.feedme.feed.domain"
return DefaultKafkaConsumerFactory(configProps)
}
ここで、JsonDeserializerでのJackson ObjectMapperの作成をオーバーライドして、引数がゼロのコンストラクターを持たないKotlinデータクラスで動作できるようにする方法が必要です:)