Avro - 反序列化POJO

时间:2015-05-26 14:54:22

标签: java web-services serialization apache-kafka avro

我是Avro和Kafka的新手,他花了最后几天发送有关Kafka主题的序列化数据......但未成功。

让我解释一下我想要实现的目标:

在生产者方面,我通过SOAP接收数据并在Kafka主题上发送内容。我使用CXF从WSDL生成POJO,并且我已经编写了相应的模式。 我想要做的是序列化由CXF解组的对象并将它们发送到我的Kafka主题上。

在网络上发现的大多数示例中,Avro记录是使用已知的架构(或数据类型)生成的,但在这种情况下,我不知道在序列化数据时将使用哪个架构。 所以我动态地获取消息类型(通过CXF拦截器)并以这种方式序列化:

// get unmarshaled POJO
MessageContentsList objs = MessageContentsList.getContentsList(message);
Object obj = objs.get(0);

EncoderFactory factory = EncoderFactory.get();
ByteArrayOutputStream out = new ByteArrayOutputStream();
Encoder encoder = factory.directBinaryEncoder(out, null);

// getting schema from class name (first approach)
String scName = obj.getClass().getSimpleName();
InputStream avroRes = this.getClass().getClassLoader().getResourceAsStream(scName);
Schema schema = new Schema.Parser().parse(avroRes);

ReflectDatumWriter<Object> writer = new ReflectDatumWriter<Object>(schema);
writer.write(obj, encoder);
encoder.flush();
out.close();

KeyedMessage< String, byte[]> kMessage = new KeyedMessage<String, byte[]>("mytopic", out.toByteArray());
producer.send(kMessage);

这样我可以发送有关我主题的数据,但我无法从传入的消息中获取模式。

有办法:

  • 从Kafka主题中读取消息并获取用于序列化的模式?
  • 在使用和反序列化时将通用记录映射到POJO?

什么是最好的&#34;在数据类型未知时发送关于Kafka主题的Avro记录的做法?

也许我在阅读Avro文档时遗漏了一些内容,并且没有按预期使用它。

感谢您的帮助......

1 个答案:

答案 0 :(得分:1)

发送到Kafka主题的消息应该对架构和Avro记录进行编码。如果在每个消息中发送模式的开销太大,则发送模式的标识符。消息使用者可以使用标识符从schema registry检索完整的模式定义。例如,此code to serialize a Kafka message将模式标识符写入消息的第一个字节:

ByteArrayOutputStream out = new ByteArrayOutputStream();

schema = getSchema(object);
int id = schemaRegistry.register(subject, schema);
out.write(MAGIC_BYTE);
out.write(ByteBuffer.allocate(idSize).putInt(id).array());

BinaryEncoder encoder = encoderFactory.directBinaryEncoder(out, null);
DatumWriter<Object> writer;
if (object instanceof SpecificRecord) {
  writer = new SpecificDatumWriter<Object>(schema);
} else {
  writer = new GenericDatumWriter<Object>(schema);
}
writer.write(object, encoder);
encoder.flush();

byte[] bytes = out.toByteArray();
out.close();
return bytes;