I've encountered an unexpected behaviour when using dependency injection in a ConstraintValidator
which is getting evaluated at class level.
Entity class:
@Entity
@ValidDemoEntity
public class DemoEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}
Validation annotation:
@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;
}
}
Test class:
@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);
}
}
Validating the entity leads to:
javax.validation.ValidationException: HV000064: Unable to instantiate ConstraintValidator: com.example.demo.DemoEntityValidator.
and further down the stack trace:
Caused by: java.lang.NoSuchMethodException: com.example.demo.DemoEntityValidator.<init>()
which indicates that Hibernate
tried to initiate the the class instead of letting Spring take care of that.
The strange thing about this is that dependency injection works fine for validations applied on field level.
The code is available at GitHub.