The library brings data validation directly into your Protobuf messages.
While Protobuf provides a structured way to define data schemas, it does not include built-in mechanisms for enforcing domain-specific rules at runtime. Without validation, invalid or inconsistent data can slip through, leading to subtle bugs and potential system failures.
Typically, developers address this by manually adding validation logic in application code or by invoking separate validation APIs. This ad-hoc approach can be error-prone and often results in duplicated, hard-to-maintain code scattered across the codebase.
Spine Validation solves this by modifying the code generated by the Protobuf compiler (protoc).
At build time, Spine Validation injects assertions directly into the generated Java classes,
enabling automatic enforcement of constraints without explicit API calls in application code.
This library is built with Java 17.
Define your validation rules right in the .proto file:
import "spine/options.proto";
import "spine/time_options.proto";
import "google/protobuf/timestamp.proto";
message CardNumber {
string digits = 1 [(pattern).regex = "\\d{4}\\s?\\d{4}\\s?\\d{4}\\s?\\d{4}"];
string owner = 2 [(required) = true];
google.protobuf.Timestamp issued_at = 3 [(when).in = PAST];
}At build time, Spine Validation injects assertions into the generated Java classes:
var card = CardNumber.newBuilder()
.setDigits("invalid")
.build(); // <- Validates here.val card = cardNumber {
digits = "invalid"
} // <- Validates here. If any constraint is violated, a ValidationException is thrown from build().
You can also validate without throwing:
var card = CardNumber.newBuilder()
.setDigits("invalid")
.buildPartial(); // <- No validation.
var optionalError = card.validate();
optionalError.ifPresent(err -> {
System.out.println(err.getMessage());
});Validation options are defined by the following files:
Users must import these .proto files to use the options they define.
import "spine/options.proto"; // Brings all options, except for time-related ones.
import "spine/time_options.proto"; // Brings time-related options.Users can extend the library by providing custom Protobuf options and code generation logic.
See the Custom validation section of the User Guide for details.