【问题标题】:javax.validation.ValidationException: HV000183: Unable to load 'javax.el.ExpressionFactory'javax.validation.ValidationException:HV000183:无法加载“javax.el.E​​xpressionFactory”
【发布时间】:2014-08-14 17:22:20
【问题描述】:

我尝试使用休眠验证器编写非常简单的应用程序:

我的步骤:

在 pom.xml 中添加以下依赖项:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.1.1.Final</version>
</dependency>

编写代码:

class Configuration {
    Range(min=1,max=100)
    int threadNumber;
    //...

    public static void main(String[] args) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();

        Validator validator = factory.getValidator();

        Configuration configuration = new Configuration();
        configuration.threadNumber = 12;
            //...

        Set<ConstraintViolation<Configuration>> constraintViolations = validator.validate(configuration);
        System.out.println(constraintViolations);

    }
}

我得到以下堆栈跟踪:

Exception in thread "main" javax.validation.ValidationException: Unable to instantiate Configuration.
    at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:279)
    at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)
    ...
    at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>(ConfigurationImpl.java:110)
    at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>(ConfigurationImpl.java:86)
    at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:41)
    at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:276)
    ... 2 more

我做错了什么?

【问题讨论】:

  • 将 hibernate-validator 升级到 5.2.4.Final 解决了我的问题。
  • @fracz 我有 hibernate-validator = 5.2.4.Final 并且异常仍然存在。

标签: java hibernate validation maven hibernate-validator


【解决方案1】:

添加到pom.xml以下依赖项后它正在工作:

<dependency>
   <groupId>javax.el</groupId>
   <artifactId>javax.el-api</artifactId>
   <version>2.2.4</version>
</dependency>
<dependency>
   <groupId>org.glassfish.web</groupId>
   <artifactId>javax.el</artifactId>
   <version>2.2.4</version>
</dependency>

Getting started with Hibernate Validator:

Hibernate Validator 还需要统一表达式语言 (JSR 341) 的实现,以评估约束违规消息中的动态表达式。当您的应用程序在 Java EE 容器(例如 WildFly)中运行时,容器已经提供了 EL 实现。但是,在 Java SE 环境中,您必须将实现添加为 POM 文件的依赖项。例如,您可以添加以下两个依赖项以使用 JSR 341 reference implementation

<dependency>
   <groupId>javax.el</groupId>
   <artifactId>javax.el-api</artifactId>
   <version>2.2.4</version>
</dependency>
<dependency>
   <groupId>org.glassfish.web</groupId>
   <artifactId>javax.el</artifactId>
   <version>2.2.4</version>
</dependency>

【讨论】:

  • Bean Validation 1.1 需要类路径上的表达式语言依赖项。另见hibernate.org/validator/documentation/getting-started
  • org.glassfish.webjavax.el2.2.4runtime 就足够了,因为休眠验证器已经依赖于 javax.el-api
  • &lt;dependency&gt;&lt;groupId&gt;javax.el&lt;/groupId&gt;&lt;artifactId&gt;javax.el-api&lt;/artifactId&gt;&lt;version&gt;2.3.1&lt;/version&gt;&lt;/dependency&gt; 对我来说已经足够了
  • javax.elel-api2.2 解决了我的问题。
  • 看起来他们在 github 页面上都推荐了 SE 环境:github.com/hibernate/hibernate-validator。不过,上面的对我来说已经足够了。
【解决方案2】:

只做

<dependency>
   <groupId>javax.el</groupId>
   <artifactId>javax.el-api</artifactId>
   <version>2.2.4</version>
</dependency>

【讨论】:

  • 为什么hibernate-validator 不依赖那个依赖?
  • 不知道为什么会更好
  • @thomas.mc.work 我认为可以避免传递依赖问题
  • 它实际上在 pom 文件中标记为依赖项,但具有提供的 maven 范围。这意味着如果您的 JavaEE 服务器没有为您提供,您有责任自己添加。
  • 这个解决方案对我不起作用,我使用的是休眠验证器 6.0.4 和 3.0.0 版本的 java.el,我使用的是 WebLogic。任何人都可以帮助我.. 提前感谢您的帮助。
【解决方案3】:

如果您不需要 javax.el(例如在 JavaSE 应用程序中),请使用 Hibernate validator 中的 ParameterMessageInterpolator。 Hibernate 验证器是一个独立的组件,可以在没有Hibernate 本身的情况下使用。

依赖休眠验证器

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>6.0.16.Final</version>
</dependency>

使用 ParameterMessageInterpolator

