Java 使用TextIO和ValueProvider创建数据流模板时出错

Java 使用TextIO和ValueProvider创建数据流模板时出错,java,google-cloud-dataflow,apache-beam,apache-beam-io,Java,Google Cloud Dataflow,Apache Beam,Apache Beam Io,我正在尝试创建一个google数据流模板,但我似乎找不到一种不产生以下异常的方法: WARNING: Size estimation of the source failed: RuntimeValueProvider{propertyName=inputFile, default=null} java.lang.IllegalStateException: Value only available at runtime, but accessed from a non-runtime cont

我正在尝试创建一个google数据流模板,但我似乎找不到一种不产生以下异常的方法:

WARNING: Size estimation of the source failed: RuntimeValueProvider{propertyName=inputFile, default=null}
java.lang.IllegalStateException: Value only available at runtime, but accessed from a non-runtime context: RuntimeValueProvider{propertyName=inputFile, default=null}
        at org.apache.beam.sdk.options.ValueProvider$RuntimeValueProvider.get(ValueProvider.java:234)
        at org.apache.beam.sdk.io.FileBasedSource.getEstimatedSizeBytes(FileBasedSource.java:218)
        at org.apache.beam.runners.dataflow.internal.CustomSources.serializeToCloudSource(CustomSources.java:78)
        at org.apache.beam.runners.dataflow.ReadTranslator.translateReadHelper(ReadTranslator.java:53)
        at org.apache.beam.runners.dataflow.ReadTranslator.translate(ReadTranslator.java:40)
        at org.apache.beam.runners.dataflow.ReadTranslator.translate(ReadTranslator.java:37)
        at org.apache.beam.runners.dataflow.DataflowPipelineTranslator$Translator.visitPrimitiveTransform(DataflowPipelineTranslator.java:453)
        at org.apache.beam.sdk.runners.TransformHierarchy$Node.visit(TransformHierarchy.java:668)
        at org.apache.beam.sdk.runners.TransformHierarchy$Node.visit(TransformHierarchy.java:660)
        at org.apache.beam.sdk.runners.TransformHierarchy$Node.visit(TransformHierarchy.java:660)
        at org.apache.beam.sdk.runners.TransformHierarchy$Node.access$600(TransformHierarchy.java:311)
        at org.apache.beam.sdk.runners.TransformHierarchy.visit(TransformHierarchy.java:245)
        at org.apache.beam.sdk.Pipeline.traverseTopologically(Pipeline.java:458)
        at org.apache.beam.runners.dataflow.DataflowPipelineTranslator$Translator.translate(DataflowPipelineTranslator.java:392)
        at org.apache.beam.runners.dataflow.DataflowPipelineTranslator.translate(DataflowPipelineTranslator.java:170)
        at org.apache.beam.runners.dataflow.DataflowRunner.run(DataflowRunner.java:680)
        at org.apache.beam.runners.dataflow.DataflowRunner.run(DataflowRunner.java:174)
        at org.apache.beam.sdk.Pipeline.run(Pipeline.java:311)
        at org.apache.beam.sdk.Pipeline.run(Pipeline.java:297)
        at org.apache.beam.examples.MyMinimalWordCount.main(MyMinimalWordCount.java:69)
        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 org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:282)
        at java.lang.Thread.run(Thread.java:748)
我可以用Beam中的MinimumWordCount示例的简单修改版本来重现它

公共类MyMinimumWordCount{
公共接口WordCountOptions扩展了PipelineOptions{
@说明(“要从中读取的文件的路径”)
ValueProvider getInputFile();
作废setInputFile(ValueProvider ValueProvider);
}
公共静态void main(字符串[]args){
WordCountOptions=PipelineOptionFactory.fromArgs(args).withValidation()
.as(WordCountOptions.class);
Pipeline p=Pipeline.create(选项);
p、 应用(TextIO.read().from(options.getInputFile()))
.应用(FlatMapElements)
.into(typedescriptor.strings())
.via((字符串字)->Arrays.asList(字.split([^\\p{L}]+]))
.apply(Filter.by((字符串字)->!word.isEmpty())
.apply(Count.perElement())
.apply(映射元素)
.into(typedescriptor.strings())
.via((KV wordCount)->wordCount.getKey()+“:“+wordCount.getValue()))
.apply(TextIO.write().to(“字数”);
//在尝试创建数据流模板时,使用waitUntilFinish会导致NPE
//p、 run().waitUntilFinish();
p、 run();
}
}
我可以在本地运行该示例:

mvn compile exec:java \
     -Pdirect-runner \
     -Dexec.mainClass=org.apache.beam.examples.MyMinimalWordCount \
     -Dexec.args="--inputFile=pom.xml " 
它也在Google Dataflow上运行,具有:

mvn compile exec:java \
     -Pdataflow-runner \
     -Dexec.mainClass=org.apache.beam.examples.MyMinimalWordCount \
     -Dexec.args="--runner=DataflowRunner \
                  --project=[project] \
                  --inputFile=gs://[bucket]/input.csv "
但是,当我尝试使用以下内容创建Google数据流模板时,我得到了一个错误:

mvn compile exec:java \
     -Pdataflow-runner \
     -Dexec.mainClass=org.apache.beam.examples.MyMinimalWordCount \
     -Dexec.args="--runner=DataflowRunner \
                  --project=[project] \
                  --stagingLocation=gs://[bucket]/staging \
                  --templateLocation=gs://[bucket]/templates/MyMinimalWordCountTemplate " 
另一件令人困惑的事情是maven构建继续并以构建成功结束

因此,我的问题是:

Q1)我应该像这样创建一个Google数据流模板吗(使用ValueProviders在运行时提供TextIO输入)

Q2)构建过程中的异常是一个真正的错误还是日志显示的一个警告

Q3)如果对Q1和Q2的回答是“是”且“只是一个警告”,并且我尝试从上传的模板创建作业,为什么它没有任何元数据或不知道我的输入选项

我使用过的参考资料:

我认为创建模板时,--inputFiles与模板捆绑在一起

请参阅备注:“除了模板文件,模板化管道执行还依赖于模板创建时暂存和引用的文件。如果暂存文件被移动或删除,管道执行将失败。”


这个线程似乎也很相关

正确的答案是在制作模板时不必输入,它应该在运行时将输入作为一个值。例外情况是谷歌数据流的内部问题,应该在将来删除

我可以回答问题3)。我认为maven/dataflow构建将自动生成所需的元数据。事实并非如此。关于如何提供自己的元数据,可以在这里找到一个很好的描述:编译程序后,它会按照
--templateLocation=
中定义的路径为您生成模板。接下来,您将转到3中的屏幕,并使用添加的模板位置运行作业。最后,在
附加参数
中单击
添加项
,在键类型
输入文件
中,在值类型中单击输入文件的存储桶位置。完成后,运行作业,您就不会再有问题了。谢谢@haris,这是否意味着异常只是一个警告?发生错误是因为它希望您将
--inputFile
作为参数传递,而您没有传递。从技术上讲,您告诉程序创建一个模板并运行作业。因此,当它没有看到作业时,就产生了一个错误。至少据我所知。我从来不需要直接使用模板。不过,该模板仍应已创建