[protocolbuffers/protobuf]com.google.protobuf.GenerateMessageV3.isStringEmpty 应该是公开的

2024-05-11 972 views
5

版本:v3.19.1 语言:Java 操作系统:Windows 10

从 .proto 文件编译 protoc 3.19.1 生成的 java 源代码时,出现以下错误:

 error: cannot find symbol
    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(appId_)) {
                                               ^
  symbol:   method isStringEmpty(Object)
  location: class GeneratedMessageV3

检查java类com.google.protobuf.GenerateMessageV3的源代码后发现方法isStringEmpty被定义为protected而不是public。

回答

7

在哪个文件中发现错误?您手头有该文件的完整源代码吗?

0

重现此错误的详细步骤:

1)从https://github.com/protocolbuffers/protobuf/releases/download/v3.19.1/protoc-3.19.1-linux-x86_64.zip下载protoc v3.19.1

$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.19.1/protoc-3.19.1-linux-x86_64.zip

2)解压下载的protoc

$ unzip protoc-3.19.1-linux-x86_64.zip
$ cd protoc-3.19.1

3)编译以下helloworld.proto

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

使用命令:

$ mkdir java_output
$ bin/protoc --java_output=java_output helloworld.proto

转到目录 java_output/io/grpc/examples/helloworld 并 grep com.google.protobuf.GenerateMessageV3.isStringEmpty

