Add validate() probe to ValidatingBuilder#316
Merged
Conversation
Add a default `validate()` method to `io.spine.validation.ValidatingBuilder`
that probes the builder's current content and returns any constraint
violations without throwing or mutating the builder. It builds the content
via `buildPartial()` and, when the result is a `ValidatableMessage`, unwraps
its `ValidationError` into the returned list; a message that does not support
validation is treated as valid. An empty list means the content is valid.
This gives callers a non-throwing counterpart to `build()` (which throws
`ValidationException`) that, unlike `buildPartial()`, does not skip validation
or hand back a possibly invalid message. It complements the `tryAlter {}`
entity extension from core-jvm PR #1642 (de-event-sourcing Phase A) and
implements the D9 amendment of ADR 0001. Requested by @armiol:
SpineEventEngine/core-jvm#1642 (comment)
Covered by stub-based unit tests (`ValidatingBuilderSpec`) and integration
tests against generated code (`JavaMessageSmokeTest`). The developer-docs
snippet mirroring the interface is updated to match.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a non-throwing validation probe to ValidatingBuilder so callers can check builder content validity (including already-invalid content) without throwing and without returning a potentially invalid message instance.
Changes:
- Added
ValidatingBuilder#validate()default method returning constraint violations (empty list = valid). - Added unit + integration tests covering valid/invalid cases and non-mutating behavior.
- Updated runtime-library docs and bumped snapshot version / regenerated dependency reports.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
jvm-runtime/src/main/java/io/spine/validation/ValidatingBuilder.java |
Adds validate() API and Javadoc explaining non-throwing probe semantics. |
jvm-runtime/src/test/kotlin/io/spine/validation/ValidatingBuilderSpec.kt |
New stub-based unit specs for validate() behavior and non-mutation. |
tests/validating/src/test/kotlin/io/spine/test/JavaMessageSmokeTest.kt |
Adds integration coverage for validate() on generated Java builder. |
docs/content/docs/validation/developer/runtime-library.md |
Updates developer docs page that mirrors the runtime contracts to include validate(). |
version.gradle.kts |
Bumps published snapshot version. |
docs/dependencies/pom.xml |
Regenerated dependency report metadata version. |
docs/dependencies/dependencies.md |
Regenerated dependency report content/version/timestamp churn. |
.agents/tasks/validating-builder-validate.md |
Task plan / implementation notes (not part of published API). |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #316 +/- ##
============================================
+ Coverage 12.09% 12.35% +0.25%
- Complexity 82 84 +2
============================================
Files 82 82
Lines 2034 2040 +6
Branches 160 161 +1
============================================
+ Hits 246 252 +6
Misses 1786 1786
Partials 2 2 🚀 New features to boost your workflow:
|
Address review feedback on PR #316: the interface-level Javadoc said `validate()` checks validity "without building the message", but the method calls `buildPartial()`, which does construct a message instance (the caller just never receives it). Reword to "without obtaining the built message". Also align abbreviation punctuation (`i.e.,`) with the `e.g.,` used earlier in the same Javadoc block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rewrite `ValidatingBuilderSpec` to probe the new `ValidatingBuilder.validate()` method through a real generated validating type instead of hand-written `AbstractMessage`/`Builder` stubs. The spec now uses the generated `InterestRate` message (a single `float percent` field constrained with `(min) > 0.0`) to cover the meaningful paths: valid content yields no violations, invalid content returns the violations without throwing, and probing leaves the builder content intact. Because a generated `ValidatingBuilder` always builds a `ValidatableMessage`, real generated types cannot reach the "message does not support validation" fallback branch; that branch is defensive and no longer has a dedicated stub test. The spec moves to the `tests:validating` module: `jvm-runtime` depends on `spine-base` and does not apply the `io.spine.validation` code generator, so it cannot produce a generated `ValidatableMessage`/`ValidatingBuilder` to test against — only a plugin-applied module such as `tests:validating` can. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Advance the `docs/_examples` submodule to the Protobuf runtime alignment for the migrated CoreJvm compiler. Fixes the `Build embedded code` check, where the generated `BankCard` failed to initialize because of a gencode `4.35.0` / runtime `4.34.1` mismatch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`ValidatingBuilder.validate()` returns an empty list when `buildPartial()` yields a message that does not implement `ValidatableMessage`. Real generated builders always produce a `ValidatableMessage`, so this branch cannot be reached from the `tests/validating` spec; exercise it here with a minimal builder that delegates to a plain `Empty` product. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Extend the `jvm-runtime` unit spec so the `validate()` default method is exercised for all three products it can encounter: a `ValidatableMessage` that is valid, one that reports violations, and a message that does not support validation. The builder stub now takes an arbitrary product, and a minimal `ValidatableMessage` stub reports the configured violations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… into claude/wonderful-hellman-f8ec72
- `runtime-library.md`: state that `validate()` treats a product that does not implement `ValidatableMessage` as valid, matching the interface Javadoc and the unit tests. - `ValidateUtilitySpec.kt`: bump the copyright header to 2026 for a file edited on this branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace restrictive `which` clauses (no preceding comma) with `that` in the interface Javadoc, per the repo grammar convention. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
armiol
approved these changes
Jul 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a default probe method to
io.spine.validation.ValidatingBuilder:It builds the current content via
buildPartial()and, when the result is aValidatableMessage, unwraps itsOptional<ValidationError>into the returnedlist; a message that does not support validation is treated as valid. An empty
list means the content is valid.
The method is a non-throwing, non-mutating probe of the builder's current
content — including content that is already invalid. It sits between the two
existing options:
build()ValidationExceptionbuildPartial()validate()(new)Why
Complements the
tryAlter {}entity extension designed in core-jvmPR #1642
(de-event-sourcing Phase A), which needs to check a builder's content for
validity in place without either throwing or handing back a message. Implements
the D9 amendment of ADR 0001. Requested by @armiol in
SpineEventEngine/core-jvm#1642 (comment)
How it works
The generated
ValidatableMessage.validate(parentPath, parentName)alreadyfolds in
ValidatorRegistry.validate(this), sobuildPartial()+ValidatableMessage.validate()checks exactly what generatedbuild()checks —no more, no less. It deliberately does not route through
Validate.violationsOf(), which addsAny-unpacking logic irrelevant to abuilder.
Tests
ValidatingBuilderSpec(jvm-runtime) — unit specs with minimal stubscovering every branch of
validate(): a validValidatableMessage→ emptylist; an invalid one → violations returned without throwing; a product that
does not implement
ValidatableMessage→ treated as valid.ValidatingBuilderSpec(tests/validating) — the same valid/invalid pathsagainst the real generated
InterestRatebuilder (a(min)constraint),plus a check that probing leaves the builder content intact.
JavaMessageSmokeTest(tests/validating) — smoke coverage forvalidate()on the generated
CardNumberbuilder.Notes for reviewers
2.0.0-SNAPSHOT.446 → .447;docs/dependencies/*are theregenerated reports (version/timestamp churn only).
runtime-library.md, which mirrors the interfacebody, is updated to include the new method.
docs/content/**was touched but no links were added or changed, socheck-linkshas no bearing on this diff.Bundled maintenance
Beyond the
validate()change, this branch also carries routine SDKmaintenance the author chose to keep together rather than split out:
2.0.0-SNAPSHOT.391) and CoreJvmcompiler (
2.0.0-SNAPSHOT.080), Protobuf4.35.0, Gradle wrapper9.6.1..agents/restructure, refreshed dependency reports, andtwo new CI workflows (
revalidate-versions,secret-scan).hello-validationdocs submodule(
docs/_examples) is advanced to force Protobuf4.35.0, matching themigrated compiler's gencode; this fixes the
Build embedded codecheck.Verification: full
./gradlew buildpasses;:docs:buildExamples(embedded-code) passes after the submodule alignment; the version-increment
guard and remaining CI checks are green.
🤖 Generated with Claude Code