协议缓冲区无效的嵌入式描述符问题

时间:2010-06-23 20:55:30

标签: java protocol-buffers

我在运行时遇到了一些生成的协议缓冲区类的问题。

我的项目布局如下:

module/
  protobuf-api/
    proto/
      com/foo/api/Service.proto
      com/foo/shared/Shared.proto
      org/bar/api/Message1.proto
      org/bar/api/Message2.proto

Service.proto文件依赖于Shared.proto和一些Message * .proto文件。从protobuf-api目录中,我运行以下命令进行编译:
find . -name *.proto -exec protoc --java_out=java -I=proto {} \;

当我尝试运行我的服务时,我得到以下异常:

java.lang.ExceptionInInitializerError
    at com.linkedin.history.api.protobuf.HistoryServiceProtos$HistoryServiceQuery.(HistoryServiceProtos.java:544)
    at com.linkedin.history.api.serializer.HistoryServiceSerializer.serialize(HistoryServiceSerializer.java:47)
     at test.history.serializer.TestSerializer.testHistoryServiceQuery(TestSerializer.java:38)
    at test.fwk.util.core.BaseTestSuiteCore.run(BaseTestSuiteCore.java:304)
     at test.fwk.util.core.BaseTestSuiteConf.run(BaseTestSuiteConf.java:186)
    at test.fwk.lispring.BaseTestSuite.run(BaseTestSuite.java:232)
    at test.fwk.lispring.BaseTestSuite.callAppropriateRun(BaseTestSuite.java:265)
    at test.fwk.util.core.BaseTestSuiteCore.run(BaseTestSuiteCore.java:199)
Caused by: java.lang.IllegalArgumentException: Invalid embedded descriptor for "com/linkedin/history/api/protobuf/HistoryService.proto".
     at com.google.protobuf.Descriptors$FileDescriptor.internalBuildGeneratedFileFrom(Descriptors.java:268)
     at com.linkedin.history.api.protobuf.HistoryServiceProtos.(HistoryServiceProtos.java:1794)
Caused by: com.google.protobuf.Descriptors$DescriptorValidationException: com/linkedin/history/api/protobuf/HistoryService.proto: Dependencies passed to FileDescriptor.buildFrom() don't match those listed in the FileDescriptorProto.
     at com.google.protobuf.Descriptors$FileDescriptor.buildFrom(Descriptors.java:221)
     at com.google.protobuf.Descriptors$FileDescriptor.internalBuildGeneratedFileFrom(Descriptors.java:266)

我已阅读帖子here,但我认为我正在做的一切正确。有关为什么我有初始化程序错误的任何建议?我用相同的-I标志编译所有内容。

2 个答案:

答案 0 :(得分:5)

怀疑问题是当你找到原型文件时,你已经给它完整的路径,例如proto / com / foo / api / Service.proto但是当它通过include目录引用它时,它使用的是com / foo / api / Service.proto

简单修复 - 从proto目录运行:

find . -name *.proto -exec protoc --java_out=../java -I=. {} \;

我必须承认我记不起protoc的许多细节(我真的应该这样做),但我怀疑它会起作用。

可以工作的另一种选择:

protoc --java_out=java `find . -name '*.proto'`

即。将所有proto文件传递给protoc。

答案 1 :(得分:1)

我在C#中有相同的错误类型,这是我的问题:我在项目的预构建步骤中调用了protoc。在那里,我使用Visual Studio内置宏(如$(SolutionDir)$(ProjectDir)来检索必要的路径。由于我从其他项目引用了*.proto个文件,因此我使用了两个--proto_path选项:一个用于根路径(用于解析import路径),另一个用于文件本身。我的解决方案文件位于根目录的子目录中,因此我使用相对路径..来到根目录。 Proto文件始终位于特定项目的子目录gen中。总而言之,命令是这样的:

protoc.exe --proto_path=$(SolutionDir).. --proto_path=$(ProjectDir)gen  $(ProjectDir)gen\DemoFile.proto

它编译得很好,但我在运行时调用System.TypeInitializationException方法获得了CreateBuilder()。问题是,由于相对路径组件$(SolutionDir)..,路径$(ProjectDir)..(尽管有效地指向同一目录)具有不同的文本表示。我通过一直使用相同的路径解决了这个问题:

protoc.exe --proto_path=$(SolutionDir).. $(SolutionDir)..\My\Demo\Project\Directory\gen\DemoFile.proto

我花了将近3天的时间来缩小范围并认识到这个问题,所以我在这里分享我的解决方案,希望能为人节省一些时间。