Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-15856

Unable to use Hibernate Validator 4.3.2 if Bean Validation API 1.1 is on the classpath

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Minor
    • Resolution: Complete
    • Affects Version/s: 4.3.10
    • Fix Version/s: 4.3.11
    • Component/s: Core
    • Labels:
    • Last commented by a User:
      false

      Description

      Trying to create a LocalValidatorFactoryBean bean while both Hibernate Validator 4.3.2 and Bean Validation 1.1 are on the classpath throws the below error:

      Aug 09, 2017 1:11:57 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
      INFO: Refreshing org.spring[email protected]5197848c: startup date [Wed Aug 09 13:11:57 AST 2017]; root of context hierarchy
      Aug 09, 2017 1:11:57 PM org.hibernate.validator.internal.util.Version <clinit>
      INFO: HV000001: Hibernate Validator 4.3.2.Final
      Aug 09, 2017 1:11:57 PM org.springframework.context.annotation.AnnotationConfigApplicationContext refresh
      WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'localValidatorFactoryBean' defined in demo.Demo: Invocation of init method failed; nested exception is java.lang.AbstractMethodError: org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
      Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'localValidatorFactoryBean' defined in demo.Demo: Invocation of init method failed; nested exception is java.lang.AbstractMethodError: org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
      	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
      	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
      	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
      	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
      	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
      	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
      	at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
      	at demo.Demo.main(Demo.java:11)
      Caused by: java.lang.AbstractMethodError: org.hibernate.validator.internal.engine.ConfigurationImpl.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216)
      	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:201)
      	at org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.configureParameterNameProviderIfPossible(LocalValidatorFactoryBean.java:315)
      	at org.springframework.validation.beanvalidation.LocalValidatorFactoryBean.afterPropertiesSet(LocalValidatorFactoryBean.java:284)
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
      	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
      	... 11 more
      
      

      The issue is that LocalValidatorFactoryBean tries to detect Bean Validation 1.1 using the API interfaces, regardless of what the provider actually implements (See here and here). And since Class.getMethod succeeds, ReflectionUtils.invokeMethod throws an AbstractMethodError, which is an Error and not an Exception, so it doesn't get caught by the catch here.

      This could be fixed by explicitly catching AbstractMethodError in addition to Exception. But I think the correct fix is to call getMethod on the provider class instead of the API interfaces.

      (The reason I can't simply remove Bean Validation 1.1 from the classpath is that Spring Boot includes it even if <hibernate-validator.version>4.3.2.Final</hibernate-validator.version> is set in pom.xml. We also faced the same issue when deploying to a Java EE container that implements Bean Validation 1.1.)

      This is only an issue for Spring 4.x. Spring 5 will make Bean Validation 1.1 mandatory.

      To reproduce:
      pom.xml

      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      	<modelVersion>4.0.0</modelVersion>
      	<groupId>com.example</groupId>
      	<artifactId>demo</artifactId>
      	<version>0.0.1-SNAPSHOT</version>
      
      	<properties>
      		<maven.compiler.source>1.8</maven.compiler.source>
      		<maven.compiler.target>1.8</maven.compiler.target>
      	</properties>
      
      	<dependencies>
      		<dependency>
      			<groupId>org.springframework</groupId>
      			<artifactId>spring-context</artifactId>
      			<version>4.3.10.RELEASE</version>
      		</dependency>
      		<dependency>
      			<groupId>javax.validation</groupId>
      			<artifactId>validation-api</artifactId>
      			<version>1.1.0.Final</version>
      		</dependency>
      		<dependency>
      			<groupId>org.hibernate</groupId>
      			<artifactId>hibernate-validator</artifactId>
      			<version>4.3.2.Final</version>
      		</dependency>
      	</dependencies>
      </project>
      

      src/main/java/demo/Demo.java

      package demo;
      
      import javax.validation.Validator;
      
      import org.springframework.context.annotation.AnnotationConfigApplicationContext;
      import org.springframework.context.annotation.Bean;
      import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
      
      public class Demo {
      	public static void main(String[] args) {
      		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Demo.class);
      		Validator validator = context.getBean(Validator.class);
      		System.out.println(validator);
      
      		context.close();
      	}
      
      	@Bean
      	public LocalValidatorFactoryBean localValidatorFactoryBean() {
      		LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
      
      		return localValidatorFactoryBean;
      	}
      }
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                juergen.hoeller Juergen Hoeller
                Reporter:
                ibrahim.mg Ibrahim Ghazal
                Last updater:
                St├ęphane Nicoll
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  44 weeks, 5 days ago