Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple constraints spring validation

I am using spring to validate a form. The model for the form is similar to this:

public class FormModel {

    @NotBlank
    private String name;

    @NotNull
    @ImageSizeConstraint
    private MultipartFile image;

}

The '@ImageSizeConstraint' is a custom constraint. What I want is for the @NotNull to be evaluated first and if this evaluates to false, not to evaluate @ImageSizeConstraint.

If this is not possible, I will have to check for null in the custom constraint as well. Which is not a problem, but I would like to seperate the concerns (not null / image size / image / aspectratio / etc).

like image 904
Robert van der Spek Avatar asked Oct 02 '17 11:10

Robert van der Spek


People also ask

How does a constraint validator work?

Naturally, we're going with a simple validation rule here in order to show how the validator works. ConstraintValidator defines the logic to validate a given constraint for a given object. Implementations must comply with the following restrictions:

When to use custom validation in Spring MVC?

Overview Generally, when we need to validate user input, Spring MVC offers standard predefined validators. However, when we need to validate a more particular type of input, we have the ability to create our own custom validation logic.

What is Hibernate Validator in spring?

The Bean Validation API is the popular approach for data validations in Spring applications. Here we will be using the hibernate implementation of the Bean Validation API known as Hibernate Validator.

What is Bean Validation in Spring MVC?

The Spring MVC framework provides us with standard predefined validators to validate user input data in a simple and straightforward way. The Bean Validation API is the popular approach for data validations in Spring applications.


Video Answer


1 Answers

You may use constraints grouping and group sequences to define the validation order. According to JSR-303 (part 3.5. Validation routine):

Unless ordered by group sequences, groups can be validated in no particular order. This implies that the validation routine can be run for several groups in the same pass.

As Hibernate Validator documentation says:

In order to implement such a validation order you just need to define an interface and annotate it with @GroupSequence, defining the order in which the groups have to be validated (see Defining a group sequence). If at least one constraint fails in a sequenced group, none of the constraints of the following groups in the sequence get validated.

First, you have to define constraint groups and apply them to the constraints:

public interface CheckItFirst {}

public interface ThenCheckIt {}

public class FormModel {

    @NotBlank
    private String name;

    @NotNull(groups = CheckItFirst.class)
    @ImageSizeConstraint(groups = ThenCheckIt.class)
    private MultipartFile image;
}

And then, as constraints are evaluated in no particular order, regardless of which groups they belong to (Default group too), you have to create @GroupSequence for your image field constraints groups.

@GroupSequence({ CheckItFirst.class, ThenCheckIt.class })
public interface OrderedChecks {}

You can test it with

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<FormModel>> constraintViolations =
                            validator.validate(formModel, OrderedChecks.class);

To apply this validation in Spring MVC Controller methods, you may use the @Validated annotation, which can specify the validation groups for method-level validation:

@PostMapping(value = "/processFormModel")
public String processFormModel(@Validated(OrderedChecks.class) FormModel formModel) {
    <...>
}
like image 182
Anatoly Shamov Avatar answered Nov 15 '22 06:11

Anatoly Shamov