我正在尝试使用Avro Serialize和Apache kafka来序列化/反序列化消息。我创建了一个生成器,用于序列化特定类型的消息并将其发送到队列。当消息成功发送到队列时,我们的消费者选择消息并尝试处理,但在尝试时我们面临异常,对于特定对象的大小写字节。例外情况如下:
<li>
根据例外情况,我们使用一些不方便的方式来读取数据,下面是我们的代码:
卡夫卡制片人代码:
[error] (run-main-0) java.lang.ClassCastException: org.apache.avro.generic.GenericData$Record cannot be cast to com.harmeetsingh13.java.avroserializer.Customer
java.lang.ClassCastException: org.apache.avro.generic.GenericData$Record cannot be cast to com.harmeetsingh13.java.avroserializer.Customer
at com.harmeetsingh13.java.consumers.avrodesrializer.AvroSpecificDeserializer.lambda$infiniteConsumer$0(AvroSpecificDeserializer.java:51)
at java.lang.Iterable.forEach(Iterable.java:75)
at com.harmeetsingh13.java.consumers.avrodesrializer.AvroSpecificDeserializer.infiniteConsumer(AvroSpecificDeserializer.java:46)
at com.harmeetsingh13.java.consumers.avrodesrializer.AvroSpecificDeserializer.main(AvroSpecificDeserializer.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
卡夫卡消费者代码:
static {
kafkaProps.put("bootstrap.servers", "localhost:9092");
kafkaProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, KafkaAvroSerializer.class);
kafkaProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, KafkaAvroSerializer.class);
kafkaProps.put("schema.registry.url", "http://localhost:8081");
kafkaProducer = new KafkaProducer<>(kafkaProps);
}
public static void main(String[] args) throws InterruptedException, IOException {
Customer customer1 = new Customer(1002, "Jimmy");
Parser parser = new Parser();
Schema schema = parser.parse(AvroSpecificProducer.class
.getClassLoader().getResourceAsStream("avro/customer.avsc"));
SpecificDatumWriter<Customer> writer = new SpecificDatumWriter<>(schema);
try(ByteArrayOutputStream os = new ByteArrayOutputStream()) {
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(os, null);
writer.write(customer1, encoder);
encoder.flush();
byte[] avroBytes = os.toByteArray();
ProducerRecord<String, byte[]> record1 = new ProducerRecord<>("CustomerSpecificCountry",
"Customer One 11 ", avroBytes
);
asyncSend(record1);
}
Thread.sleep(10000);
}
在控制台中使用消费者,我们成功地能够接收消息。那么将消息解码到我们的pojo文件中的方法是什么?
答案 0 :(得分:0)
这个问题的解决方法是,使用
DatumReader<GenericRecord> customerDatumReader = new SpecificDatumReader<>(schema);
而不是
`DatumReader<Customer> customerDatumReader = new SpecificDatumReader<>(schema);
确切的原因,仍未找到。这可能是因为Kafka不知道消息的结构,我们明确定义了消息的模式,GenericRecord
对于根据模式将任何消息转换为可读的JSON格式很有用。创建JSON后,我们可以轻松地将其转换为我们的POJO类。
但是,仍然需要找到直接转换为我们的POJO类的解决方案。
答案 1 :(得分:0)
在将值传递给ProduceRecord
之前,您无需显式执行Avro序列化。序列化器将为您完成。您的代码如下:
Customer customer1 = new Customer(1002, "Jimmy");
ProducerRecord<String, Customer> record1 = new ProducerRecord<>("CustomerSpecificCountry", customer1);
asyncSend(record1);
}
请参阅Confluent中的simple producer using avro
示例