Spring MVC form validation
-
Bean validation features
-
required
length
numbers
regular expressions
-
custom validation
-
Hibernate validator
@InitBinder
: Apply text pre-processing for request coming to the controller
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.6.Final</version>
</dependency>
public class Customer {
private String firstName;
@NotNull(message="must not be null")
@Size(min=3, message="not long enough")
private String lastName;
@NotNull(message="is required")
@Min(value=0, message="must be equal or greater than zero")
@Max(value=10, message="must be equal or less than ten")
private Integer freePasses; // if the type is 'int', initBinder will trim it to string 'null'
@Pattern(regexp = "^[a-zA-Z0-9]{5}", message = "only 5 chars/digits")
private String postalCode;
}
@RequestMapping("/processForm")
public String processForm(
@Valid @ModelAttribute("customer") Customer theCustomer, // Populate theCustomer object coming from the request
BindingResult theBindingResult) {// REsult of the validation. MUST come after the @valid
System.out.printf("Last name: |" + theCustomer.getLastName()+ "|");
System.out.println("Binding result: " + theBindingResult);
System.out.println("\n\n\n\n");
if (theBindingResult.hasErrors()) {
return "customer-form";
} else {
return "customer-confirmation";
}
}
Custom validation rule
- Create a new annotation
@Constraint(validatedBy = CourseCodeConstraintValidator.class) // Class with the business logic for the validator
@Target( {ElementType.METHOD, ElementType.FIELD} ) // Where to apply this annotation: Methods and Fields
@Retention(RetentionPolicy.RUNTIME) // How long the annotation will be stored/used. Retain at source code and use at runtime by the JVM
public @interface CourseCode {
// default value
public String[] value() default {"LUV"}; // Validate against an array of strings
// default message (for errors)
public String message() default "must start with LUV";
// default groups
public Class<?>[] groups() default {};
// default payloads
public Class<? extends Payload>[] payload() default {};
}
- CourseCodeConstraintValidator.class
public class CourseCodeConstraintValidator implements ConstraintValidator<CourseCode, String> { // ConstraintValidator is a interface from javax.validation pkg
private String[] coursePrefixes;
@Override
public void initialize(CourseCode theCourseCode) {
coursePrefixes = theCourseCode.value(); // The value of the annotation
}
@Override
public boolean isValid(String theCode, ConstraintValidatorContext theConstraintValidatorContext) {
boolean result = false; // do not validate by default
if (theCode != null) {
//
// loop thru course prefixes
//
// check to see if code matches any of the course prefixes
//
for (String tempPrefix : coursePrefixes) {
result = theCode.startsWith(tempPrefix);
// if we found a match then break out of the loop
if (result) break;
}
} else {
result = true; // If nothing is passed, just pass it (nothing to validate)
}
return result;
}
}
@CourseCode // @CourseCode(value={"TOPS", "LUV"}, message="must start with LUV") is the default
private String courseCode;