import javax.validation.Validation;
import javax.validation.Validator;
import org.hibernate.validator.messageinterpolation.ParameterMessageInterpolator;

private static final Validator VALIDATOR =
  Validation.byDefaultProvider()
    .configure()
    .messageInterpolator(new ParameterMessageInterpolator())
    .buildValidatorFactory()
    .getValidator();

【讨论】:

  • 是的,我不想添加更多依赖项。干得好
  • 哦,关于图书馆项目,这对我来说确实是一个很好的答案。
  • 这应该是选择的答案。
  • 这是最好的答案,因为您不必依赖其他依赖项。
【解决方案4】:

如果您使用 tomcat 作为服务器运行时并且在测试中遇到此错误(因为在测试期间 tomcat 运行时不可用),那么包含 tomcat el 运行时而不是来自 glassfish 的运行时是有意义的)。这将是:

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-el-api</artifactId>
        <version>8.5.14</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jasper-el</artifactId>
        <version>8.5.14</version>
        <scope>test</scope>
    </dependency>

【讨论】:

  • 依然爱你。看起来您可以只包含 tomcat-jasper-el 依赖项,因为它似乎可以传递地包含 tomcat-el-api 依赖项。
【解决方案5】:

如果您使用带有启动器的 Spring Boot - 此依赖项添加了 tomcat-embed-elhibernate-validator 依赖项:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

