2016-12-29 69 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

相關問題