我有一个转换,它输出一个带通配符的类型:Feature<? extends Geomery>
。我为这个类指定了一个编码器并创建了一个管道。
final Pipeline pipeline = Pipeline.create();
final TypeDescriptor<Feature<? extends Geometry>> featureTypeDescriptor =
new TypeDescriptor<Feature<? extends Geometry>>() {
};
pipeline.getCoderRegistry().registerCoderForType(featureTypeDescriptor, FeatureCoder.of());
final List<String> data = Arrays.asList("a", "b");
final PCollection<Feature<? extends Geometry>> features =
pipeline.apply(Create.of(data).withCoder(StringUtf8Coder.of()))
.apply(ParDo.of(new DoFn<String, Feature<? extends Geometry>>() {
@ProcessElement
public void process(ProcessContext processContext) {
final String name = processContext.element();
processContext.output(new FeatureImpl(name));
}
}));
pipeline.run().waitUntilFinish();
当我运行此管道时,出现以下错误:
Exception in thread "main" java.lang.ClassCastException: org.apache.beam.sdk.repackaged.com.google.common.reflect.Types$WildcardTypeImpl cannot be cast to java.lang.reflect.TypeVariable
at org.apache.beam.sdk.coders.CoderRegistry.getCoderFromTypeDescriptor(CoderRegistry.java:623)
at org.apache.beam.sdk.coders.CoderRegistry.getCoderFromParameterizedType(CoderRegistry.java:656)
at org.apache.beam.sdk.coders.CoderRegistry.getCoderFromTypeDescriptor(CoderRegistry.java:618)
at org.apache.beam.sdk.coders.CoderRegistry.getCoder(CoderRegistry.java:252)
at org.apache.beam.sdk.values.PCollection.inferCoderOrFail(PCollection.java:149)
at org.apache.beam.sdk.values.PCollection.finishSpecifyingOutput(PCollection.java:89)
这可以在Beam代码中追溯到org.apache.beam.sdk.coders.CoderRegistry#getCoderFromTypeDescriptor
中的以下行,其中类型最终被分配给? extends Geometry
:
else if (type instanceof WildcardType) {
// No coder for an unknown generic type.
throw new CannotProvideCoderException(
String.format("Cannot provide a coder for type variable %s"
+ " (declared by %s) because the actual type is unknown due to erasure.",
type,
((TypeVariable<?>) type).getGenericDeclaration()),
ReasonCode.TYPE_ERASURE);
}
以下示例简化了实际问题。实际上,我不是从字符串列表中读取而是从HBase中读取,所以我不能简单地在Create.of(data).withCoder(...)
中指定我的编码器。但是,行为是一样的。
这是预期的行为吗?我应该避免使用外卡吗?或者我应该以另一种方式处理这个问题?为什么我的指定编码器不用于此?