#StackBounty: #spring #hibernate #bean-validation #hibernate-validator ConstraintValidator dependency injection leads to ValidationExce…

Bounty: 100

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.


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.