从kafka流和Avro反序列化同一类的ClassCastException

时间:2019-07-04 14:54:30

标签: java apache-kafka avro apache-kafka-streams

我已经使用avro-maven-plugin从Avro模式生成了Avro Java类。我将avro类序列化为字节数组,然后将其写入kafka主题。

然后我有一个kafka流,它试图操纵avro数据来执行某些操作。在反序列化过程中,我从同一类中获得ClassCastExcetion。我读到这个问题是由于Avro在回退时使用了另一个ClassLoader(ClassLoader的新实例)而产生的。

有一种方法可以强制Avro使用调用者的ClassLoader或类似的东西?

KafkaStream属性

this.props = new Properties();
        this.props.put(StreamsConfig.APPLICATION_ID_CONFIG, "test");
        this.props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        this.props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
        this.props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.ByteArray().getClass());

我正在使用String键和序列化的avro的字节数组,那么我需要手动反序列化avro的有效负载。 我使用avro的解码器像这样反序列化:

AvroPayload stp = AvroPayload.fromByteBuffer(ByteBuffer.wrap(bytes));

甚至是这样:

AvroPayload stp = AvroPayload.getDecoder().decode(ByteBuffer.wrap(bytes));

在第一个版本的调试中,我可以看到,如果我仍留在avro的生成的类上下文中,则将字节数组正确反序列化为AvroPayload类。返回该新实例可能会引发ClassCastException

1 个答案:

答案 0 :(得分:2)

我发现的唯一解决方案是按照建议将avro类放入外部jar,然后将其导入。

这不是一个好的解决方案,因为它需要大量配置才能保持您的avro模式和您生成的类的耦合,但这是我发现的唯一一个。

我配置了一个maven项目,该项目将avro的类jar生成到目录中,而名称中没有工件版本,因此我始终可以导入最新版本而不必更改pom。

如果有人会发现其他解决方案,请发布