私は、キーと値コンバータの両方のアブロスキーマレジストリを使用し、コネクタによって作成された入力トピックを取るJavaでカフカストリームアプリを書いています。コネクタには、次のスキーマを生成します。
key-schema: "int"
value-schema:{
"type": "record",
"name": "User",
"fields": [
{"name": "firstname", "type": "string"},
{"name": "lastname", "type": "string"}
]}
実際には、いくつかのトピックは、キースキーマは、常に「INT」であり、値スキーマは、常にいくつかの種類(ユーザー、製品、など)の記録である、があります。私のコードは次の定義が含まれています
Map<String, String> serdeConfig = Collections.singletonMap("schema.registry.url", schemaRegistryUrl);
Serde<User> userSerde = new SpecificAvroSerde<>();
userSerde.configure(serdeConfig, false);
最初のIでのようなものでトピックを消費しようとしたConsumed.with(Serdes.Integer(), userSerde);
が、整数は4つのバイトが、アブロ用途可変長符号化を使用して符号化されることを期待するSerdes.Integer()ので、それは仕事をしませんでした。使い方は、Consumed.with(Serdes.Bytes(), userSerde);
働いていたが、私はこれに私のコードを変更するので、私は実際にint型を望んでいたし、バイトではありません
KafkaAvroDeserializer keyDeserializer = new KafkaAvroDeserializer()
KafkaAvroSerializer keySerializer = new KafkaAvroSerializer();
keyDeserializer.configure(serdeConfig, true);
keySerializer.configure(serdeConfig, true);
Serde<Integer> keySerde = (Serde<Integer>)(Serde)Serdes.serdeFrom(keySerializer, keyDeserializer);
これは、コンパイラが警告を生成し(それが好きではない作られた(Serde<Integer>)(Serde)
鋳造)が、それは使用に私を可能に
Consumed.with(keySerde, userSerde);
そしてキーとして整数を取得します。これはうまく動作しますし、期待通りに私のアプリが動作している(素晴らしいです!)。しかし、今、私は、キー/値のデフォルトserdeを定義したいと私は仕事にそれを得ることができません。
デフォルト値のserdeを設定することは簡単です:
streamsConfiguration.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, SpecificAvroSerde.class);
しかし、私はデフォルトのキーserdeを定義する方法を見つけ出すことはできません。
私は試した
streamsConfiguration.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, keySerde.getClass().getName());
ランタイムエラーが発生します。org.apache.kafka.common.serialization.Serdes $ WrapperSerdeの公開引数なしのコンストラクタが見つかりませんでしたstreamsConfiguration.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, SpecificAvroSerde.class);
ランタイムエラーが発生します。java.lang.Integerのはorg.apache.avro.specific.SpecificRecordにキャストすることはできません
私は何をしないのですか?ありがとうございました。
アップデート (バージョン5.5以降)
コンフルエントバージョンは、5.5
経由して、プリミティブアブロタイプのネイティブサポートが追加されますPrimitiveAvroSerde
(参照https://github.com/confluentinc/schema-registry/blob/5.5.x/avro-serde/src/main/java/io/confluent/kafka/streams /serdes/avro/PrimitiveAvroSerde.java)
オリジナルの答え (バージョン5.4およびそれ以前):
これは既知の問題です。SERDESがで動作するので、プリミティブアブロタイプは、コンフルエントのAvroSerdesとうまく動作しませんGenericAvroRecord
とSpecificAvroRecord
だけ。
したがって、に基づいて、あなた自身のSerdeを構築KafkaAvroSerializer
し、KafkaAvroDeserializer
正しいアプローチです。デフォルトSerdeとしてコンフィグにこれを渡すことができるようにするには、使用することはできませんSerdes.serdeFrom
型情報が原因genricsの型消去のために失われているため。
ただし、拡張することあなた自身のクラスを実装することができますSerde
インターフェースの代わりと設定にカスタムクラスを渡します。
public class MySerde extends Serde<Integer> {
// use KafkaAvroSerializer and KafkaAvroDeserializer and cast `Object` to `Integer`
}
config.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, MySerde.class);