How can I add my own code to JAVA generated classes from proto file?

牧云@^-^@ 提交于 2019-12-24 07:16:11

问题


I'm using protobuf and I'm generating JAVA classes from the following proto file.

syntax = "proto3";
enum Greeting {
    NONE = 0;
    MR = 1;
    MRS = 2;
    MISS = 3;
}

message Hello {
    Greeting greeting = 1;
    string name = 2;
}

message Bye {
    string name = 1;
}

option java_multiple_files = true;

Now I need to add some code to the generated files and I found that is possible using a custom plugin (https://developers.google.com/protocol-buffers/docs/reference/java-generated#plugins). I'm trying to generate that plugin in Java, something like this.

public class Test {
   PluginProtos.CodeGeneratorResponse.getDefaultInstance();
   /* Code to get generated files from java_out and use the insertion points */
   codeGeneratorResponse.writeTo(System.out);
}

And then I run

protoc --java_out=./classes --plugin=protoc-gen-demo=my-plugin --demo_out=. example.proto

The problem is that on my Test.java main method I don't know how to get access to the files created by the option --java_out so that I can use their insertion points. Currently the CodeGeneratorResponse for the default instance is empty (no files).

Does anybody know how can I get the CodeGeneratorResponse from the --java_out so that I can add more code to the generated classes?

Thanks in advance.


回答1:


I recently struggled with this as well and wasn't able to find a good answer. I finally figured it out after staring at the comments within the CodeGeneratorResponse message for a while.

What threw me off at first was that I was thinking of plugins as a pipeline, where the output from one feeds into the next. However, each plugin gets the exact same input (the parsed .proto files expressed via CodeGeneratorRequest messages), and all the generated code from the plugins (including the built-in ones) gets combined into the output file. However, plugins may modify the output from the previous plugins, which is what insertion points are designed for.

Specifically to your question, you would add a file to the response with the name field getting set to the name of the generated Java file, the insertion_point field getting set to the name of the insertion point at which you want to add code, and the content field getting set to the code you want inserted at that point.

I found this article helpful in creating a simple plugin (in this case in python). As a simple test, I modified the generate_code function from that article to look like this:

def generate_code(request, response):
    for proto_file in request.proto_file:
        f = response.file.add()
        f.name = "Test.java"
        f.insertion_point = "outer_class_scope"
        f.content = "// Inserting a comment as a test"

Then I ran protoc with the plugin:

$ cat test.proto
syntax = "proto3";
message MyMsg {
    int32 num = 1;
}
$ protoc --plugin=protoc-gen-sample=sample_proto_gen.py --java_out=. --sample_out=. test.proto
$ tail -n3 Test.java
  // Inserting a comment as a test
  // @@protoc_insertion_point(outer_class_scope)
}

Your plugin just needs to be some executable which reads a CodeGeneratorRequest message from stdin and writes a CodeGeneratorResponse message to stdout, so could certainly be written in Java instead. I just chose python as I'm generally more comfortable with it and found this simple example.




回答2:


I have made a custom python plugin. To run my plugin i use the command below:

protoc --plugin=protoc-gen-custom=my_plugin_executable_file --custom_out=./build test.proto

So i think that, you have to generate an executable file from your .java file and use it in your command.



来源:https://stackoverflow.com/questions/50806894/how-can-i-add-my-own-code-to-java-generated-classes-from-proto-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!