0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spring MVC: Controller level model binding validation

Posted at

To perform model binding validation of controller, one of the solution is register validator on controller.

#1. Write your own validator

You validator should extend org.springframework.validation.Validator interface. Below is a example.

public class MessageDtoValidator implements Validator {

	@Override
	public boolean supports(Class<?> clazz) {
		return MessageDto.class.isAssignableFrom(clazz);
	}

	@Override
	public void validate(Object target, Errors errors) {
		// target is model being checked and errors register into errors instance
		ValidationUtils.rejectIfEmpty(errors, "publishDate", "publishDate.empty");
		ValidationUtils.rejectIfEmpty(errors, "description", "description.empty");
	}

}

#2. Register your validator

You should register your validator on function annotated with org.springframework.web.bind.annotation.InitBinder annotation with org.springframework.validation.DataBinder.setValidator(Validator) function.

// Call everytime when recevies request
@InitBinder
public void initBinder(WebDataBinder binder) {
	...
	binder.setValidator(new MessageDtoValidator())
	...
}

org.springframework.validation.Validator.supports(Class>) of your validator will be called when calling setValidator() to verify is your validator supports model binded.

#3. Specify model argument you want to verify and define corresponding action

You should add javax.validation.Valid (or org.springframework.validation.annotation.Validated) annotation in addition with org.springframework.web.bind.annotation.ModelAttribute annotation on model argument you want to verify. And specify actions when binding error is found.

@PostMapping("/{messageId}/save")
public String saveEditMessage(@PathVariable("messageId") long id, @Valid @ModelAttribute MessageDto message, BindingResult errors) {
	if (errors.hasErrors()) {
		// your action
		...
	}
}

After binding model, framework will check if validation annotation exists on model argument by org.springframework.web.method.annotation.ModelAttributeMethodProcessor.determineValidationHints(Annotation) function.

/**
 * Determine any validation triggered by the given annotation.
 * @param ann the annotation (potentially a validation annotation)
 * @return the validation hints to apply (possibly an empty array),
 * or {@code null} if this annotation does not trigger any validation
 * @since 5.1
 */
@Nullable
private Object[] determineValidationHints(Annotation ann) {
	Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
	if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
		Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(ann));
		if (hints == null) {
			return new Object[0];
		}
		return (hints instanceof Object[] ? (Object[]) hints : new Object[] {hints});
	}
	return null;
}

And then actual validation logic org.springframework.validation.Validator.validate(Object, Errors) will be called by org.springframework.web.method.annotation.ModelAttributeMethodProcessor.validateIfApplicable(WebDataBinder, MethodParameter) function.

#Example

You can find actual implementation from my notice board example application.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?