尝试序列化包含数组的Avro GenericRecord时出现NullPointerException

时间:2017-03-16 21:21:54

标签: java apache-kafka avro

尝试使用$items = Cap::pluck('cap_citta'); 编写Avro对象时,我尝试发布Avro(进入Kafka)并获得NullPointerException

这是缩写的stacktrace:

BinaryEncoder

以下是我的代码中发生异常的send方法:

java.lang.NullPointerException: null of array of com.mycode.DeeplyNestedObject of array of com.mycode.NestedObject of union of com.mycode.ParentObject
    at org.apache.avro.generic.GenericDatumWriter.npe(GenericDatumWriter.java:132) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:126) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:73) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:60) ~[avro-1.8.1.jar:1.8.1]
    at com.mycode.KafkaAvroPublisher.send(KafkaAvroPublisher.java:61) ~[classes/:na]
    ....
    at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:73) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:112) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.specific.SpecificDatumWriter.writeField(SpecificDatumWriter.java:87) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.generic.GenericDatumWriter.writeRecord(GenericDatumWriter.java:143) ~[avro-1.8.1.jar:1.8.1]
    at org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:105) ~[avro-1.8.1.jar:1.8.1]
    ... 55 common frames omitted

在架构中,private static final EncoderFactory ENCODER_FACTORY = EncoderFactory.get(); private static final SpecificDatumWriter<ParentObject> PARENT_OBJECT_WRITER = new SpecificDatumWriter<>(ParentObject.SCHEMA$); public void send(ParentObject parentObject) { try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); binaryEncoder = ENCODER_FACTORY.binaryEncoder(stream, binaryEncoder); PARENT_OBJECT_WRITER.write(parentObject, binaryEncoder); // Exception HERE binaryEncoder.flush(); producer.send(new ProducerRecord<>(topic, stream.toByteArray())); } catch (IOException ioe) { logger.debug("Problem publishing message to Kafka.", ioe); } } 包含NestedObject数组。我已经做了足够的调试,看到DeeplyNestedObject实际上包含NestedObject数组或者如果不存在则包含空数组。以下是架构的相关部分:

DeeplyNestedObject

2 个答案:

答案 0 :(得分:2)

来自Avro的堆栈跟踪具有误导性。问题可能比Exception消息所指示的类更深一层。

当它显示&#34; null of array of com.mycode.DeeplyNestedObject of array of com.mycode.NestedObject of union of com.mycode.ParentObject&#34;时,表示DeeplyNestedObject内的其中一个字段应为array,但发现{ {1}}。 (将null DeeplyNestedObject置于null内部意味着错误解释是完全有意义的。)

您需要检查NestedObject的字段,并确定哪些DeeplyNestedObject未正确序列化。问题可能位于创建array的位置。它将有一个类型为DeeplyNestedObject的字段,在调用send方法之前,串行器不会在所有情况下填充该字段。

答案 1 :(得分:0)

我对你拥有的对象了解不多,但我在你的例子中看到的是你的avro-schema不正确。

avro中的DeeplyNestedObject是一个记录,因此您的架构必须如下所示:

{
  "type": "record",
  "name": "NestedObject",
  "namespace": "com.mycode.avro",
  "fields": [
    {
      "name": "timestamp",
      "type": "long"
    },
    {
      "name": "objs",
      "type": {
        "type": "record",
        "name": "DeeplyNestedObject",
        "fields": []
      }
    }
  ]
}

当然,您需要在“fields”中声明DeeplyNestedObject的所有字段:[]与DeeplyNestedObject记录相关。