Внедрение зависимостей ConstraintValidator приводит к ValidationException при проверке на уровне класса - PullRequest
0 голосов
/ 27 июня 2019

Я столкнулся с неожиданным поведением при использовании внедрения зависимостей в ConstraintValidator, который оценивается на уровне класса.

Класс сущности:

@Entity
@ValidDemoEntity
public class DemoEntity {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

}

Комментарий к валидации:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {DemoEntityValidator.class})
public @interface ValidDemoEntity {

    String message() default "{some.demo.validator.message}";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

}

Validator:

public class DemoEntityValidator implements ConstraintValidator<ValidDemoEntity, DemoEntity> {

    private DemoEntityRepository demoEntityRepository;

    public DemoEntityValidator(DemoEntityRepository demoEntityRepository) {
        this.demoEntityRepository = demoEntityRepository;
    }

    @Override
    public void initialize(ValidDemoEntity constraintAnnotation) {

    }

    @Override
    public boolean isValid(DemoEntity demoEntity, ConstraintValidatorContext constraintValidatorContext) {
        return true;
    }
}

Тестовый класс:

@SpringBootTest
public class ValidatorInstantiationTest {

    private Validator validator;

    @Before
    public void setUp() throws Exception {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        validator = validatorFactory.getValidator();
    }

    @Test
    public void shouldInitiateAndCallDemoEntityValidator() {
        DemoEntity demoEntity = new DemoEntity();
        validator.validate(demoEntity);
    }

}

Проверка сущности приводит к:

javax.validation.ValidationException: HV000064: Unable to instantiate ConstraintValidator: com.example.demo.DemoEntityValidator.

и далее по трассе стека:

Caused by: java.lang.NoSuchMethodException: com.example.demo.DemoEntityValidator.<init>()

, который указывает, что Hibernate пытался инициировать класс, вместо того чтобы позволить Spring позаботиться об этом.

Странно то, что внедрение зависимостей отлично работает для проверок, применяемых на уровне полей.

Код доступен на GitHub .

Ответы [ 2 ]

0 голосов
/ 27 июня 2019

1 Сделайте ваш валидатор Spring Bean

Этот сайт сообщает:

Платформа Spring автоматически обнаруживает все классы, которые реализуют интерфейс ConstraintValidator. Фреймворк создает их и связывает все зависимости, как если бы класс был обычным компонентом Spring.

Что явно работает для проверок, применяемых на уровне поля.

Тем не менее я обновил код.

DemoEntityValidator теперь является компонентом Spring:

@Component
public class DemoEntityValidator implements ConstraintValidator<ValidDemoEntity, DemoEntity>

Я изменил тест на:

@SpringBootTest
@RunWith(SpringRunner.class)
public class ValidatorInstantiationTest {

    @Autowired
    private DemoEntityRepository demoEntityRepository;

    @Test
    public void shouldInitiateAndCallDemoEntityValidator() {
        DemoEntity demoEntity = new DemoEntity();
        demoEntityRepository.save(demoEntity);
    }

}

Чтобы сделать регистр использования более понятным, но тест все еще приводит к тому же исключению.

0 голосов
/ 27 июня 2019

Исключение говорит об отсутствии конструктора по умолчанию, поскольку Hibernate Validator пытается создать экземпляр вашего валидатора.

Вы должны использовать Spring.

1 Сделайте ваш валидатор Spring Bean:

@Component
public class DemoEntityValidator implements ConstraintValidator<ValidDemoEntity, DemoEntity> {

2 Введите предоставленный Spring валидатор и используйте SpringRunner для выполнения ваших тестов:

@SpringBootTest
@RunWith(SpringRunner.class)
public class ValidatorInstantiationTest {

    @Autowired
    private Validator validator;

    @Test
    public void shouldInitiateAndCallDemoEntityValidator() {
        DemoEntity demoEntity = new DemoEntity();
        validator.validate(demoEntity);
    }

}
...