简体   繁体   中英

Spring boot 2 rest validator called twice when groups are used

When I enable the @Validated spring annotation at class level in a Rest controller, 2 validation contexts are generated (each one with a different prefix). The @Validated annotation is required as I want to use 2 different validation groups but as there are 2 validations context all validations are executed twice. I think all validations should be verified only once so:

  • Is there any problem with my configuration?
  • Have I missed something?
    @RestController
    @RequestMapping
    @Validated
    public class KidController {
        private final KidService kidService;

        public KidController(KidService kidService) {
            this.kidService = kidService;
        }

        @PostMapping
        @Validated(OnRegistrationRequest.class)
        @ResponseStatus(HttpStatus.CREATED)
        public KidDTO createKidRegistration(@RequestBody @Valid KidDTO kid) {
            return kidService.saveKid(kid);
        }
    }

    public interface KidValidatorGroup {
        interface OnRegistrationRequest extends Default {
        }

        interface OnCheckInPersist extends Default {
        }
    }


    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @JsonPropertyOrder({"id"})
    @JsonInclude(Include.NON_NULL)
    public class KidDTO {
        @NotEmpty
        private String id;
        @NotEmpty
        private String firstName;
        @KidAgeConstraint
        private Integer age;
        @NotEmpty(groups = OnCheckInPersist.class)
        private String roomDocId;
        @Valid
        private Set<AnswerDTO> answers;
        @Valid
        private Set<GuardianDTO> guardians;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @FieldStrictDependentConstraint(principalField = "answer", 
       dependentField = "description")
    @JsonInclude(Include.NON_NULL)
    public class AnswerDTO {
        @QuestionIdConstraint(groups = OnRegistrationRequest.class)
        private String questionId;
    }

I found the 2 contexts when debugging the application and the second one looks with method name like prefix.

上下文图片1 上下文图片2

In your code you have an annotation that triggers validation both on method parameter and on method return value:

    @PostMapping
    @Validated(OnRegistrationRequest.class) // this one is "@Valid" with a specified group and will be used for return value validation
    @ResponseStatus(HttpStatus.CREATED)
    public KidDTO createKidRegistration(@RequestBody @Valid /* this one is for method parameter */ KidDTO kid) {
        return kidService.saveKid(kid);
    }

See the different paths that you have in your screenshots. One is createKidRegistration.kid.firstName that's the one for parameter. If you only need to validate the passed parameter with s specific group you should try to replace your @Valid with @Validated(OnRegistrationRequest.class) , and remove the @Validated from the method level completely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM