使用AvroCoder使用提供的模式序列化泛型类

时间:2016-12-29 14:28:54

标签: java generics avro google-cloud-dataflow

让我们做一个简单的课程。

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中,当它无法获得字段&#34;数据&#34;来自Object的一个实例。这是有道理的,但为什么它不使用提供的模式来重建对象?在这种情况下如何创建AvroCoder实例?

更新

发现另一篇有类似问题的帖子,但看起来似乎没有得到解决...... Dataflow output parameterized type to avro file

3 个答案:

答案 0 :(得分:2)

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

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.0.0</version>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>org.sample.App</mainClass>     // specify your main class here
            </manifest>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id> <!-- this is used for inheritance merges -->
            <phase>package</phase> <!-- bind to the packaging phase -->
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      [...]
</project>

也许问题已得到解决?

答案 1 :(得分:0)

从未使用过AvroCoder,但这也是其他框架中泛型的常见问题。这通常由超类型令牌解决。 AvroCoder有一个采用类型令牌的方法(在这种情况下是TypeDescriptor)。

我没有尝试过这段代码,但它有可能工作。

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

答案 2 :(得分:0)

最后的说明: 最高版本1.9 Dataflow SDK 不支持在泛型上使用AvroCoder。当AvroCoder构造函数试图猜测结果是否具有确定性时,会发生错误。

Jule&#39; 16中Apache Beam的问题是resolved。在Apache Beam v0.2孵化之后,AvroCoder 始终为泛型实例化非确定性编码器。由于某些原因,它没有向后移植到Dataflow SDK。根据@jkff建议,我已经为数据流创建了PR。如果维护者决定应用它 - Dataflow SDK v1.10将支持泛型。

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