[Spring Boot] Move validation (@Validated / @Valid) at any time [Bean Validation]

Verification was done with Spring Boot 2.0.9.

TL;DR Simple validation can be done at any time by using Validator obtained byValidation.buildDefaultValidatorFactory (). GetValidator ()of javax.validation.Validation.

Content that involves annotations that use a validator that uses @Autowired can be validated at any time by injecting @Autowire with @Autowire and using it.

Conventional way of moving

If you want the controller to receive the form you want to validate, you can receive an error in BindingResult by doing the following:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/*abridgement*/

@PostMapping("/api/test-post-api")
public void editRelayStructs(
        @RequestBody @Validated Form form,
        BindingResult errorResult
) {
    /*abridgement*/
}

Problems with conventional methods

In reality, you may want to perform validation at any time, such as unit tests or correlation checks with parameters. In that case, you will not be able to validate and receive the error in the form of the example given above.

How to get Validator withValidation.buildDefaultValidatorFactory (). GetValidator ()

If there is no reason such as @Autowire, you can validate at any time by usingValidator obtained by Validation.buildDefaultValidatorFactory (). GetValidator () of javax.validation.Validation. ..

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

/*abridgement*/

@PostMapping("/api/test-post-api")
public void editRelayStructs(
        @RequestBody Form form
) {
    //Get validation results
    Set<ConstraintViolation<Form>> errorResult =
            Validation.buildDefaultValidatorFactory().getValidator().validate(form);

    /*abridgement*/
}

This method can cover simple validation. On the other hand, since this method executes validation without going through Spring, there is a problem that injection does not work for self-made annotations that @Autowired.

How to get Validator by injecting it with @Autowire

As mentioned above, the Validator obtained withValidation.buildDefaultValidatorFactory (). GetValidator ()does not work with the validator class that does @ Autowired for validation.

@Example of validator class to autowired


import org.springframework.beans.factory.annotation.Autowired;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class ExistingIdValidator implements ConstraintValidator<ExistingId,Integer> {
    @Autowired
    public Dao dao;

    @Override
    public boolean isValid(Integer id, ConstraintValidatorContext context) {
        if (id == null) {
            return true;
        }
        return /*Existence check result for ID using Dao*/;
    }
}

In this case, @Autowired in the validator class works by injecting @Autowire to get the Validator defined on the Spring side.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;

/*abridgement*/

//(Originally, it should be injected with the constructor pattern)
@Autowired
public Validator validator; //Javax defined in Spring.validation.Validator

@PostMapping("/api/test-post-api")
public void editRelayStructs(
        @RequestBody Form form
) {
    //Get validation results
    Set<ConstraintViolation<Form>> errorResult = validator.validate(form);

    /*abridgement*/
}

Recommended Posts

[Spring Boot] Move validation (@Validated / @Valid) at any time [Bean Validation]
How to change application.properties settings at boot time in Spring boot
Spring Boot validation message changes
Spring Boot for the first time
Get validation results with Spring Boot
[Spring Boot] Post files and other data at the same time [Axios]
Processing at application startup with Spring Boot
[Introduction to Spring Boot] Form validation check
DI SessionScope Bean in Spring Boot 2 Filter
Form class validation test with Spring Boot
Change session timeout time in Spring Boot