使用带有通配符泛型的编码器

时间:2018-05-14 12:17:15

标签: apache-beam

我有一个转换,它输出一个带通配符的类型: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(...)中指定我的编码器。但是,行为是一样的。

这是预期的行为吗?我应该避免使用外卡吗?或者我应该以另一种方式处理这个问题?为什么我的指定编码器不用于此?

0 个答案:

没有答案