javax.validation.ValidationException:HV000183:无法加载' javax.el.E​​xpressionFactory'

时间:2014-06-24 12:34:08

标签: java hibernate validation maven hibernate-validator

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

我的步骤:

在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

我错了什么?

12 个答案:

答案 0 :(得分:144)

在添加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

答案 1 :(得分:56)

只做

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

答案 2 :(得分:12)

如果你使用tomcat作为你的服务器运行时并且你在测试中得到这个错误(因为测试期间tomcat运行时不可用),那么包含tomcat el runtime而不是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>

答案 3 :(得分:10)

关于Hibernate validator documentation page,您必须为JSR-341实施定义依赖关系:

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

答案 4 :(得分:6)

如果您将Spring Boot与启动程序一起使用-此依赖项会同时添加handleChange = (key, e) => { const { name, value } = e.target; this.setState(previousState => { const formRows = [...previousState.formRows]; const currentIndex = formRows.findIndex(row => row.key === key); formRows[currentIndex] = { ...formRows[currentIndex], [name]: value }; return { formRows }; }); }; tomcat-embed-el依赖项:

hibernate-validator

答案 5 :(得分:4)

如果使用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();
    }
}

答案 6 :(得分:3)

如果不需要 javax.el (例如在JavaSE应用程序中),请使用ParameterMessageInterpolator中的Hibernate validator。 休眠验证器是一个独立的组件,无需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();

答案 7 :(得分:2)

根据Getting started with Hibernate Validator文档,需要提供Expression Language (EL)实现。在Java EE环境中,它将由容器提供。但是,在您这样的独立应用程序中,需要提供它。

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

当您的应用程序在WildFly之类的Java EE容器中运行时,该容器已经提供了EL实现。

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

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

文档的依赖项示例有些陈旧,例如2018年的表达式语言transitioned to the Jakarta EE project。要使用Jakarta EE版本的表达式语言,请添加以下Eclipse Glassfish EL依赖项:

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

除了Glassfish,还有其他可以使用的EL实现。例如,Spring Boot默认使用嵌入式Tomcat。此版本的EL可以按以下方式使用:

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

答案 8 :(得分:1)

对于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"

答案 9 :(得分:1)

雅加达命名空间

作为从 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(分别)。

桌面和控制台应用

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

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

您可以使用依赖项管理工具(例如 MavenGradleIvy)来下载和捆绑接口和实现 jar。

雅加达表达语言

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

Jakarta Expression Language 由 Jakarta EE 定义为您必须下载接口 jar 的规范。并且您还需要在另一个 jar 中获取这些接口的实现。

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

Maven POM 依赖

将所有这些信息放在一起,您需要四个 jar:用于两个项目中的每一个的一对接口和实现 jar,Jakarta Bean ValidationJakarta Expression Language。< /p>

  • Jakarta Bean 验证
    • 界面
    • 实施
  • 雅加达表达语言
    • 界面
    • 实施

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

如上所述,您可以找到另一种 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

答案 10 :(得分:0)

对于gradle:

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

答案 11 :(得分:0)

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

 <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后,它对我有用。