0

I have a Spring (v2.2) application where I created a custom constraint validator for field on one of the entities I have like so,

@Retention(RetentionPolicy.RUNTIME)
public @interface ValidModules {
  String message() default "Only specify approved modules.";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}
public class ValidModulesValidator implements ConstraintValidator<ValidModules, List<String>> {

   private final ModuleResourcesConfig moduleResourcesConfig;

   public ValidModulesValidator(ModuleResourcesConfig moduleResourcesConfig) {
      this.moduleResourcesConfig = moduleResourcesConfig;
   }

   public boolean isValid(List<String> inputModules, ConstraintValidatorContext context) {
      ...     
      return true;
   }
}

When I use this validation by making rest api call & having a @Validated service, it returns back errors properly. But in the same call when I when then persist these input, it throws exception.

I use this to save modulesRepository.saveAll(modulesInput). The exception is,

java.lang.NoSuchMethodException: org.baps.ims.validation.validator.ValidModulesValidator.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_152]
    at java.lang.Class.getConstructor(Class.java:1825) ~[na:1.8.0_152]
    at org.hibernate.validator.internal.util.privilegedactions.NewInstance.run(NewInstance.java:41) ~[hibernate-validator-6.0.17.Final.jar:6.0.17.Final]
    at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl.run(ConstraintValidatorFactoryImpl.java:43) ~[hibernate-validator-6.0.17.Final.jar:6.0.17.Final]
Flush(DefaultFlushEventListener.java:40) ~[hibernate-core-5.4.4.Final.jar:5.4.4.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1493)

I tried multiple approaches by googling this without any success. Some of the things I tried,

  1. Use @Autowired for injecting the moduleResourcesConfig in the custom validator instead of having a constructor with that as the input. This gave a NPE because moduleResourcesConfig was never instantiated even though I have it as @Autowired.

  2. Next I explicitly specified @Component on the constraint validator, even though this should not have been required.

  3. Then I added a Validator Bean in the application like so,

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

  @Bean
  public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
  }
  1. I also tried setting spring.jpa.hibernate.ddl-auto: none.

  2. Also tried setting javax.persistence.validation.mode: none.

None of this has helped so far.

Chantz
  • 5,883
  • 10
  • 56
  • 79

2 Answers2

0

i think you need to specify the constraint in your validation interface like this :

@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
@Constraint(validatedBy = ValidModulesValidator .class)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidModules {
0

Found a solution that worked for me.

Basically need to have this,

@Lazy
class SpringValidatorConfiguration {

    @Bean
    @Lazy
    public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(final Validator validator) {
        return new HibernatePropertiesCustomizer() {

            @Override
            public void customize(Map<String, Object> hibernateProperties) {
                hibernateProperties.put("javax.persistence.validation.factory", validator);
            }
        };
    }
}
Chantz
  • 5,883
  • 10
  • 56
  • 79