Importing protocol buffer definitions between Mave

2019-03-11 10:31发布

问题:

I currently manage a few separate Maven projects in which I use Protobufs as a serialization format and over the wire. I am using David Trott's maven-protoc plugin to generate the code at compile time.

All is good and well until I want those project to communicate between one another — or rather, use each other's protobufs. The protobuf language has an "import" directive which does what I want but I'm faced with the challenge of having project A exporting a ".proto" file (or possibly some intermediate format?) for project B to depend upon.

Maven provides a way for a project to bundle resources but AFAIK, these are meant to be used at runtime by the code and not by a goal during the compile / source generation phase — at least I haven't been able to find documentation that describes what I want to achieve.

回答1:

I've found another way to achieve, and it doesn't involve any Maven magic. Diving into the code for the maven-protoc plugin, I found that this is a supported use case -- the plugin will look for and collect and .proto files in dependent jars and unpack them into a temporary directory. That directory is then set as an import path to the protoc invocation.

All that needs to happen is for the .proto file to be included in the dependency's package, which I did by making it a resource:

projects/a/src/main/resources/a.proto

Now in projects/b/pom.xml, add 'a' as a regular Maven dependency and just import a.proto from b.proto as if it existed locally:

b.proto: import "a.proto";

This isn't ideal, since files names may clash between various projects, but this should occur rarely enough.



回答2:

You can package your .proto files in a separate .jar/.zip in the project where they are generated, and publish them in your repository using a dedicated classifier. Using the assembly plugin might help here to publish something close to "source jars" that are built during releases.

Then, on projects using them, add previously created artifact as dependency. Use the dependency plugin with the "unpack-dependencies" goal, and bind it to a phase before "compile".