이전에 객체에 대해서 Validation을 적용하는 방법에 대해서 알아봤습니다. 하지만 Collection형태로 넘어올 때 Validation이 동작하지 않습니다. 따라서 이번 포스팅은 Collection으로 넘어올 때도 마찬가지로 Validation이 동작하도록 코드를 만들겠습니다.  

 

1. Collection Test

 

단일 객체는 이전에 확인을 했으므로 컬렉션으로 넘겼을 Validation이 동작하는지 확인하겠습니다.

 

Controller 메서드 

private final CustomValidator customValidator;

@PostMapping("/validation/v7")
public ResponseEntity<?> validationV7(@Valid @RequestBody List<UserDto> dto){
    return new ResponseEntity<>(dto,HttpStatus.OK);
}

 

보내는 요청입니다. 

 

Collection에 들어있는 각 객체마다 Validation을 적용해주길 원했지만, 아래와 같이 적용이 되지 않을 것을 확인할 수 있습니다. 

 

2. Custom Validator 생성

Collection에도 Validation을 적용하기 위해서 Validator를 하나 정의합니다.

 

SpringValidatorAdapter는 Custom으로 만든 Validator를 기본 Validator로 사용하게끔 해주는 클래스입니다.

Validation.buildDefaultValidatorFactory(). getValidator()는 Bean Validation과 XML로 Validator를 사용할 수 있는 인스턴스를 반환해주는 역할을 합니다. 저희는 Bean Validation을 사용하므로 이것을 구현체로 사용하면 됩니다. 

@Component
public class CustomValidator implements Validator {

    private SpringValidatorAdapter validator;

    public CustomValidator(SpringValidatorAdapter validator) {
        this.validator = new SpringValidatorAdapter(Validation.buildDefaultValidatorFactory().getValidator());
    }

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

    @Override
    public void validate(Object target, Errors errors) {
        Collection col = (Collection) target;

        for(Object now: col){
            validator.validate(col,errors);
        }
    }
}

 

 

3. Controller 수정

 

@PostMapping("/validation/v7")
public ResponseEntity<?> validationV7(@Validated @RequestBody List<UserDto> dto, BindingResult bindingResult){
    customValidator.validate(dto,bindingResult);

    HashMap<String, Object> errors = new HashMap<>();
    if(bindingResult.hasErrors()){
        bindingResult.getAllErrors().stream()
                .forEach(a->{
                    String field = ((FieldError) a).getField();
                    String defaultMessage = a.getDefaultMessage();
                    errors.put(field, defaultMessage);
                });
        return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
    }
    return new ResponseEntity<>(dto,HttpStatus.OK);
}

 

4. CustomValidator Test

 

아래와 같이 올바르게 작동하는 것을 볼 수 있습니다. 

 

 

이렇게 해서 Collection에 대해서 Validation을 적용해봤습니다. Collection이 아닌 형태의 Validation은 기존에 구현해서 사용한 UserValidationHandler 혹은 ControllerAdvice를 사용하면 됩니다.

 

Collection에 Validation을 적용하기 위해서는 Controller 계층이 난잡해지는 코드가 존재하는데 추후에 방법이 있다면 추가해서 포스팅하겠습니다. 감사합니다.