我正在创建一个数据流模板,如果我传递所有必需的参数,它会完美地运行,但我的用例是创建一个通用模板,我可以在运行时传递参数。
我所有的选项都是ValueProvider,但仍然,它试图在创建模板时执行代码,并给出一个错误。是否有任何方法我可以创建一个数据流模板而不执行代码?
我也遇到了一个奇怪的问题,当我使用create template命令和所有的参数,然后它成功地创建模板,但在那个时候,所有的参数在代码中得到硬编码,如果我传递新的参数值,而运行它不会改变模板的值。
是数据流模板的正确行为吗?
不传递所有参数的命令:
mvn compile exec:java -D"exec.mainClass"="org.example.Main" -D"exec.args"="--runner=DataflowRunner --project=<project> --stagingLocation=gs://test-bucket/staging_4 --templateLocation=gs://test-bucket/templates/my_template --region=asia-south1 " -P dataflow-runner -X
在多次设计我的代码后,我知道我在做什么错误。
我所知道的是,你的代码应该被设计成这样一种方式,它不会要求任何值生成图形除了项目Id,阶段路径和模板路径。如果是询问,请检查以下做法并相应地进行设计。
如果你正在创建自定义模板,下面是你应该遵循的实践。
1.将所有选项声明为ValueProvider
,以便在运行时计算,模板创建过程将跳过它。
2.不要像下面这样把ValueProvider的值赋给normal变量
String Query = options.getQuery().toString();
PCollection<TableRow> rows = p.apply("Read From Source", JdbcIO.<TableRow>read()
.withQuery(Query)
3.尝试将ValueProvider
值直接传递给方法。例如,上面的代码片段应该像下面的
PCollection<TableRow> rows = p.apply("Read From Source", JdbcIO.<TableRow>read()
.withQuery(options.getQuery())
4不要只在模板创建过程中无法访问的特定代码块中使用选项。如下例:
Boolean Check = false;
if (options.getA().isAccessible()){
Check = true;
}
if (Check == true){
//Use of Options.getB().
}
在上面的情况下,如果您在创建模板时没有传递--a
选项,那么Check
值将始终是false
,并且下面的特定代码块将不可执行。如果我们没有在Check
块中使用--b
,那么在模板选项创建之后,b
对模板来说是未知的,如果在运行时传递它,它会给出一个错误。
5如果你有需要操作输入选项传递的数据的用例,那么你应该使用NestedValueProvider
而不是将ValueProvider
转换为正常变量,如String和操作数据。
例如,请避免以下做法:
String Query = String.format("SELECT * FROM %s", options.getTableName().toString());
PCollection<TableRow> rows = p.apply("Read From Source", JdbcIO.<TableRow>read()
.withQuery(Query)
实现如下逻辑:
ValueProvider<String> Query = NestedValueProvider.of(options.getTableName(),
new SerializableFunction<String, String>() {
@Override
public String apply(TranslatorInput<String, String> input)
{
return String.format("SELECT * FROM %s", input);;
}
});;
PCollection<TableRow> rows = p.apply("Read From Source", JdbcIO.<TableRow>read()
.withQuery(Query)
使用FlexTemplates代替。文档可以在这里找到。