Java
Java is a popular enterprise programming language with excellent Protocol Buffers and gRPC support. Bufrnix provides comprehensive Java code generation using Google’s official generators and runtime libraries.
Quick Start
Section titled “Quick Start”{ languages.java = { enable = true; outputPath = "gen/java"; };}
{ languages.java = { enable = true; outputPath = "gen/java"; grpc.enable = true; };}
{ languages.java = { enable = true; outputPath = "gen/java"; protovalidate.enable = true; };}
Generators
Section titled “Generators”Bufrnix supports all three major Java protobuf generators:
Generator | Purpose | Plugin |
---|---|---|
protocolbuffers/java | Base types for Java messages and enums | Built-in to protoc |
grpc/java | Java client and server stubs for gRPC | protoc-gen-grpc-java |
bufbuild/validate-java | Runtime validation using CEL expressions | protovalidate-java library |
Configuration
Section titled “Configuration”Basic Options
Section titled “Basic Options”{ languages.java = { enable = true;
# Output directory for generated Java files outputPath = "gen/java";
# Java package to use (defaults to proto package) packageName = "com.example.protos";
# JDK version to use jdk = pkgs.jdk17;
# Additional options for protoc options = []; };}
gRPC Support
Section titled “gRPC Support”{ languages.java.grpc = { enable = true;
# gRPC Java package package = pkgs.grpc-java;
# Additional gRPC generation options options = []; };}
Validation Support
Section titled “Validation Support”{ languages.java.protovalidate = { enable = true;
# Protovalidate package (runtime validation) package = pkgs.protoc-gen-validate-java;
# Additional validation options options = []; };}
Generated Code Structure
Section titled “Generated Code Structure”When you run nix run .#generate
, bufrnix creates:
gen/java/├── com/example/protos/v1/ # Generated Java classes│ ├── Person.java # Message class│ ├── PersonOrBuilder.java # Interface│ └── PersonProto.java # File-level class├── build.gradle # Gradle build file├── pom.xml # Maven build file└── PROTOVALIDATE_README.txt # Validation setup (if enabled)
Examples
Section titled “Examples”Basic Message Usage
Section titled “Basic Message Usage”// Create a person messagePerson person = Person.newBuilder() .setId(1) .setName("John Doe") .setEmail("john.doe@example.com") .build();
// Serialize to bytesbyte[] data = person.toByteArray();
// Parse from bytesPerson parsed = Person.parseFrom(data);
gRPC Service Implementation
Section titled “gRPC Service Implementation”public class GreeterImpl extends GreeterServiceGrpc.GreeterServiceImplBase { @Override public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) { HelloResponse response = HelloResponse.newBuilder() .setMessage("Hello " + request.getName()) .build(); responseObserver.onNext(response); responseObserver.onCompleted(); }}
Validation with Protovalidate
Section titled “Validation with Protovalidate”// Create validatorValidator validator = new Validator();
// Validate a messagetry { validator.validate(user); System.out.println("User is valid!");} catch (ValidationException e) { System.out.println("Validation failed:"); e.getViolations().forEach(violation -> System.out.println("- " + violation.getFieldPath() + ": " + violation.getMessage()) );}
Build Integration
Section titled “Build Integration”Gradle
Section titled “Gradle”The generated build.gradle
includes all necessary dependencies:
dependencies { implementation 'com.google.protobuf:protobuf-java:3.25.1' implementation 'io.grpc:grpc-stub:1.60.0' // if gRPC enabled implementation 'io.grpc:grpc-protobuf:1.60.0' // if gRPC enabled implementation 'io.grpc:grpc-netty-shaded:1.60.0' // if gRPC enabled implementation 'build.buf:protovalidate:0.1.8' // if validation enabled}
The generated pom.xml
provides equivalent Maven dependencies:
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.25.1</version></dependency>
Features
Section titled “Features”Core Protobuf Features
Section titled “Core Protobuf Features”- Type Safety: Strongly typed message classes with builders
- Performance: Efficient binary serialization
- Immutability: Generated classes are immutable
- Reflection: Full descriptor and reflection support
- JSON Support: Optional JSON serialization (with additional dependencies)
gRPC Features
Section titled “gRPC Features”- Service Stubs: Blocking, async, and future-based clients
- Server Implementation: Base classes for service implementation
- Streaming: Support for all four gRPC streaming patterns
- Error Handling: Rich status and error handling
- Interceptors: Client and server interceptor support
Validation Features
Section titled “Validation Features”- Runtime Validation: CEL-based validation expressions
- Field Constraints: String length, numeric ranges, patterns
- Message Validation: Cross-field validation logic
- Collection Rules: Min/max items, uniqueness constraints
- Custom Rules: Complex business logic with CEL
Best Practices
Section titled “Best Practices”- Use Java 17+: Modern Java features improve code quality
- Builder Pattern: Always use builders for message construction
- Null Safety: Messages are never null, but optional fields may be unset
- Performance: Reuse builder instances when creating many messages
- Error Handling: Always handle parsing and validation exceptions
- Thread Safety: Generated classes are thread-safe (immutable)
Examples
Section titled “Examples”- java-basic - Basic protobuf usage
- java-grpc - gRPC client and server
- java-protovalidate - Runtime validation
Dependencies
Section titled “Dependencies”Java code generation requires:
- JDK 17+: For building and running Java code
- Protocol Buffers: Core protobuf runtime
- gRPC Java (optional): For gRPC functionality
- Protovalidate Java (optional): For validation support
Complete Flake Configuration Example
Section titled “Complete Flake Configuration Example”{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
bufrnix = {
url = "github:conneroisu/bufrnix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = {
self,
nixpkgs,
flake-utils,
bufrnix,
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
packages = [
pkgs.gradle
pkgs.maven
pkgs.jdk17
pkgs.protobuf
];
shellHook = ''
echo "Java Basic Protobuf Example"
echo "Available commands:"
echo " nix build - Generate Java protobuf code"
echo " gradle build - Build with Gradle (in gen/java/)"
echo " mvn compile exec:java -Dexec.mainClass='com.example.Main' - Build and run with Maven (in gen/java/)"
'';
};
packages = {
default = bufrnix.lib.mkBufrnixPackage {
inherit pkgs;
config = {
root = ./.;
protoc = {
sourceDirectories = ["./proto"];
includeDirectories = ["./proto"];
files = ["./proto/example/v1/person.proto"];
};
languages.java = {
enable = true;
package = pkgs.protobuf;
jdk = pkgs.jdk17;
outputPath = "gen/java";
options = [];
};
};
};
};
});
}