让我们做一个简单的类。

class IntValue {
    private int data;

    IntValue() {}
    IntValue(int data) { this.setData(data); }

    int getData() { return this.data; }
    void setData(int data) { this.data = data; }
}


还有一个薄的通用包装器:

class Snapshot<T> {
    private T value;

    Snapshot<T> () {}

    T getValue() { return value; }
    void setValue(T value) { this.value = value; }
}


接下来,让我们来帮助您获取包装器的架构。

private static Schema buildSnapshotSchema(Schema valueSchema) {
    return SchemaBuilder.record("Snapshot")
            .namespace("com.stackoverflow.primer")
            .fields()
            .name("value").type(valueSchema).noDefault()
            .endRecord();
}


最后,我想以与在Using Avrocoder for Custom Types with Generics中创建的方式相同的方式使用显式架构创建AvroCoder

AvroCoder.of(Snapshot.class, buildSnapshotSchema(AvroCoder.of(IntValue.class).getSchema())


结果是...

Exception in thread "main" java.lang.IllegalArgumentException: Unable to get field data from class null
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.getField(AvroCoder.java:710)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.checkRecord(AvroCoder.java:548)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.doCheck(AvroCoder.java:477)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.recurse(AvroCoder.java:453)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.checkRecord(AvroCoder.java:567)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.doCheck(AvroCoder.java:477)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.recurse(AvroCoder.java:453)
at com.google.cloud.dataflow.sdk.coders.AvroCoder$AvroDeterminismChecker.check(AvroCoder.java:430)
at com.google.cloud.dataflow.sdk.coders.AvroCoder.<init>(AvroCoder.java:189)
at com.google.cloud.dataflow.sdk.coders.AvroCoder.of(AvroCoder.java:144)
at com.stackoverflow.primer.GenericPipeline.main(GenericPipeline.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)


当它无法从Object实例获取字段“数据”时,它发生在AvroDeterminismChecker中。这是有道理的,但是为什么它不使用提供的模式来重建对象呢?在这种情况下,如何创建AvroCoder的实例?

更新

找到了另一个存在类似问题的帖子,但似乎无法解决... Dataflow output parameterized type to avro file

最佳答案

我将您的示例复制并粘贴到Apache Beam的master分支的AvroCoderTest代码中,并且测试不会因以下异常而失败:

static class IntValue {
  private int data;

  IntValue() {}
  IntValue(int data) { this.setData(data); }

  int getData() { return this.data; }
  void setData(int data) { this.data = data; }
}
static class Snapshot<T> {
  private T value;

  Snapshot() {}

  T getValue() { return value; }
  void setValue(T value) { this.value = value; }
}
private static Schema buildSnapshotSchema(Schema valueSchema) {
  return SchemaBuilder.record("Snapshot")
      .namespace("blah")
      .fields()
      .name("value").type(valueSchema).noDefault()
      .endRecord();
}

@Test
public void testStackOverflowPost() throws Exception {
  AvroCoder.of(Snapshot.class, buildSnapshotSchema(AvroCoder.of(IntValue.class).getSchema()));
}


也许问题已经解决了?

10-08 20:28