Spring @ControllerAdvice messageSource не работает с параметрами сообщения Hibernate - PullRequest
0 голосов
/ 01 сентября 2018

Я пытаюсь добавить пользовательскую проверку bean-компонента в REST-контроллер Spring Boot, расширяя класс ResponseEntityExceptionHandler аннотацией @ControllerAdvice и переопределяя метод #handleMethodArgumentNotValid(MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request). В этом методе я пытаюсь преобразовать данное FieldError через messageSource в локализованное сообщение. Хотя я получаю NumberFormatException при попытке использовать параметры сообщения, которые возможны через валидатор Hibernate.

Я использую следующие зависимости:

  • org.hibernate.validator:hibernate-validator (6.0.11. Финал)
  • org.springframework:spring-web (5.0.8. РЕЛИЗ)
  • org.springframework:spring-webmvc (5.0.8. РЕЛИЗ)

Все включено через org.springframework.boot:spring-boot-starter-web (2.0.4.RELEASE).

Рассмотрите возможность использования следующего контроллера REST:

@RestController
public class FooController {

    @PostMapping(value = "/foo")
    public void submitFooRequest(@Validated @RequestBody FooRequest fooRequest) {
        // ....
    }
}

Бин FooRequest имеет пользовательскую аннотацию проверки бина и валидатор ограничений:

Боб FooRequest:

@Getter
@Setter
@ValidBarRequest
public class FooRequest {

    private String fieldFoo;
    private BarRequest barRequest;
}

Бобовый запрос:

@Getter
@Setter
public class BarRequest {

    private String fieldBar;
}

Подтверждение аннотации:

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = BarRequestValidator.class)
@Documented
public @interface ValidBarRequest {

    String message() default "{org.example.validation.constraints.ValidBarRequest.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String fieldFoo() default "fieldFoo";

    String barRequestFieldBar() default "barRequest.fieldBar";
}

Валидатор ограничения проверки:

@Log4j2
public class BarRequestValidator implements ConstraintValidator<ValidBarRequest, Object> {

    // ....

    @Override
    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        if (/* some condition */) {
            HibernateConstraintValidatorContext hibernateValidatorContext = constraintValidatorContext.unwrap(HibernateConstraintValidatorContext.class);
            hibernateValidatorContext.disableDefaultConstraintViolation();
            hibernateValidatorContext.addMessageParameter("fieldFoo", "some value...").buildConstraintViolationWithTemplate("{org.example.validation.constraints.ValidBarRequest.message}")
                .addPropertyNode("barRequest.fieldBar").addConstraintViolation();
            return false;
        }

        return true;
    }
}

Однако через аннотированный компонент @ControllerAdvice и с использованием источника сообщений Spring в следующем сообщении (в messages.properties) генерируется исключение NumberFormatException:

ValidBarRequest.fooRequest.barRequest.fieldBar=must be lower or equal than {fieldFoo}

bean-компонент @ControllerAdvice:

@ControllerAdvice
public class ControllerExceptionHandler extends ResponseEntityExceptionHandler {

    @Autowired private MessageSource messageSource;

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException e, HttpHeaders headers, HttpStatus status, WebRequest request) {
        List<ErrorDetails> errorDetails = new ArrayList<>();
        for (FieldError fieldError : e.getBindingResult().getFieldErrors()) {
            errorDetails.add(new ErrorDetails(fieldError.getField(), messageSource.getMessage(fieldError, Locale.getDefault())));
        }

        return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
    }

    @Getter
    @AllArgsConstructor
    class ErrorDetails {

        private String field;
        private String message;
    }
}

Это вызывает следующее исключение: Caused by: java.lang.NumberFormatException: For input string: "fieldFoo"

Что я делаю не так? Также я включил в свой @SpringBootApplication следующий боб:

@Bean
public LocalValidatorFactoryBean validator(MessageSource messageSource) {
    LocalValidatorFactoryBean localValidatorFactory = new LocalValidatorFactoryBean();
    localValidatorFactory.setValidationMessageSource(messageSource);

    return localValidatorFactory;
}

1 Ответ

0 голосов
/ 01 сентября 2018

Заполните переменные в источнике сообщения MessageFormat.format, и там вы должны использовать числа в фигурных скобках.

ValidBarRequest.fooRequest.barRequest.fieldBar=must be lower or equal than {0}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...