-
Notifications
You must be signed in to change notification settings - Fork 17
Repobuild java tutorial
This will help you create a new "repobuild" based project. This tutorial is in Java.
If you have not already, install repobuild (see README)
- Fork the example_cpp project: https://github.com/chrisvana/repobuild_java_example
- Set up the repository locally:
$ git clone https://github.com/<username>/repobuild_java_example
$ cd repobuild_java_example
Currently, the BUILD file looks like this:
// Empty build file
[]
We are going to create a new java binary (jar) called "checker"
[
{ "java_binary": {
"name": "checker",
"java_sources": [ "Checker.java" ]
} }
]
And now create Checker.java:
// Simple checker main.
public class Checker {
public static void main(String[] args) {
System.out.println("Are you classified as human?");
}
}
Now run repobuild:
$ repobuild ":checker"
Processing: //:checker
Processing: //:checker.0
Processing: //:checker
Generating: Makefile
And build it:
$ make
Compiling: checker (java)
Jaring: .gen-obj/checker.jar
And test it:
$ ./checker
Are you classified as human?
At this point, your client should look like this.
Update our build file to add "parser":
[
{ "java_library": {
"name": "parser",
"java_sources": [ "Parser.java" ]
} },
{ "java_binary": {
"name": "checker",
"java_sources": [ "Checker.java" ],
"dependencies": [ ":parser" ]
} }
]
Now add Parser.java:
// Example library
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Parser {
public void Parse(InputStream input, OutputStream output) throws IOException {
// For now, do nothing but mirror the input.
int character ;
while ((character = input.read()) >= 0) {
output.write(character);
}
}
}
Great, now run repobuild:
$ repobuild ":checker"
Processing: //:checker
Processing: //:parser
Processing: //:checker.0
Processing: //:checker
Generating: Makefile
And run make:
$ make
Compiling: parser (java)
Compiling: checker (java)
Jaring: .gen-obj/checker.jar
Now let's make sure this works:
$ echo 'Negative, I am a meat popsicle' | ./checker
Negative, I am a meat popsicle
Wonderful. Your client should now look like this.
Add a proto library to your codebase:
[
{ "proto_library": {
"name": "my_proto",
"sources": [ "my_proto.proto" ],
"generate_java": true
} },
{ "java_library": {
"name": "parser",
"java_sources": [ "Parser.java" ],
"dependencies": [ ":my_proto" ]
} },
{ "java_binary": {
"name": "checker",
"java_sources": [ "Checker.java" ],
"dependencies": [ ":parser" ]
} }
]
proto_library (by default) uses //third_party/protobuf:... as its source. Let's add //third_party:
$ git submodule add https://github.com/chrisvana/third_party.git
Cloning into 'third_party'...
remote: Counting objects: 58, done.
remote: Compressing objects: 100% (50/50), done.
remote: Total 58 (delta 26), reused 39 (delta 7)
Unpacking objects: 100% (58/58), done.
Checking connectivity... done
Now re-run repobuild (note it auto-fetches required sub-modules from //third_party):
$ repobuild ":checker"
Processing: //:checker
Processing: //:parser
Processing: //:checker.0
Processing: //:my_proto
Processing: //:checker
Processing: //:my_proto.0
Processing: //:my_proto.1
Processing: //third_party/protobuf:java_proto
remote: Counting objects: 744, done.
remote: Compressing objects: 100% (459/459), done.
remote: Total 744 (delta 267), reused 738 (delta 261)
Receiving objects: 100% (744/744), 2.49 MiB | 540.00 KiB/s, done.
Resolving deltas: 100% (267/267), done.
Processing: //third_party/protobuf:generate_java_descriptor_proto
Processing: //third_party/protobuf:auto_.0
Processing: //third_party:auto_.0
Processing: //third_party/protobuf:protoc
Processing: //third_party/protobuf:protoc_lib
Processing: //third_party/protobuf:proto_lib
Processing: //third_party/protobuf:protoc.0
Generating: Makefile
Now run make:
$ make clean
$ make -j8
Compiling: third_party/protobuf/src/google/protobuf/descriptor.pb.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/descriptor.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/descriptor_database.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/dynamic_message.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/extension_set.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/extension_set_heavy.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/generated_message_reflection.cc (c++)
Compiling: third_party/protobuf/src/google/protobuf/generated_message_util.cc (c++)
... <cut> ...
Linking: .gen-obj/third_party/protobuf/protoc
Script: //third_party/protobuf:generate_java_descriptor_proto
Compiling: third_party/protobuf/java_proto (java)
Protobuf: //:my_proto.0
Compiling: my_proto.1 (java)
Compiling: parser (java)
Compiling: checker (java)
Jaring: .gen-obj/checker.jar
Your client should look like this.
Tying everything together, update Parser.java to check if the input is a valid instance of our protocol buffer:
// Example library
import com.google.protobuf.TextFormat;
import com.google.protobuf.TextFormat.ParseException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
public class Parser {
public void Parse(InputStream input, OutputStream output) throws IOException {
MyProto.FooProto.Builder builder = MyProto.FooProto.newBuilder();
PrintStream stream = new PrintStream(output);
try {
TextFormat.merge(new InputStreamReader(input, "ASCII"), builder);
stream.println("Success!");
} catch (ParseException e) {
stream.println("Failed to Parse ASCII input: " + e);
}
}
}
Run make (dependencies were added in the previous step, so no need to re-run repobuild):
$ make
Compiling: parser (java)
Compiling: checker (java)
Jaring: .gen-obj/checker.jar
Now test it:
# Ok protobuf:
$ echo "int_val: 10 bool_val: false" | ./checker
Success!
# Unknown field:
$ echo "int_val: 10 bool_val: false unknown_val: 123" | ./checker
Failed to Parse ASCII input: com.google.protobuf.TextFormat$ParseException: 1:29: Message type "FooProto" has no field named "unknown_val".
# Random garbage:
$ echo 'asdf' | ./checker
Failed to Parse ASCII input: com.google.protobuf.TextFormat$ParseException: 1:1: Message type "FooProto" has no field named "asdf".
Great, now your client should look something like this.
Congratulations, you've built a jar that depends a library, and some third_party open source code. Check out some other examples: https://github.com/chrisvana/repobuild/wiki/Examples