Проверка bean-компонентов JSR-303 с помощью Spring не запускается

Я настроил специальный валидатор JSR-303, следуя указаниям в документации (http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/validation.html) вместе с LocalValidatorFactoryBean и валидатором Hibernate на путь к классам. Однако мой валидатор просто отказывается включиться. Я разместил здесь простой тестовый проект (https://github.com/abhijitsarkar/java/tree/master/spring-jsr-303) вместе с неудачным модульным тестом. Если вы решите взглянуть, просто клонируйте его и запустите gradlew clean test из корневого каталога. Я использую Spring framework 4.0.2.RELEASE и валидатор Hibernate 5.0.3.Final.

Проверяемый метод:

public Coffee serve(@ValidOrder(Coffee.Blend.class) final String blend) {

Аннотация ValidOrder:

@Documented
@Constraint(validatedBy = {OrderValidator.class})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,
        ElementType.FIELD,
        ElementType.ANNOTATION_TYPE,
        ElementType.CONSTRUCTOR,
        ElementType.PARAMETER})
@NotNull
public @interface ValidOrder {

Валидатор OrderValidator:

public class OrderValidator implements ConstraintValidator<ValidOrder, String> {

Конфигурация Spring:

@Configuration
@ComponentScan(basePackages = "name.abhijitsarkar.coffeehouse")
@EnableAspectJAutoProxy
public abstract class AppConfig {

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }
}

Зависимости:

dependencies {
    compile(
            [group: 'javax.inject', name: 'javax.inject', version: injectApiVersion],
            [group: 'javax.validation', name: 'validation-api', version: beanValidationApiVersion],
            [group: 'javax.annotation', name: 'javax.annotation-api', version: annotationApiVersion],
            [group: 'org.springframework', name: 'spring-beans', version: springVersion],
            [group: 'org.springframework', name: 'spring-context', version: springVersion],
            [group: 'org.springframework', name: 'spring-aop', version: springVersion],
            [group: 'org.aspectj', name: 'aspectjrt', version: aspectjVersion]
    )
    runtime(
            [group: 'org.hibernate', name: 'hibernate-validator', version: hibernateValidatorVersion],
            [group: 'javax.el', name: 'javax.el-api', version: elVersion],
            [group: 'org.glassfish.web', name: 'javax.el', version: glassfishElVersion],
            [group: 'org.aspectj', name: 'aspectjweaver', version: aspectjVersion]
    )

person Abhijit Sarkar    schedule 23.02.2014    source источник


Ответы (2)


  1. В дополнение к LocalValidatorFactoryBean необходимо настроить MethodValidationPostProcessor.
  2. Проверяемый класс должен иметь аннотацию @Validated, иначе методы НЕ будут искать встроенные аннотации ограничений.

    @Configuration
    @ComponentScan(basePackageClasses = {SpringPackageComponentScanMarker.class})
    @EnableAspectJAutoProxy
    public abstract class AppConfig {
    
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        final MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
    
        return methodValidationPostProcessor;
    }
    
    @Bean
    public LocalValidatorFactoryBean validator() {
        final LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    
        return localValidatorFactoryBean;
      }
    }
    

...

@Service
@Validated
public class SpringBarista extends Barista {

Часть справочного руководства, в которой говорится об интеграции с JSR-303, для удобства опускает эти 2 важных момента, без которых BV не сработает. Это вызвало у меня 6 часов отладки и разрыва волос, когда я делал все, что сказано в документе, но BV просто не сдаваться. Мне, наконец, пришлось отлаживать исходный код Spring, чтобы понять это. Должен быть способ попроще, и я не могу быть единственным, у кого была эта проблема. Создал JIRA SPR-11473, чтобы они могли обновить документ.

person Abhijit Sarkar    schedule 23.02.2014

Чтобы spring to validation активировал аргумент blend, перед ним должна стоять аннотация @Valid.

Ваш подход может не сработать, поскольку ограничения параметров не поддерживаются JSR303.

Аннотации ограничений могут быть нацелены на любой из следующих ElementTypes:

ПОЛЕ для ограниченных атрибутов

МЕТОД для ограниченных геттеров

ТИП для ограниченных бобов

ANNOTATION_TYPE для ограничений, составляющих другие ограничения

http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation

person Bart    schedule 23.02.2014
comment
@Valid используется для рекурсивной проверки bean-компонента, я не уверен, работает ли он вообще с типом String; он может ожидать, что члены класса будут иметь свои собственные ограничения проверки. Во всяком случае, это не было моей проблемой. См. Мой ответ выше. - person Abhijit Sarkar; 23.02.2014
comment
Кроме того, ограничения параметров поддерживаются в BV 1.1 beanvalidation.org/1.1/spec/ - person Abhijit Sarkar; 23.02.2014