Java 在apache beam中使用SpanRio时出错

Java 在apache beam中使用SpanRio时出错,java,google-cloud-dataflow,apache-beam,google-cloud-spanner,Java,Google Cloud Dataflow,Apache Beam,Google Cloud Spanner,这是一个后续问题。 我正在尝试使用ApacheBeam从google扳手表读取数据(然后进行一些数据处理)。我使用java SDK编写了以下最低限度的示例: package com.google.cloud.dataflow.examples; import java.io.IOException; import org.apache.beam.sdk.Pipeline; import org.apache.beam.sdk.PipelineResult; import org.apache.b

这是一个后续问题。 我正在尝试使用ApacheBeam从google扳手表读取数据(然后进行一些数据处理)。我使用java SDK编写了以下最低限度的示例:

package com.google.cloud.dataflow.examples;
import java.io.IOException;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.PipelineResult;
import org.apache.beam.sdk.io.gcp.spanner.SpannerIO;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.values.PCollection;
import com.google.cloud.spanner.Struct;

public class backup {

  public static void main(String[] args) throws IOException {
    PipelineOptions options = PipelineOptionsFactory.create();

    Pipeline p = Pipeline.create(options);
    PCollection<Struct> rows = p.apply(
            SpannerIO.read()
                .withInstanceId("my_instance")
                .withDatabaseId("my_db")
                .withQuery("SELECT t.table_name FROM information_schema.tables AS t")
                );
    
    PipelineResult result = p.run();
    try {
      result.waitUntilFinish();
    } catch (Exception exc) {
      result.cancel();
    }
  }
}
package com.google.cloud.dataflow.examples;
导入java.io.IOException;
导入org.apache.beam.sdk.Pipeline;
导入org.apache.beam.sdk.PipelineResult;
导入org.apache.beam.sdk.io.gcp.span.span;
导入org.apache.beam.sdk.options.PipelineOptions;
导入org.apache.beam.sdk.options.pipelineoptions工厂;
导入org.apache.beam.sdk.values.PCollection;
导入com.google.cloud.panner.Struct;
公共类备份{
公共静态void main(字符串[]args)引发IOException{
PipelineOptions=PipelineOptionsFactory.create();
Pipeline p=Pipeline.create(选项);
PCollection行=p.apply(
请参阅(
.withInstanceId(“我的实例”)
.withDatabaseId(“my_db”)
.withQuery(“从信息中选择t.table\u name\u schema.tables作为t”)
);
PipelineResult=p.run();
试一试{
result.waitUntilFinish();
}捕获(异常exc){
result.cancel();
}
}
}
当我尝试使用DirectRunner执行代码时,我得到 以下错误消息:

org.apache.beam.runners.direct.repackaged.com.google.common.util.concurrent.UncheckedExecutionException:

org.apache.beam.sdk.util.UserCodeException: java.lang.NoClassDefFoundError:无法初始化类 com.google.cloud.span.spi.v1.span错误截取器

[……]由下列原因造成: org.apache.beam.sdk.util.UserCodeException: java.lang.NoClassDefFoundError:无法初始化类 com.google.cloud.span.spi.v1.span错误截取器

[……]由下列原因造成: java.lang.NoClassDefFoundError:无法初始化类 com.google.cloud.span.spi.v1.span错误截取器

或者,使用DataflowRunner:

org.apache.beam.runners.direct.repackaged.com.google.common.util.concurrent.UncheckedExecutionException: org.apache.beam.sdk.util.UserCodeException: java.lang.NoSuchFieldError: 内部\静态\谷歌\ rpc \本地化消息\字段可访问性

[…]原因:org.apache.beam.sdk.util.UserCodeException: java.lang.NoSuchFieldError: 内部\静态\谷歌\ rpc \本地化消息\字段可访问性

[…]原因:java.lang.NoSuchFieldError: 内部\静态\谷歌\ rpc \本地化消息\字段可访问性

在这两种情况下,错误信息都相当隐晦,我无法从谷歌搜索中找到任何关于错误原因的清晰想法。我也找不到任何使用span模块的示例脚本


此错误是由于我的代码中的明显错误造成的,还是由于google cloud tools安装错误造成的?

您需要指定ProjectID:

    SpannerIO.read()
            .withProjectId("my_project")
            .withInstanceId("my_instance")
            .withDatabaseId("my_db")
您需要为您的扳手项目设置凭据。由于SpanRio的API不允许您设置任何自定义凭据,因此必须使用环境变量GOOGLE_Application_credentials设置全局应用程序凭据

您还可以使用JDBC读取(和写入)云扳手。阅读是这样做的:

        PCollection<KV<String, Long>> words = p2.apply(JdbcIO.<KV<String, Long>> read()
            .withDataSourceConfiguration(JdbcIO.DataSourceConfiguration.create("nl.topicus.jdbc.CloudSpannerDriver",
                    "jdbc:cloudspanner://localhost;Project=my-project-id;Instance=instance-id;Database=database;PvtKeyPath=C:\\Users\\MyUserName\\Documents\\CloudSpannerKeys\\cloudspanner-key.json"))
            .withQuery("SELECT t.table_name FROM information_schema.tables AS t").withCoder(KvCoder.of(StringUtf8Coder.of(), BigEndianLongCoder.of()))
            .withRowMapper(new JdbcIO.RowMapper<KV<String, Long>>()
            {
                private static final long serialVersionUID = 1L;

                @Override
                public KV<String, Long> mapRow(ResultSet resultSet) throws Exception
                {
                    return KV.of(resultSet.getString(1), resultSet.getLong(2));
                }
            }));
PCollection words=p2.apply(JdbcIO.read())
.withDataSourceConfiguration(JdbcIO.DataSourceConfiguration.create(“nl.topicus.jdbc.CloudSpanerDriver”),
“jdbc:cloudspanner://localhost;Project=my Project id;Instance=Instance id;Database=Database;PvtKeyPath=C:\\Users\\MyUserName\\Documents\\cloudspan-rkeys\\cloudspan-key.json”))
.withQuery(“从信息中选择t.table\U名称作为t”).withCoder(KvCoder.of(StringUtf8Coder.of(),BigEndianLongCoder.of())
.withRowMapper(新的JdbcIO.RowMapper()
{
私有静态最终长serialVersionUID=1L;
@凌驾
public KV mapRow(ResultSet ResultSet)引发异常
{
返回KV.of(resultSet.getString(1),resultSet.getLong(2));
}
}));

此方法还允许您通过设置PvtKeyPath来使用自定义凭据。您还可以使用JDBC向Google Cloud Spaner写入数据。查看此处的示例:

此问题很可能是由此处描述的依赖项兼容性问题引起的:。以下是JIRA期刊评论中描述的快速解决方法:


com.google.api.grpc
谷歌通用协议
0.1.9
org.apache.beam
beam SDK java io谷歌云平台
${beam.version}
com.google.api.grpc
谷歌通用协议

明确定义所需的
com.google.api.grpc
依赖项,并从
org.apache.beam
中排除该版本

我确实忘记了“projectID”行,尽管添加它并不能修复错误。事实上,我正在使用EclipseGoogleCloudTools插件,并登录到我的google帐户。所以这应该考虑到凭证?我可能不得不尝试JDBC版本。啊,您可能遇到了依赖冲突。它是固定的,但我们需要等待新版本的梁。您可以自己从源代码构建beam二进制文件,也可以在pom.xml中使用此技巧。谢谢我想我会试试这个方法。谢谢!不过,老实说,我最终还是使用了python SDK,并制作了一个自定义的ParDo,用于对扳手进行读/写操作。