diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 312610353e..cc61f4e00d 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -901,4 +901,4 @@
-
\ No newline at end of file
+
diff --git a/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt b/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt
index fa3956f1f8..327c6114d7 100644
--- a/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt
+++ b/buildSrc/src/main/kotlin/io/spine/dependency/local/Validation.kt
@@ -36,7 +36,7 @@ object Validation {
/**
* The version of the Validation library artifacts.
*/
- const val version = "2.0.0-SNAPSHOT.404"
+ const val version = "2.0.0-SNAPSHOT.405"
/**
* The last version of Validation compatible with ProtoData.
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt b/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt
index c0651fa769..5e3c892235 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/kotlin/KotlinConfig.kt
@@ -27,10 +27,10 @@
package io.spine.gradle.kotlin
import org.gradle.jvm.toolchain.JavaLanguageVersion
+import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
-import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode
/**
* Sets [Java toolchain](https://kotlinlang.org/docs/gradle.html#gradle-java-toolchains-support)
diff --git a/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt b/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt
index df02697b14..75af960e23 100644
--- a/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt
+++ b/buildSrc/src/main/kotlin/io/spine/gradle/testing/Logging.kt
@@ -79,10 +79,6 @@ fun Test.configureLogging() {
logger.lifecycle(result.summary())
}
}
-
- override fun beforeSuite(suite: TestDescriptor?) = Unit
- override fun beforeTest(testDescriptor: TestDescriptor?) = Unit
- override fun afterTest(testDescriptor: TestDescriptor?, result: TestResult?) = Unit
}
addTestListener(listener)
diff --git a/config b/config
index 0bca88448a..21366d370b 160000
--- a/config
+++ b/config
@@ -1 +1 @@
-Subproject commit 0bca88448a18cde81f83ead25dfbd36a364aa7c0
+Subproject commit 21366d370b26c28690a42b313c172d6dbb4f4d36
diff --git a/dependencies.md b/dependencies.md
index 79491000b0..762e0e5328 100644
--- a/dependencies.md
+++ b/dependencies.md
@@ -1,6 +1,6 @@
-# Dependencies of `io.spine.tools:validation-context:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-context:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -1139,14 +1139,14 @@
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-context-tests:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-context-tests:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -1743,28 +1743,28 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-docs:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-docs:2.0.0-SNAPSHOT.406`
## Runtime
## Compile, tests, and tooling
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:29 WET 2026** using
+This report was generated on **Mon Mar 23 16:41:13 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-gradle-plugin:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-gradle-plugin:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -2881,14 +2881,14 @@ This report was generated on **Thu Mar 12 21:14:29 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-java:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-java:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -3967,14 +3967,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-java-bundle:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-java-bundle:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : org.jetbrains. **Name** : annotations. **Version** : 13.0.
@@ -4021,14 +4021,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:42 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine:validation-jvm-runtime:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine:validation-jvm-runtime:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -4861,14 +4861,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-consumer:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-consumer:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -5455,14 +5455,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:42 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-consumer-dependency:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-consumer-dependency:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -5985,14 +5985,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-extensions:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-extensions:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -6684,14 +6684,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-runtime:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-runtime:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -7329,14 +7329,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-validating:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-validating:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -8013,14 +8013,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-validator:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-validator:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0.
@@ -8807,14 +8807,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-validator-dependency:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-validator-dependency:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -9088,14 +9088,14 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:43 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
-# Dependencies of `io.spine.tools:validation-vanilla:2.0.0-SNAPSHOT.405`
+# Dependencies of `io.spine.tools:validation-vanilla:2.0.0-SNAPSHOT.406`
## Runtime
1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2.
@@ -9442,6 +9442,6 @@ This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
The dependencies distributed under several licenses, are used according their commercial-use-friendly license.
-This report was generated on **Thu Mar 12 21:14:30 WET 2026** using
+This report was generated on **Mon Mar 23 17:45:42 WET 2026** using
[Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under
[Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE).
\ No newline at end of file
diff --git a/docs/_bin/embed-code-linux b/docs/_bin/embed-code-linux
new file mode 100755
index 0000000000..49d4dbb840
Binary files /dev/null and b/docs/_bin/embed-code-linux differ
diff --git a/docs/_bin/embed-code-macos b/docs/_bin/embed-code-macos
index 035be58649..dd5dde24d6 100755
Binary files a/docs/_bin/embed-code-macos and b/docs/_bin/embed-code-macos differ
diff --git a/docs/_bin/embed-code-macos-x86_64 b/docs/_bin/embed-code-macos-x86_64
deleted file mode 100755
index 5e2577c6d7..0000000000
Binary files a/docs/_bin/embed-code-macos-x86_64 and /dev/null differ
diff --git a/docs/_bin/embed-code-ubuntu b/docs/_bin/embed-code-ubuntu
deleted file mode 100755
index ca362fe444..0000000000
Binary files a/docs/_bin/embed-code-ubuntu and /dev/null differ
diff --git a/docs/_bin/embed-code-windows.exe b/docs/_bin/embed-code-windows.exe
new file mode 100755
index 0000000000..1065d78799
Binary files /dev/null and b/docs/_bin/embed-code-windows.exe differ
diff --git a/docs/_examples b/docs/_examples
index 774c08ce1b..67342d3fa4 160000
--- a/docs/_examples
+++ b/docs/_examples
@@ -1 +1 @@
-Subproject commit 774c08ce1bb8da49fd97319cad632c5a93cdde45
+Subproject commit 67342d3fa4ef7028c1f3bda9569daf21a1b972b8
diff --git a/docs/_script/check-samples b/docs/_script/check-samples
index 2277c7c4a9..b7b42da5cc 100755
--- a/docs/_script/check-samples
+++ b/docs/_script/check-samples
@@ -17,10 +17,10 @@ fi
# Navigate to the folder with embed-code binaries.
cd _bin
-# Use the Ubuntu binary for GitHub Actions and macOS binary in other cases.
+# Use the Linux binary for GitHub Actions and macOS binary in other cases.
if [ "$GITHUB_ACTIONS" = "true" ]; then
echo "Running in GitHub Action."
- TOOL="./embed-code-ubuntu"
+ TOOL="./embed-code-linux"
else
echo "Running locally on macOS."
TOOL="./embed-code-macos"
diff --git a/docs/_settings/embed-code.yml b/docs/_settings/embed-code.yml
index 170b024569..71da18049e 100644
--- a/docs/_settings/embed-code.yml
+++ b/docs/_settings/embed-code.yml
@@ -1,5 +1,6 @@
-code-path: "../_examples"
+code-path:
+ - name: "examples"
+ path: "../_examples"
+ - name: "runtime"
+ path: "../../jvm-runtime"
docs-path: "../content/docs/"
-embed-mappings:
- - code-path: "../_examples"
- docs-path: "../content/docs/"
diff --git a/docs/content/docs/validation/01-getting-started/adding-to-build.md b/docs/content/docs/validation/01-getting-started/adding-to-build.md
index 65bc949a64..747a186998 100644
--- a/docs/content/docs/validation/01-getting-started/adding-to-build.md
+++ b/docs/content/docs/validation/01-getting-started/adding-to-build.md
@@ -8,7 +8,11 @@ headline: Documentation
## Adding Spine-specific Gradle plugin repositories
-
+
+
```kotlin
pluginManagement {
repositories {
@@ -78,11 +82,15 @@ Use this mode if you want to run Validation without the rest of Spine.
Add the Validation plugin to the build.
-
+
+
```kotlin
plugins {
module
- id("io.spine.validation") version "2.0.0-SNAPSHOT.404"
+ id("io.spine.validation") version "2.0.0-SNAPSHOT.406"
}
```
@@ -104,11 +112,15 @@ the JVM runtime dependency automatically.
If your project is based on the Spine CoreJvm library, apply the CoreJvm Gradle plugin instead of
adding Validation directly. CoreJvm brings in the Validation Gradle plugin for you.
-
+
+
```kotlin
plugins {
module
- id("io.spine.core-jvm") version "2.0.0-SNAPSHOT.054"
+ id("io.spine.core-jvm") version "2.0.0-SNAPSHOT.055"
}
```
diff --git a/docs/content/docs/validation/01-getting-started/first-model.md b/docs/content/docs/validation/01-getting-started/first-model.md
index 467d9c4b49..432ff32f94 100644
--- a/docs/content/docs/validation/01-getting-started/first-model.md
+++ b/docs/content/docs/validation/01-getting-started/first-model.md
@@ -16,7 +16,11 @@ The validation options come from `spine/options.proto` and include constraints l
Create a `.proto` file and import `spine/options.proto`:
-
+
+
```protobuf
syntax = "proto3";
diff --git a/docs/content/docs/validation/01-getting-started/generated-code.md b/docs/content/docs/validation/01-getting-started/generated-code.md
index de12426c25..ce767b0786 100644
--- a/docs/content/docs/validation/01-getting-started/generated-code.md
+++ b/docs/content/docs/validation/01-getting-started/generated-code.md
@@ -18,7 +18,10 @@ When a message violates declared constraints, `build()` throws `ValidationExcept
{{< code-tabs langs="Kotlin, Java">}}
{{< code-tab lang="Kotlin" >}}
-
+
+
```kotlin
shouldThrow {
// Kotlin proto DSL delegates to a Java builder.
@@ -31,7 +34,10 @@ shouldThrow {
{{< /code-tab >}}
{{< code-tab lang="Java" >}}
-
+
+
```java
assertThrows(ValidationException.class, () ->
BankCard.newBuilder()
@@ -51,7 +57,10 @@ and call `validate()`:
{{< code-tabs langs="Kotlin, Java">}}
{{< code-tab lang="Kotlin" >}}
-
+
+
```kotlin
// There is no Kotlin DSL which allows building a non-valid message.
// So we use a builder from Java.
@@ -71,7 +80,10 @@ formatted shouldContain "wrong number"
{{< /code-tab >}}
{{< code-tab lang="Java" >}}
-
+
+
```java
var card = BankCard.newBuilder()
.setOwner("ALEX SMITH")
diff --git a/docs/content/docs/validation/04-validators/_index.md b/docs/content/docs/validation/04-validators/_index.md
index 541e027f90..e7bb17d412 100644
--- a/docs/content/docs/validation/04-validators/_index.md
+++ b/docs/content/docs/validation/04-validators/_index.md
@@ -13,8 +13,10 @@ Sometimes this is not enough, or not possible.
Use validators when you need **custom logic in code**:
-- validate **external** message types whose `.proto` files you cannot change (e.g. `google.protobuf.Timestamp`);
-- validate **local** messages when the rule requires computation and cannot be expressed as proto options.
+- validate **external** message types whose `.proto` files you cannot change
+ (e.g. `google.protobuf.Timestamp`);
+- validate **local** messages when the rule requires computation and cannot be
+ expressed as proto options.
Validators are implemented via `io.spine.validation.MessageValidator` and executed by
`io.spine.validation.ValidatorRegistry`.
diff --git a/docs/content/docs/validation/04-validators/implement-a-validator.md b/docs/content/docs/validation/04-validators/implement-a-validator.md
index 44b65dfb17..0ae1f65e3b 100644
--- a/docs/content/docs/validation/04-validators/implement-a-validator.md
+++ b/docs/content/docs/validation/04-validators/implement-a-validator.md
@@ -46,15 +46,12 @@ The core logic is intentionally small: it first delegates to `Timestamps.isValid
if invalid, adds a field-specific violation for each invalid field (`seconds` and/or `nanos`).
For range checks, it relies on `Timestamps.MIN_VALUE` and `Timestamps.MAX_VALUE`.
+
+
```kotlin
-import com.google.auto.service.AutoService
-import com.google.protobuf.Timestamp
-import com.google.protobuf.util.Timestamps
-import com.google.protobuf.util.Timestamps.MAX_VALUE
-import com.google.protobuf.util.Timestamps.MIN_VALUE
-import io.spine.validation.DetectedViolation
-import io.spine.validation.MessageValidator
-
@AutoService(MessageValidator::class)
public class TimestampValidator : MessageValidator {
@@ -75,11 +72,16 @@ public class TimestampValidator : MessageValidator {
}
```
+{{% note-block class="note" %}}
+The code snippet above omits import statements and helper functions for brevity.
+You can find the full implementation [via GitHub][TimestampValidator].
+{{% /note-block %}}
+
### Reporting violations with placeholders
`TimestampValidator` reports errors via `FieldViolation`, providing:
-- `fieldPath` — which field is invalid (for example, `"seconds"`),
+- `fieldPath` — which field is invalid, for example, `"seconds"`,
- `fieldValue` — the actual invalid value, and
- `message` — a `TemplateString` with placeholders and a placeholder-to-value map.
@@ -90,8 +92,7 @@ formatting, logging, and customization.
When violations are converted to regular `ConstraintViolation`s, Spine Validation also populates
the `validator` placeholder with the fully qualified class name of the validator.
-Below is the helper that creates a violation for invalid `seconds`
-(the `invalidNanos()` function is similar):
+Below is the helper that creates a violation for invalid `seconds`.
```kotlin
private fun invalidSeconds(seconds: Long): FieldViolation = FieldViolation(
@@ -110,6 +111,7 @@ private fun invalidSeconds(seconds: Long): FieldViolation = FieldViolation(
fieldValue = seconds
)
```
+The `invalidNanos()` function is similar.
## Walkthrough: validate a nested message field
@@ -136,3 +138,6 @@ to the nested field in error (for example, to `starts_at.seconds`).
- [Using `ValidatorRegistry`](validator-registry.md)
- [Custom validation](../08-custom-validation/)
- [Architecture](../09-developers-guide/architecture.md)
+
+
+[TimestampValidator]: https://github.com/SpineEventEngine/validation/blob/master/jvm-runtime/src/main/kotlin/io/spine/validation/TimestampValidator.kt
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 61285a659d..d997cfc60f 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 37f78a6af8..dbc3ce4a04 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index 2fa0b7c0bd..d992737997 100755
--- a/gradlew
+++ b/gradlew
@@ -60,7 +60,7 @@ export TEMPORARILY_DISABLE_PROTOBUF_VERSION_CHECK=true
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# https://github.com/gradle/gradle/blob/b631911858264c0b6e4d6603d677ff5218766cee/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
diff --git a/jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java b/jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java
index e2a8de9ec5..e26c7a13d8 100644
--- a/jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java
+++ b/jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java
@@ -63,10 +63,10 @@ default Optional validate() {
* does not make sense. Both must either be provided or omitted together.
*
* @param parentPath
- * the path to the parent field that initiated in-depth validation.
+ * The path to the parent field that initiated in-depth validation.
* Can be the default instance, which means no parent path.
* @param parentName
- * the name of the parent type that initiated in-depth validation
+ * The name of the parent type that initiated in-depth validation
* Can be {@code null}, which means no parent name.
*
* @return an error or {@link Optional#empty()} if no violations found
diff --git a/jvm-runtime/src/main/kotlin/io/spine/validation/MessageValidator.kt b/jvm-runtime/src/main/kotlin/io/spine/validation/MessageValidator.kt
index d4ee9b8983..cc8b59aa4a 100644
--- a/jvm-runtime/src/main/kotlin/io/spine/validation/MessageValidator.kt
+++ b/jvm-runtime/src/main/kotlin/io/spine/validation/MessageValidator.kt
@@ -30,37 +30,33 @@ import com.google.protobuf.Message
import io.spine.annotation.SPI
/**
- * A validator for an external Protobuf message of type [M].
+ * A validator for a Protobuf message of type [M].
*
- * This interface enforces validation rules for `Message`s whose Java/Kotlin classes
- * are already generated by third parties, in case they are used in the Protobuf
- * codebase to which the Validation library is applied.
+ * ## Local and external messages
*
- * ## Problem
- *
- * Java/Kotlin libraries that use Protobuf messages often distribute both the `.proto`
- * definitions and the compiled class files (`.class`) for these messages.
- * As these classes are pre-generated, consumers cannot modify their underlying
- * `.proto` files to define validation constraints and the Validation library
- * cannot use code generation to enforce the constraints.
- *
- * Thus, the library effectively deals with the two types of messages:
- *
- * 1. **Local messages** are message types for which end-users generate and control
+ * 1. **Local messages** are the types for which end-users generate and control
* the Java/Kotlin classes by compiling the corresponding `.proto` definitions
* within their own codebase. For such messages, the Validation library allows
* declaring validation constraints and enforces them with the generated code.
*
- * 2. **External messages** are message types for which end-users do not generate or control
+ * 2. **External messages** are the types for which end-users do not generate or control
* the Java/Kotlin classes. Because the classes are already generated, users cannot modify
* the underlying `.proto` definitions and add validation options at compile time.
*
+ * Both local and external messages can be checked using classes implementing this interface.
+ *
+ * ## Applying `MessageValidator` to local messages
+ *
+ * If built-in or custom validation options are not sufficient, you can implement
+ * this interface to enforce additional validation rules for local messages.
+ *
+ * The validator will be applied after the validation of the built-in and custom options in
+ * the [generated code][ValidatableMessage.validate].
+ *
* ## Validation of external messages
*
* The Validation library provides a mechanism that allows validating of
* the external messages, **which are used for fields within local messages**.
- * Implement this interface and ensure the implementation is discoverable
- * by [ServiceLoader][java.util.ServiceLoader].
*
* For each field of type [M] within any local message, the library will invoke
* the [MessageValidator.validate] method when validating the local message.
@@ -101,16 +97,12 @@ import io.spine.annotation.SPI
*
* Supposing that the Validation library applied to the module where both `WorkingSetup`
* and `EarphonesValidator` classes are declared, then the generated code of `WorkingSetup`
- * will apple the validator to each instance passed to the `WorkingSetup.earphones` field.
+ * will apply the validator to each instance passed to the `WorkingSetup.earphones` field.
*
- * Please note that the following use cases are NOT supported and will lead to an error:
+ * ## Multiple validators for the same message type
*
- * 1) Declaring a validator for a local message is prohibited. Only external messages are
- * allowed to have a validator. Use built-in or custom validation options to declare
- * constraints for local messages.
- * 2) Declaring multiple validators for the same message type is prohibited. The library
- * scans the module’s classpath to discover validators, and expects exactly one validator
- * per message type.
+ * It is possible to declare more than one validator for the same message type.
+ * The order in which they are applied to a message type is not guaranteed.
*
* ## Implementation
*
@@ -123,10 +115,14 @@ import io.spine.annotation.SPI
* a [ConstraintViolation][ConstraintViolation].
* Returning of an empty list of violations means that the given message is valid.
*
- * Keep in mind that for each invocation a new instance of [MessageValidator] is created.
+ * ## Automatic discovery
+ *
* Every implementation of [MessageValidator] must have a public, no-args constructor.
*
- * @param M the type of Protobuf [Message][Message] being validated.
+ * To make the validator used from the generated code, ensure the implementation is
+ * discoverable by [ServiceLoader][java.util.ServiceLoader].
+ *
+ * @param M the type of Protobuf [Message] being validated.
*
* @see ValidatorRegistry
*/
diff --git a/pom.xml b/pom.xml
index be758412cf..0b4610014b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject.
-->
io.spine.tools
validation
-2.0.0-SNAPSHOT.405
+2.0.0-SNAPSHOT.406
2015
@@ -62,7 +62,7 @@ all modules and does not describe the project structure per-subproject.
io.spine
spine-validation-jvm-runtime
- 2.0.0-SNAPSHOT.404
+ 2.0.0-SNAPSHOT.405
compile
@@ -289,7 +289,7 @@ all modules and does not describe the project structure per-subproject.
io.spine.tools
validation-java-bundle
- 2.0.0-SNAPSHOT.404
+ 2.0.0-SNAPSHOT.405
net.sourceforge.pmd
diff --git a/version.gradle.kts b/version.gradle.kts
index 470663c085..711f4c9125 100644
--- a/version.gradle.kts
+++ b/version.gradle.kts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, TeamDev. All rights reserved.
+ * Copyright 2026, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,4 +29,4 @@
*
* For Spine-based dependencies please see [io.spine.dependency.local.Spine].
*/
-val validationVersion by extra("2.0.0-SNAPSHOT.405")
+val validationVersion by extra("2.0.0-SNAPSHOT.406")