$ cd java_output/io/grpc/examples/helloworld
$ grep com.google.protobuf.GeneratedMessageV3.isStringEmpty *.java
HelloReply.java:    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(message_)) {
HelloReply.java:    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(message_)) {
HelloRequest.java:    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) {
HelloRequest.java:    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) {

com.google.protobuf.GenerateMessageV3 类中的受保护方法 isStringEmpty 由类 HelloReply 和 HelloRequest 使用。当尝试编译上面生成的源代码时,我们收到错误:

 error: cannot find symbol
    if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(appId_)) {
                                               ^
  symbol:   method isStringEmpty(Object)
  location: class GeneratedMessageV3
5

您能否确认在编译该版本的协议生成的源代码时使用的是最新的运行时?我想我们过去也见过类似的问题。

7

我在尝试使用最新版本的 protoc、protbuf-java 和 grpc-java 时遇到了类似的问题,以便能够通过 protobuf maven 插件在 Mac M1 中编译 protos。

com.google.protobuf.protoc = 3.19.1 protoc-gen-grpc-java.plugin = 1.42.1 (对 protobuf-java = 3.17.2 有内部依赖)(不包含com.google.protobuf.GeneratedMessageV3.isStringEmpty) protobuf-java = 3.19.1 protobuf-java-util = 3.19.1

问题是最新的协议生成的代码依赖于com.google.protobuf.GeneratedMessageV3.isStringEmpty3.17.3+ 中可用的函数 ( )。

因此,正如 @perezd 所说,您可能会再次编译旧版本的 protobuf-java。

因此,解决方法是使用 protoc 3.17.3,正如我提到的https://github.com/protocolbuffers/protobuf/issues/8062#issuecomment-977716425https://github.com/grpc/grpc-java/issues /8724(如果还要求升级到最新的 protobuf 3.19.1 版本)

1

protobuf新版本中发生了变化,配置工作在这里:


    <dependencies>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.19.1</version> 
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.5.0</version>
                <extensions>true</extensions>
                <configuration>
                    <protoSourceRoot>${project.basedir}/proto</protoSourceRoot>
                    <outputDirectory>${project.build.sourceDirectory}</outputDirectory>
                    <clearOutputDirectory>true</clearOutputDirectory>
                    <temporaryProtoFileDirectory>
                        ${project.build.directory}/protoc-temp
                    </temporaryProtoFileDirectory>
                    <protocExecutable>
                        D:/arch/myexe/protoc/bin/protoc.exe <!-- libprotoc 3.19.1 -->
                    </protocExecutable>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
2

只是猜测:没有官方的 protobuf maven 插件,而您在这里使用的插件比该开发人员发布的版本落后了几个版本。可能是这个插件的旧版本正在拉入旧版本的原型库。

2

要解决此问题,您必须明确指出 protobuf-java(3.17.3+) 的版本,例如在 build.gradle 文件中: implementation 'com.google.protobuf:protobuf-java:3.19.1'

8

谢谢,很高兴听到

5

@elharo 我一直在尝试自学如何编码和解码协议缓冲区,因为我必须能够将 GoogleAuthenticator 应用程序导出迁移到我用 Java 编写的应用程序中。我为了学习如何做到这一点而进行的搜索导致我在 Github 上找到了这个问题- 其中的解决方案根本不是我理解的……这开始了我对如何做这件事的追求……该问题有一个 .proto文件被列为将有助于完成该任务的文件。这是 .proto 文件:

syntax = "proto3";

message MigrationPayload {
    enum Algorithm {
        ALGORITHM_UNSPECIFIED = 0;
        ALGORITHM_SHA1 = 1;
        ALGORITHM_SHA256 = 2;
        ALGORITHM_SHA512 = 3;
        ALGORITHM_MD5 = 4;
    }
    enum DigitCount {
        DIGIT_COUNT_UNSPECIFIED = 0;
        DIGIT_COUNT_SIX = 1;
        DIGIT_COUNT_EIGHT = 2;
    }
    enum OtpType {
        OTP_TYPE_UNSPECIFIED = 0;
        OTP_TYPE_HOTP = 1;
        OTP_TYPE_TOTP = 2;
    }
    message OtpParameters {
        bytes secret = 1;
        string name = 2;
        string issuer = 3;
        Algorithm algorithm = 4;
        DigitCount digits = 5;
        OtpType type = 6;
        int64 counter = 7;
    }
    repeated OtpParameters otp_parameters = 1;
    int32 version = 2;
    int32 batch_size = 3;
    int32 batch_index = 4;
    int32 batch_id = 5;
}

然后我在 Google 上找到了这个关于协议缓冲区的教程,它指示我下载 proto 命令,最终引导我在这里获取 MacOS 的编译版本。

然后,我运行该命令并收到一个生成的 .java 类文件,该文件中有多个位置,其中包含以下语句:

com.google.protobuf.GeneratedMessageV3.isStringEmpty

但“isStringEmpty”似乎是对不存在的东西的引用......

从我的立场来看,生成 .java 类的 proto 命令是失败的地方,因为它似乎将代码插入到它生成的类中,从而调用另一个不存在的类。

我想知道...是如何修复它生成的类?

顺便说一句,这是我在项目中使用的依赖项:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.19.1</version>
</dependency>

编辑:

当我从此处下载proto 版本 3.17.3并从同一 .proto 文件重新生成该类时,生成的类不包含对 isStringEmpty 的调用,并且在仍然使用依赖项版本 3.19.1 时不会导致任何错误。

2

@elharo 我一直在尝试自学如何编码和解码协议缓冲区,因为我必须能够将 GoogleAuthenticator 应用程序导出迁移到我用 Java 编写的应用程序中。我为了学习如何做到这一点而进行的搜索导致我在 Github 上找到了这个问题- 其中的解决方案根本不是我理解的……这开始了我对如何做这件事的追求……该问题有一个 .proto文件被列为将有助于完成该任务的文件。这是 .proto 文件:

syntax = "proto3";

message MigrationPayload {
  enum Algorithm {
      ALGORITHM_UNSPECIFIED = 0;
      ALGORITHM_SHA1 = 1;
      ALGORITHM_SHA256 = 2;
      ALGORITHM_SHA512 = 3;
      ALGORITHM_MD5 = 4;
  }
  enum DigitCount {
      DIGIT_COUNT_UNSPECIFIED = 0;
      DIGIT_COUNT_SIX = 1;
      DIGIT_COUNT_EIGHT = 2;
  }
  enum OtpType {
      OTP_TYPE_UNSPECIFIED = 0;
      OTP_TYPE_HOTP = 1;
      OTP_TYPE_TOTP = 2;
  }
  message OtpParameters {
      bytes secret = 1;
      string name = 2;
      string issuer = 3;
      Algorithm algorithm = 4;
      DigitCount digits = 5;
      OtpType type = 6;
      int64 counter = 7;
  }
  repeated OtpParameters otp_parameters = 1;
  int32 version = 2;
  int32 batch_size = 3;
  int32 batch_index = 4;
  int32 batch_id = 5;
}

然后我在 Google 上找到了这个关于协议缓冲区的教程,它指示我下载 proto 命令,最终引导我在这里获取 MacOS 的编译版本。

然后,我运行该命令并收到一个生成的 .java 类文件,该文件中有多个位置,其中包含以下语句:

com.google.protobuf.GeneratedMessageV3.isStringEmpty

但“isStringEmpty”似乎是对不存在的东西的引用......

从我的立场来看,生成 .java 类的 proto 命令是失败的地方,因为它似乎将代码插入到它生成的类中,从而调用另一个不存在的类。

我想知道...是如何修复它生成的类?

顺便说一句,这是我在项目中使用的依赖项:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.19.1</version>
</dependency>

编辑:

当我从此处下载proto 版本 3.17.3并从同一 .proto 文件重新生成该类时,生成的类不包含对 isStringEmpty 的调用,并且在仍然使用依赖项版本 3.19.1 时不会导致任何错误。

谢谢你的提示。它确实帮助我解决了我的问题。我也尝试过使用3.19.2,但它没有解决这个问题。

我做了以下事情:

  1. 下载原型版本 3.17.3 并将其复制到/usr/local/bin/protoc-3.17.3
  2. 将此原型版本包含在我的插件设置中,pom.xml如下所示:
 <plugin>
        <groupId>org.xolstice.maven.plugins</groupId>
        <artifactId>protobuf-maven-plugin</artifactId>
        <extensions>true</extensions>
        <version>${protobuf-plugin.version}</version>
        <configuration>
          <protocArtifact>
            com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
          </protocArtifact>
          <pluginId>grpc-java</pluginId>
          <pluginArtifact>
            io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
          </pluginArtifact>
          <protoSourceRoot>
            src/submodules/grpc/streamm
          </protoSourceRoot>
          <protocExecutable>
            /usr/local/bin/protoc-3.17.3
          </protocExecutable>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
              <goal>compile-custom</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

另外,既然这种情况仍然发生,那么这个问题应该重新打开还是一个新问题? @埃尔哈罗

1

我不相信这里有错误。这是由于协议编译器版本和运行时版本不匹配导致的。

5
<protocExecutable>
            /usr/local/bin/protoc-3.17.3
</protocExecutable>

删除此行并将 3.17.3 版本添加到protobuf-java-util解决了该问题,但它仍然不适用于任何比该版本更新的版本。

我不相信这里有错误。这是由于协议编译器版本和运行时版本不匹配导致的。

您能详细说明一下吗?那么如何使用3.19.2版本呢?

4

将 Spring Boot Starter ( https://github.com/yidongnan/grpc-spring-boot-starter ) 与 Spring 2.6.4 一起使用我遇到了同样的问题,我通过修复以下版本解决了它:

<protobuf.version>3.14.0</protobuf.version> <protobuf-plugin.version>0.6.1</protobuf-plugin.version> <grpc.version>1.35.0</grpc.version>

1

我遇到了同样的问题并通过修复以下版本解决了:

implementation 'net.devh:grpc-server-spring-boot-starter:2.13.1.RELEASE' protobufVersion = '3.19.2' protobufPluginVersion = '0.8.18' grpcVersion = '1.43.2'