Search code examples
javavalidationspring-bootspring-webfluxreactive

Bean validation is not working for spring webflux


I have refactored my code to use spring webflux but now @Valid stopped working. It is not validating the request body.

@PostMapping(value = "/getContactInfo",produces = "application/json",consumes = "application/json")
public Flux<UserContactsModel> getUserContacts(@Valid @RequestBody Mono<LoginModel> loginDetail) {

    loginDetail.log();
    return contactInfoService
        .getUserContacts(loginDetailApiMapper.loginModelMonoToLoginBoMono(loginDetail))
        .flatMapIterable(
            userContactsBO -> contactInfoMapper.userContactBoToModelList(userContactsBO));
}

I am getting 200 OK in place of Bad request which I am returning from the controller advice.

Edit 1:

   import javax.validation.constraints.NotNull;
   import javax.validation.constraints.Pattern;

    public class LoginModel implements Serializable {

      private String clientId;

      @Pattern(regexp = "^[a-zA-Z0-9]*$", message = "Login ID is invalid")
      @NotNull
      private String loginId;
    }

update 1: After changing the code like this and adding @Validated on class level

@RestController
@Validated
public class ContactInfoController implements ContactInfoApi {
public Flux<UserContactsModel> getUserContacts(@RequestBody  Mono<@Valid  LoginModel> loginDetail) {

I am getting javax.validation.ConstraintDeclarationException: HV000197: No value extractor found for type parameter 'T' of type reactor.core.publisher.Mono.


Solution

  • Nothing worked for me. So I validated it manually by using javax.validator.

    @Autowired private Validator validator;
    
     public Flux<UserContactsModel> getUserContacts(@RequestBody Mono<@Valid LoginModel> loginDetail) {
    
        return loginDetail
            .filter(this::validate)
            .map(....);
    }
    
     private boolean validate(LoginModel loginModel) {
    
        Set<ConstraintViolation<LoginModel>> constraintViolations = validator.validate(loginModel);
    
        if (CollectionUtils.isNotEmpty(constraintViolations)) {
          StringJoiner stringJoiner = new StringJoiner(" ");
          constraintViolations.forEach(
              loginModelConstraintViolation ->
                  stringJoiner
                      .add(loginModelConstraintViolation.getPropertyPath().toString())
                      .add(":")
                      .add(loginModelConstraintViolation.getMessage()));
          throw new RuntimeException(stringJoiner.toString());
        }
    
        return true;
      }