2016-12-29 71 views
0

让我们来创建一个简单的类。使用AvroCoder序列化提供的模式的泛型类

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(); 
} 

最后,我想以同样的方式与明确的模式创建AvroCoder因为它是在Using Avrocoder for Custom Types with Generics

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) 

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

UPDATE

找到另一篇文章中有类似的问题,但它看起来就像是无法得到解决...... Dataflow output parameterized type to avro file

+0

你可以请发布完整的堆栈跟踪,而不是只有错误消息? – jkff

+0

@jkff只是FYI SDK的版本是1.9.0 – Eugene

+0

@jkff我已经用完整的堆栈跟踪更新了这篇文章,能否再次检查一下? – Eugene

回答

0

最后一点: 直到版本1.9数据流SDK 不支持在泛型上使用AvroCoder。当AvroCoder构造函数试图猜测结果是否为确定性时会发生错误。

对于Jule'16中的Apache Beam,问题是resolved。在Apache Beam v0.2之后 - 孵化AvroCoder 总是实例化泛型的非确定性编码器。由于某些原因,它未被移植到Dataflow SDK。遵循@jkff的建议,我为Dataflow创建了一个PR。如果维护者决定应用它 - Dataflow SDK v1.10将支持泛型。

好消息是已经有SDK v.2.01-beta,它是Apache Beam v0.4.0的轻型代理,它支持泛型并且有很多附加功能。过渡需要一些代码更新,但绝对值得。

0

没用过AvroCoder,但多数民众赞成在其他框架仿制药的共同问题,以及。这通常通过超类型令牌来解决。 AvroCoder有一个方法,它接受一个类型标记(在这种情况下是TypeDescriptor)。

我还没有试过这段代码,但它有一定的工作可能性。

AvroCoder.of(new TypeDescriptor<Snapshot<InvValue>>(){}).of(buildSnapshotSchema(AvroCoder.of(IntValue.class).getSchema()); 
+0

我已经试过这种方法,但没有成功。它导致: '异常线程“main” org.apache.avro.AvroTypeException:未知类型:T' – Eugene

2

我复制并粘贴你的榜样成AvroCoderTest代码Apache中梁主分支和测试不会失败与此异常:

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())); 
} 

也许问题已得到修复?

+0

谢谢你,这很有趣,看起来是这样的情况下,铺满了测试[几个月前(https://开头github.com/apache/beam/commit/9c8dc4fe920618253b425f0d998f8d63552ec358)。综观[数据流SDK(https://github.com/GoogleCloudPlatform/DataflowJavaSDK/blob/master/sdk/src/main/java/com/google/cloud/dataflow/sdk/coders/AvroCoder版本AvroCoder的。 Java),似乎这个变化没有被反向支持。这是否意味着目前无法使用Dataflow SDK对泛型类进行编码? – Eugene

+0

这是可能的 - 梁意在成为*将* SDK的数据流,我们倾向于反向移植自己只是关键修复 - 猜我们错过了这一个。你能够使用Beam SDK吗?否则,请随时发送拉请求数据流与反向移植 - 它可能会进行审查,并迅速合并。 – jkff

相关问题