Skip to content

Conversation

tomas-langer
Copy link
Member

@tomas-langer tomas-langer commented Oct 8, 2025

Resolves #10735

validation/tests/validation/src/test/java/io/helidon/validation/tests/validation/ValidationTest.java
and
validation/tests/validation/src/test/java/io/helidon/validation/tests/validation/ValidatorTest.java
for usage (not really examples, but what I am testing right now)

Declarative Validation

Validation provides capabilities to validate types and method parameters/return values.
Both features require code-generation.

Type validation code-generation of type validators is triggered by the presence of the @Validation.Validated annotation on a type.

Method validation code-generation of interceptors is triggered by the presence of an annotation "meta-annotated"
with @Validation.Constraint on a method, its parameter, or type arguments of its parameters or return type.
In addition the Check.Valid annotation also triggers code-generation, and can be used to validate against a type validator
mentioned above.

Declaration

Annotations:

  • Most annotations from io.helidon.validation.Validation class to trigger validation using an interceptor (all meta-annotated with @Validation.Constraint)
  • @Validation.Validated - on a type to generate type validator for a type

Configuration

There is currently no configuration for validation.

Implementation

Each constraint has a dedicated validator provider service, with (default-weight - 30) weight.
The providers are annotated with a named annotation that matches the constraint annotation.

This allows our users to override the implementation using their custom services.

The validation process works as follows:

  1. an interceptor is generated for any method that has constraint annotations or valid annotation
  2. the interceptor obtains all constraint validation instances and type validators needed to validate a call
  3. the interceptor validates the call and throws a ValidationException if validation fails

The type validation works as follows:

  1. a type validator is generated for any type that has a @Validation.Validated annotation
  2. the type validator obtains all constraint validation instances and type validators needed to validate an instance
  3. the type validator validates the type and returns response with possible constraint violations

Important types:

  • Validation - a container class for validation annotations
  • ValidationException - throws when validation fails in an interceptor
  • Validator - programmatic API to validate instances and their properties (only for validated types), can be obtained from service registry
  • ConstraintValidatorProvider - service registry service that validates a single constraint annotation type
  • ConstraintValidator - created for each annotated element using the type of the element and the constraint annotation
  • validators package contains built-in constraint validator providers

Supported concepts:

  • any service method annotated with a constraint annotation will be intercepted and validated
  • any service method that has parameters with at least one constraint annotation will be intercepted and validated
  • for identification of "what to validate", @Validation.Valid is a constraint annotation
  • annotations on type arguments of method parameters and method return type are supported, as long as they are on
    Optional, Map, Collection - i.e. List<@Validation.String.NotBlank String> will trigger an interceptor and will be validated
  • types annotated with @Validation.Validated will be validated when used in a method or constructor that uses @Validation.Valid on the typed parameter
  • same rules as for generation of interceptors apply for type validation: constraints are honored, including getters,
    fields, and type arguments
  • a user may create a "compound annotation" - an annotation that has one or more constraint annotations, these will be honored as
    if the element was directly annotated with the constraints
  • a user may create a custom constraint annotation (annotation meta-annotated with @Validation.Constraint), such annotations
    may also be meta-annotated with additional constraints; a custom constraint annotation requires a custom validator provider

@oracle-contributor-agreement oracle-contributor-agreement bot added the OCA Verified All contributors have signed the Oracle Contributor Agreement. label Oct 8, 2025
@tomas-langer tomas-langer self-assigned this Oct 8, 2025
@tomas-langer tomas-langer added bean validation 4.x Version 4.x declarative Helidon Declarative labels Oct 8, 2025
@tomas-langer tomas-langer added this to the 4.4.0 milestone Oct 8, 2025
@tomas-langer tomas-langer marked this pull request as ready for review October 8, 2025 17:05
propertyName = propertyName.substring(3);
if (propertyName.length() == 1) {
propertyName = propertyName.toLowerCase(Locale.ROOT);
} else if (!Character.isUpperCase(propertyName.charAt(1))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a mistake. You wanted the character at the index 0, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if you add the check for the 4tch character to be upper case as I wrote before, this check would be redundant :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not redundant, nor is it a mistake - this is for cases such as getADSL - we want to keep all capital...

New module, fixes to codegen to support all required features (such as annotations on type declaration)
passes tests, checkstyle, spotbugs and copyright
Removed as much as possible that can be hidden in the implementation from the public API.
Added module to error handle validation exception into a bad request status code
@tomas-langer
Copy link
Member Author

Examples of generated files:

  • ValidatedType__Validated - for a validated record
  • ValidatedService__ValidationInterceptor_1 - for an intercepted method that has bot constraints and a validated type

ValidatedType__Validated.java
ValidatedService__ValidationInterceptor_1.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.x Version 4.x bean validation declarative Helidon Declarative OCA Verified All contributors have signed the Oracle Contributor Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Declarative Validation

2 participants