【讨论】:

    【解决方案6】:

    关于Hibernate validator documentation page,您必须定义对JSR-341 实现的依赖:

    <dependency>
       <groupId>org.glassfish</groupId>
       <artifactId>javax.el</artifactId>
       <version>3.0.1-b11</version>
    </dependency>
    

    【讨论】:

      【解决方案7】:

      Hibernate 验证器需要(但不包括)Expression Language (EL) 实现。添加一个依赖将解决这个问题。

      <dependency>
         <groupId>org.glassfish</groupId>
         <artifactId>jakarta.el</artifactId>
         <version>3.0.3</version>
      </dependency>
      

      Getting started with Hibernate Validator 文档中记录了此要求。在 Java EE 环境中,它将由容器提供。在像您这样的独立应用程序中,需要提供它。

      Hibernate Validator 还需要统一表达式语言 (JSR 341) 的实现,以评估约束违规消息中的动态表达式。

      当您的应用程序在 Java EE 容器(例如 WildFly)中运行时,容器已经提供了 EL 实现。

      但是,在 Java SE 环境中,您必须将实现作为依赖项添加到您的 POM 文件中。例如,您可以添加以下依赖项以使用 JSR 341 参考实现:

      <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>jakarta.el</artifactId>
        <version>${version.jakarta.el-api}</version>
      </dependency>
      

      表达式语言实现

      存在几种 EL 实现。一种是文档中提到的 Jakarta EE Glassfish 参考实现。另一个是嵌入的Tomcat,当前版本的Spring Boot默认使用。该版本的 EL 可以按如下方式使用:

      <dependency>
         <groupId>org.apache.tomcat.embed</groupId>
         <artifactId>tomcat-embed-el</artifactId>
         <version>9.0.48</version>
      </dependency>
      

      this comment 中所述,必须选择兼容版本的表达式语言。 Glassfish 实现被指定为 Hibernate Validator 的 provided-scope 依赖项,因此那里指定的版本应该可以正常工作。特别是,Hibernate Validator 7 使用 Glassfish EL 实现的第 4 版,Hibernate 6 使用第 3 版。

      春季启动

      在 Spring Boot 项目中,通常会使用 spring-boot-starter-validation 依赖项,而不是直接指定 Hibernate 验证器和 EL 库。该依赖项包括org.hibernate.validator:hibernate-validatortomcat-embed-el

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-validation</artifactId>
          <version>2.4.3.RELEASE</version>
      </dependency>
      

      【讨论】:

      • 注意版本兼容性:我刚刚发现 Hibernate Validator 6.1 无法与 org.glassfish:jakarta.el:4.0.1 一起使用,我需要坚持使用 org.glassfish:jakarta.el:3.0.3(我猜在升级 Hibernate Validator 之前)。
      • @EtienneMiret Hibernate 7 documentation 使用 4.0.0,因此看起来更新到该版本确实可以让您使用 EL 4 实现。另一方面,Hibernate 6 documentation 使用 3.0.3。
      • @EtienneMiret 我已经更新了答案以提及版本兼容性问题以及确保选择兼容版本的一种方法
      【解决方案8】:

      雅加达命名空间

      作为从OracleEclipse Foundation 的移交的一部分,Java EE 正在重命名为 Jakarta EE。在 Jakarta EE 9 中,Java 包名称从 javax.* 更改为 jakarta.*

      关于雅加达,Answer by M. Justin 是正确的。我添加了这个答案以提供更多解释和具体示例。

      接口与实现

      Jakarta Bean Validation 是 Java 中的 API 规范。此规范的二进制库仅包含interfaces,不包含可执行代码。所以我们还需要这些接口的实现。

      我只知道 Jakarta Bean Validation 版本 2 和 3 规范的一种实现:Hibernate Validator 版本 6 和 7(分别)。

      桌面和控制台应用程序

      对于 Web 应用,符合 Jakarta 标准的 Web 容器将提供执行 Bean 验证所需的接口和实现。

      对于桌面和控制台应用程序,我们没有这种符合 Jakarta 标准的 Web 容器。因此,您必须将接口 jar 和实现 jar 与您的应用程序捆绑在一起。

      您可以使用诸如MavenGradleIvy 之类的依赖项管理工具来下载和捆绑接口和实现 jar。

      雅加达表达语言

      要运行 Jakarta Bean 验证,我们还需要另一个 Jakarta 工具:Jakarta Expression Languagespecial purpose programming language 用于嵌入和评估 expressions雅加达表达语言也简称为EL

      Jakarta 表达语言 由 Jakarta EE 定义为您必须下载一个 jar 接口的规范。而且你还需要在另一个jar中获取这些接口的实现。

      您可以选择实现。截至 2021 年 3 月,我知道 Eclipse Foundation 的 Eclipse Glassfish 提供了一个实现作为单独的库,我们可以免费下载。可能还有其他实现,例如 IBM Corporation 的 Open Liberty。货比三家,寻找适合您需求的实施方案。

      Maven POM 依赖项

      将所有这些信息汇总在一起,您需要四个 jar:两个项目中的每一个都有一对接口和实现 jar,Jakarta Bean ValidationJakarta Expression Language

      • Jakarta Bean 验证
        • 接口
        • 实施
      • 雅加达表达语言
        • 接口
        • 实施

      如果 Maven 是您选择的工具,以下是您需要添加到 Maven POM 文件中的四个依赖项。

      如上所述,您也许可以找到另一种 EL 实现来替代我在这里使用的 Glassfish 库。

      <!--********| Jakarta Bean Validation  |********-->
      
      <!-- Interface -->
      
      <!-- https://mvnrepository.com/artifact/jakarta.validation/jakarta.validation-api -->
      <dependency>
          <groupId>jakarta.validation</groupId>
          <artifactId>jakarta.validation-api</artifactId>
          <version>3.0.0</version>
      </dependency>
      
      <!-- Implementation -->
      
      <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
      <dependency>
          <groupId>org.hibernate.validator</groupId>
          <artifactId>hibernate-validator</artifactId>
          <version>7.0.1.Final</version>
      </dependency>
      
      <!-- Jakarta Expression Language -->
      
      <!-- Interface -->
      
      <!-- https://mvnrepository.com/artifact/jakarta.el/jakarta.el-api -->
      <dependency>
          <groupId>jakarta.el</groupId>
          <artifactId>jakarta.el-api</artifactId>
          <version>4.0.0</version>
      </dependency>
      
      <!-- Implementation -->
      
      <!-- https://mvnrepository.com/artifact/org.glassfish/jakarta.el -->
      <dependency>
          <groupId>org.glassfish</groupId>
          <artifactId>jakarta.el</artifactId>
          <version>4.0.1</version>
      </dependency>
      

      这应该可以消除javax.validation.ValidationException: HV000183: Unable to load 'javax.el.ExpressionFactory' 错误。

      示例用法

      您可以使用以下简单类Car 来测试您的设置。我们对三个成员字段中的每一个都进行了验证。

      package work.basil.example.beanval;
      
      import jakarta.validation.constraints.*;
      
      public class Car
      {
          // ---------------|  Member fields  |----------------------------
          @NotNull
          private String manufacturer;
      
          @NotNull
          @Size ( min = 2, max = 14 )
          private String licensePlate;
      
          @Min ( 2 )
          private int seatCount;
      
          // ---------------|  Constructors  |----------------------------
          public Car ( String manufacturer , String licensePlate , int seatCount )
          {
              this.manufacturer = manufacturer;
              this.licensePlate = licensePlate;
              this.seatCount = seatCount;
          }
      
          // ---------------|  Object overrides  |----------------------------
      
          @Override
          public String toString ( )
          {
              return "Car{ " +
                      "manufacturer='" + manufacturer + '\'' +
                      " | licensePlate='" + licensePlate + '\'' +
                      " | seatCount=" + seatCount +
                      " }";
          }
      }
      

      或者,如果使用 Java 16 及更高版本,请改用更简短的 record

      package work.basil.example.beanval;
      
      import jakarta.validation.constraints.*;
      
      public record Car (
              @NotNull
              String manufacturer ,
              @NotNull
              @Size ( min = 2, max = 14 )
              String licensePlate ,
              @Min ( 2 )
              int seatCount
      )
      {
      }
      

      运行验证。首先,我们使用成功配置的Car 对象运行。然后我们实例化第二个有故障的Car 对象,违反了对三个字段中的每一个字段的一个约束。

      package work.basil.example.beanval;
      
      import jakarta.validation.ConstraintViolation;
      import jakarta.validation.Validation;
      import jakarta.validation.Validator;
      import jakarta.validation.ValidatorFactory;
      
      import java.util.Set;
      
      public class App
      {
          public static void main ( String[] args )
          {
              App app = new App();
              app.demo();
          }
      
          private void demo ( )
          {
              ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
              Validator validator = factory.getValidator();
      
              // No violations.
              {
                  Car car = new Car( "Honda" , "ABC-789" , 4 );
                  System.out.println( "car = " + car );
      
                  Set < ConstraintViolation < Car > > violations = validator.validate( car );
                  System.out.format( "INFO - Found %d violations.\n" , violations.size() );
              }
      
              // 3 violations.
              {
                  Car car = new Car( null , "X" , 1 );
                  System.out.println( "car = " + car );
      
                  Set < ConstraintViolation < Car > > violations = validator.validate( car );
                  System.out.format( "INFO - Found %d violations.\n" , violations.size() );
                  violations.forEach( carConstraintViolation -> System.out.println( carConstraintViolation.getMessage() ) );
              }
          }
      }
      

      运行时。

      car = Car{ manufacturer='Honda' | licensePlate='ABC-789' | seatCount=4 }
      INFO - Found 0 violations.
      car = Car{ manufacturer='null' | licensePlate='X' | seatCount=1 }
      INFO - Found 3 violations.
      must be greater than or equal to 2
      must not be null
      size must be between 2 and 14
      

      【讨论】:

        【解决方案9】:

        如果使用 Spring Boot,则效果很好。即使使用 Spring Reactive Mongo。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        

        和验证配置:

        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
        import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
        
        @Configuration
        public class MongoValidationConfig {
        
            @Bean
            public ValidatingMongoEventListener validatingMongoEventListener() {
                return new ValidatingMongoEventListener(validator());
            }
        
            @Bean
            public LocalValidatorFactoryBean validator() {
                return new LocalValidatorFactoryBean();
            }
        }
        

        【讨论】:

          【解决方案10】:

          对于 sbt,请使用以下版本

          val glassfishEl = "org.glassfish" % "javax.el" % "3.0.1-b09"
          
          val hibernateValidator = "org.hibernate.validator" % "hibernate-validator" % "6.0.17.Final"
          
          val hibernateValidatorCdi = "org.hibernate.validator" % "hibernate-validator-cdi" % "6.0.17.Final"
          
          

          【讨论】:

            【解决方案11】:

            我遇到了同样的问题,上面的答案没有帮助。我需要调试并找到它。

             <dependency>
                    <groupId>org.apache.hadoop</groupId>
                    <artifactId>hadoop-common</artifactId>
                    <version>2.6.0-cdh5.13.1</version>
                    <exclusions>
                        <exclusion>
                            <artifactId>jsp-api</artifactId>
                            <groupId>javax.servlet.jsp</groupId>
                        </exclusion>
                    </exclusions>
                </dependency>
            

            排除 jsp-api 后,它对我有用。

            【讨论】:

              【解决方案12】:

              对于毕业:

              compile 'javax.el:javax.el-api:2.2.4'
              

              【讨论】:

                【解决方案13】:

                对于使用 Hibernate Validator 7 (org.hibernate.validator:hibernate-validator:7.0.0.Final) 作为 Jakarta Bean Validation 3.0 实现的任何人,都应该使用依赖项:

                <dependency>
                    <groupId>org.glassfish</groupId>
                    <artifactId>jakarta.el</artifactId>
                    <version>4.0.0</version>
                </dependency>
                

                Hibernate Validator documentation中所述

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2019-07-09
                  • 1970-01-01
                  • 2017-07-31
                  • 2019-09-29
                  • 2018-05-29
                  • 2012-08-27
                  • 2017-10-31
                  • 1970-01-01
                  相关资源
                  最近更新 更多