我在运行时遇到了一些生成的协议缓冲区类的问题。
我的项目布局如下:
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标志编译所有内容。
答案 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天的时间来缩小范围并认识到这个问题,所以我在这里分享我的解决方案,希望能为人节省一些时间。