Support multiple validators, add "Using Validators" section#275
Support multiple validators, add "Using Validators" section#275alexander-yevsyukov merged 81 commits intomasterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds documentation and runtime support for validating third-party (external) Protobuf messages via MessageValidator implementations, using google.protobuf.Timestamp as an example.
Changes:
- Bumped Validation plugin/dependency snapshot version to
2.0.0-SNAPSHOT.401. - Added
TimestampValidator+ corresponding unit tests. - Added a new documentation page describing external message validation and updated docs/examples references.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| version.gradle.kts | Bumps the Validation dependency version used by the build. |
| jvm-runtime/src/main/kotlin/io/spine/validation/TimestampValidator.kt | Introduces an external validator for google.protobuf.Timestamp. |
| jvm-runtime/src/test/kotlin/io/spine/validation/TimestampValidatorSpec.kt | Adds tests for TimestampValidator behavior and violation formatting. |
| jvm-runtime/src/main/kotlin/io/spine/validation/Validator.kt | Updates KDoc and copyright year. |
| docs/content/docs/validation/04-third-party-messages/_index.md | Adds documentation section explaining external validators and usage. |
| docs/content/docs/validation/01-getting-started/adding-to-build.md | Updates the plugin version shown in setup instructions. |
| docs/_examples | Updates docs examples submodule pointer. |
| .agents/tasks/third-party-messages-plan.md | Adjusts the documentation plan to use TimestampValidator and new placement. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jvm-runtime/src/main/kotlin/io/spine/validation/TimestampValidator.kt
Outdated
Show resolved
Hide resolved
jvm-runtime/src/test/kotlin/io/spine/validation/TimestampValidatorSpec.kt
Show resolved
Hide resolved
jvm-runtime/src/test/kotlin/io/spine/validation/TimestampValidatorSpec.kt
Show resolved
Hide resolved
…xternal messages"
Also: * Add `qualified` property to improve readability of strings.
…try.kt Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 51 out of 53 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (4)
jvm-runtime/src/main/kotlin/io/spine/validation/ValidatorRegistry.kt:1
- Correct the typo “kep” → “key”.
jvm-runtime/src/main/kotlin/io/spine/validation/ValidatorRegistry.kt:1 - The KDoc says “a list of validators”, but the implementation stores a
MutableSet<MessageValidator<*>>. Please update the documentation to reflect set semantics (e.g., uniqueness, no ordering), or change the type to a list if ordering/duplicates are intended.
jvm-runtime/src/test/kotlin/io/spine/validation/ValidatorRegistrySpec.kt:1 - This test relies on reflective access to a private method, which is brittle (renames/visibility changes won’t be caught by the compiler) and can fail under stricter runtime settings. Prefer exposing a test-only entry point (e.g., an
internalmethod annotated with@VisibleForTesting, or injecting aServiceLoader/loader function) so tests can trigger reload without reflection.
jvm-runtime/src/main/kotlin/io/spine/validation/ValidatorRegistry.kt:1 - The overload
validate(message, parentPath, parentName)is newly introduced and is the one used by generated code for nested-field validation, but the added tests exercise the simplervalidate(message)path. Please add coverage that asserts correct propagation/merging ofparentPathandparentNameinto producedConstraintViolations (including the nested-field path concatenation behavior).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b00cdb6606
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
java/src/main/kotlin/io/spine/tools/validation/java/generate/option/ValidateGenerator.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 51 out of 53 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
jvm-runtime/src/main/kotlin/io/spine/validation/ValidatorRegistry.kt:1
cls.qualifiedNameis nullable (String?), but the map key type is non-nullString, so this call should not compile (and/or may behave incorrectly). Use a non-null key consistently (e.g.,cls.qualifiedName!!if guaranteed, or prefercls.java.name/cls.qualifiedOrThrow()-style helper) to match how keys are written inadd()/get().
tests/validating/src/test/kotlin/io/spine/test/options/ValidateITest.kt:1- The test name says “accept”, but the assertion now expects
UnknownTypeException(i.e., rejection). Rename the test to reflect the new behavior (similar to the other two renamed tests in this file) to keep intent clear.
jvm-runtime/src/test/kotlin/io/spine/validation/ValidatorRegistrySpec.kt:1 ValidatorRegistry.get()returns aSet, and the iteration order of the underlying concurrent set is not guaranteed.shouldContainExactlyis order-sensitive for iterables and may lead to flaky tests. Prefer an order-insensitive assertion (e.g., “contains exactly in any order”, or assert size +containsAll).
jvm-runtime/src/test/kotlin/io/spine/validation/ValidatorRegistrySpec.kt:1- Exceptions thrown inside
executor.execute { ... }won’t fail the test thread, soassertDoesNotThrowhere won’t reliably detect concurrency issues. Consider usingsubmit()+ collectingFutures and callingget()(or capturing uncaught exceptions), and assertawaitTermination(...)returnstrueto ensure all tasks actually completed.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 51 out of 53 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
jvm-runtime/src/test/kotlin/io/spine/validation/TimestampValidatorSpec.kt:1
- The expected
withPlaceholdersstring for the nanos violation is inconsistent with the template produced byTimestampValidator.invalidNanos()(it includes parentheses around the placeholder key). As written, this assertion is very likely to fail. Align either the validator message template or the test expectation so the placeholder formatting matches exactly (ideally keep the same pattern as the seconds-range message: include the range placeholder in parentheses and a: valuesuffix).
jvm-runtime/src/main/kotlin/io/spine/validation/ValidatorRegistry.kt:1 - The registry uses
ConcurrentHashMapplus a concurrent set, but still synchronizes onthisforadd/remove/clear. This adds global contention and largely defeats the benefit of concurrent structures, whilevalidate()reads without synchronization anyway. Prefer relying on the atomicity ofConcurrentHashMap.computeand the thread-safety of the backing set (i.e., remove thesynchronizedblocks), or switch to a consistent read/write locking strategy acrossadd/remove/clear/validate.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This PR updates the code generation so that multiple
Validators are used for validating fields as long as whole message classes.ValidatorRegistrywas introduced for keeping the association between a message class name and associated validator instances.The validators are automatically discovered using the
ServiceLoadermechanism of Java.Validators in the generated code are invoked after the option-based validation occurs.
Documentation was extended accordingly.