Issue
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.
Solution
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.
Answered By - AndrewThomas
Answer Checked By - Willingham (JavaFixing Volunteer)