I often use constraints on fields in spring . The constraint are standard or custom
public abstract class OrganizationEntity {
@Length(min = 1 , max = 256, message = "Organization name max length is 256 and min length is 1")
@NotNull(message = "Organization name should not be empty")
@Pattern(regexp = "^[a-zA-Z0-9][-a-zA-Z0-9] [a-zA-Z0-9]$",message = "Organization name can contain Alphanumeric character and Hyphen in the middle")
public abstract String getName();
}
On navigating to Length or Pattern annotation I see the definition of annotation org.hibernate.validator.constraints
@Documented
@Constraint(
validatedBy = {}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(List.class)
public @interface Length {
int min() default 0;
int max() default Integer.MAX_VALUE;
String message() default "{org.hibernate.validator.constraints.Length.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface List {
Length[] value();
}
}
I see validatedBy is left empty which implies there is somebody mechanism/library which has implementation for these checks. Which library provides these implementation? How does spring manage this validation flow.
CodePudding user response:
Hibernate provides the validation implementation and it is used by Spring.
I may be oversimplifying, but as I understand Spring configures Hibernate's ValidationFactory
implementation (ValidationFactoryImpl
) with Validator
and ExecutableValidator
implementation (ValidatorImpl
) for Spring's application context usage, exposes it for other Spring components and convert validation results into BindingResult
.
At the same time, Hibernate's ValidatorImpl
uses validation context, in which ConstraintValidator
s are registered as a map with different annotations from package javax.validation.constraints
as keys, along with Hibernate's own constraints, such as @URL
and @ISBN
. This map can be found in the ConstraintHelper
class.
For example, you can find PatternValidator
registered there for validating values annotated with @Pattern
.
Then we have the next Hibernate validation flow (again - simplified):
ValidatorImpl
tries to validate something and createsMetaConstraint
s (helper class with all information needed for validation);MetaConstraint
createsConstraintTree
for multiple constraints check;ConstraintTree
callsConstraintValidatorManager
and itsgetInitializedValidator
method, which returns neededConstraintValidator
for a specific annotation from a map, mentioned before.
So the validation framework, used by Spring, already knows which ConstraintValidator
instances to use for specific validation annotations.