With Version 9 Hibernate Validator introduced a module-info file hiding the internal-packages (https://github.com/hibernate/hibernate-validator/blob/main/engine/pom.xml#L400-L402). During application startup the class LocalValidatorFactoryBean calls the method externalClassLoader of the interface HibernateValidatorConfiguration via reflection. This is no longer possible on module-path aware applications since the implementation of the method is located in class org.hibernate.validator.internal.engine.AbstractConfigurationImpl.

Stacktrace:

java.lang.IllegalStateException: Could not access method or field: class org.springframework.util.ReflectionUtils cannot access class org.hibernate.validator.internal.engine.AbstractConfigurationImpl (in module org.hibernate.validator) because module org.hibernate.validator does not export org.hibernate.validator.internal.engine to unnamed module @7357a011
        at org.springframework.util.ReflectionUtils.handleReflectionException(ReflectionUtils.java:109)
        at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:284)
        at spring.context@7.0.1/org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.afterPropertiesSet(LocalValidatorFactoryBean.java:267)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesJsr303Validator$Delegate.<init>(ConfigurationPropertiesJsr303Validator.java:72)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesJsr303Validator.<init>(ConfigurationPropertiesJsr303Validator.java:43)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesBinder.getJsr303Validator(ConfigurationPropertiesBinder.java:182)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesBinder.getValidators(ConfigurationPropertiesBinder.java:160)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesBinder.getBindHandler(ConfigurationPropertiesBinder.java:114)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:95)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:101)
        ... 47 more

A simple reproducer project is attached. The application starts successfully, if Hibernate Validator 8 is used instead of the new one.

validator-demo.zip

Comment From: jhoeller

Thanks for the report!

Like in other places, we enforce a publicly accessible method for externalClassLoader(ClassLoader) - in this case, it should find the corresponding method in the BaseHibernateValidatorConfiguration interface - before attempting reflection now.

This is available in the latest Spring Framework 7.0.3 snapshot already. Please give it an early try!

Comment From: johchur

Thank you for the quick fix @jhoeller.

Unfortunately, the reproducer is still not starting. The necessary validators are also in the internal package and cannot be created by BeanUtils.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator': Failed to instantiate [org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator]: Is the constructor accessible?
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:321)
        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1382)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1227)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:565)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:525)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:325)
        at spring.context@7.0.3-SNAPSHOT/org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory.getInstance(SpringConstraintValidatorFactory.java:56)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.constraintvalidation.ClassBasedValidatorDescriptor.newInstance(ClassBasedValidatorDescriptor.java:82)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.constraintvalidation.AbstractConstraintValidatorManagerImpl.createAndInitializeValidator(AbstractConstraintValidatorManagerImpl.java:87)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorManagerImpl.getInitializedValidator(ConstraintValidatorManagerImpl.java:115)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.getInitializedConstraintValidator(ConstraintTree.java:135)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:56)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:73)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:131)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:124)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:589)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:543)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:512)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:448)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:398)
        at org.hibernate.validator@9.0.1.Final/org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:170)
        at spring.context@7.0.3-SNAPSHOT/org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:102)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.ConfigurationPropertiesJsr303Validator.validate(ConfigurationPropertiesJsr303Validator.java:54)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.bind.validation.ValidationBindHandler.validateAndPush(ValidationBindHandler.java:143)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.bind.validation.ValidationBindHandler.validate(ValidationBindHandler.java:120)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.bind.validation.ValidationBindHandler.onFinish(ValidationBindHandler.java:109)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.bind.Binder.handleBindResult(Binder.java:404)
        at spring.boot@4.0.0/org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:374)
        ... 52 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator]: Is the constructor accessible?
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:218)
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:129)
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:318)
        ... 80 more
Caused by: java.lang.IllegalAccessException: class org.springframework.beans.BeanUtils cannot access class org.hibernate.validator.internal.constraintvalidators.bv.NotNullValidator (in module org.hibernate.validator) because module org.hibernate.validator does not export org.hibernate.validator.internal.constraintvalidators.bv to unnamed module @7357a011
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:670)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:492)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483)
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:198)
        ... 82 more

Comment From: jhoeller

Reopening for the SpringConstraintValidatorFactory part. Looks like we need to delegate to Hibernate's own DefaultConstraintValidatorFactory for those internal validators.

Comment From: johchur

Sucessfully tested the new change.

Thanks for the work.

Comment From: jhoeller

Great to hear! thanks for the immediate feedback.