让我们做一个简单的类。
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()));
}
也许问题已经解决了?