An alternative Google Protocol Buffers code generator, parser, and Gradle module. The project has two design goals:
These design goals often compete with each other so this project tries to strike the right balance for use in the Hedera Node project. The hope is that balance might well be useful in many other projects. There is still plenty of work to achieve these goals and will probably always we improvements that can be made but this is what the project is striving for.
There is 3 gradle projects, the root project that builds two libraries:
pbj-core
which has 2 sub projects
pbj-compiler
which produces hedera.pbj-compiler.gradle.plugin-VERSION.jar
pbj-runtime
which produces pnj-runtime-VERSION.jar
pbj-integration-tests
which uses PBJ with test .proto files to generate code and run generated unit tests Each protobuf message is generated into a Java Record model object. With static instances for two codecs and a default
value. There is an inner Builder
class generated for fluid style building of the model object. There is also a
copyBuilder()
method that lets you easily create a derivative of this immutable record with some changes.
message Fraction {
int64 numerator = 1;
int64 denominator = 2;
}
public record Fraction(
long numerator,
long denominator
){
public static final Codec<Fraction> PROTOBUF = new com.hedera.hapi.node.base.codec.FractionProtoCodec();
public static final JsonCodec<Fraction> JSON = new com.hedera.hapi.node.base.codec.FractionJsonCodec();
public static final Fraction DEFAULT = newBuilder().build();
public Builder copyBuilder() {...}
public static Builder newBuilder() {...}
public static final class Builder {...}
}
Codecs are generated for each model class, one for Protobuf binary encoding and one for Protobuf JSON encoding. There
are static instances accessible via MyModelOject.PROTOBUF
and MyModelOject.JSON
.
For each generated model object there is a unit test generate that tests the protobuf and JSON codecs against the protoc generated code to make sure they are 100% byte for byte binary compatible.
com.hedera.pbj.runtime.io
As well as protobuf code generation, PBJ also provides a data IO library that provides an alternative to the default java.io & java.nio libraries. The PBJ Data IO library has some key design decisions, of which some are alternatives to the standard Java IO libraries:
EOFException
rather than by returning -1 from read bytes.Bytes
class. It tries hard to avoid
leakage of the underlying byte[] array while trying to balance that with performance.
Running gradle build
in pbj-core
directory will build the 2 libraries into the local maven repository for compiler and runtime.
Running gradle build
in pbj-integration-tests
will check out the latest proto source files from the
hedera-protobufs repository and generate code using pbj-compiler
then
run all the 100k+ generated unit tests which takes a few minutes. The hedera protobufs provide a good coverage of
protobuf features and insure all the generated code is tested for hedera node use case.
These tests should be run before committing any new code for PBJ.