136

I try to write very simple application with hibernate validator:

my steps:

Added following dependency in pom.xml:

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

Wrote following code:

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);

    }
}

And I get following stacktrace:

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

What do I wrong?

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710

16 Answers16

175

It is working after adding to pom.xml following dependencies:

<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 also requires an implementation of the Unified Expression Language (JSR 341) for evaluating dynamic expressions in constraint violation messages. When your application runs in a Java EE container such as WildFly, an EL implementation is already provided by the container. In a Java SE environment, however, you have to add an implementation as dependency to your POM file. For instance you can add the following two dependencies to use the 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>
M. Justin
  • 14,487
  • 7
  • 91
  • 130
gstackoverflow
  • 36,709
  • 117
  • 359
  • 710
  • 6
    Bean Validation 1.1 requires the Expression Language dependencies on the classpath. See also http://hibernate.org/validator/documentation/getting-started/ – Hardy Jun 25 '14 at 09:01
  • 1
    org.glassfish.web javax.el 2.2.4 runtime is sufficent as hibernate validator already depends on javax.el-api – mvera Jul 15 '14 at 20:57
  • 9
    `javax.eljavax.el-api2.3.1` was sufficient for me – Sled Jul 25 '14 at 18:22
  • 1
    javax.el el-api 2.2 solved my problem. – zhy2002 Oct 07 '14 at 00:56
  • hibernate-validator uses the `provided` scope dependency on `javax.el:javax.el-api` and `org.glassfish.web:javax.el`. Possibly, they are not always required - I have a colleague running without them, using xml validation instead of annotations. – Sarah Phillips Apr 07 '16 at 10:29
  • 3
    Looks like they recommend both on the github page for SE environments: https://github.com/hibernate/hibernate-validator. The top one was sufficient for me though. – riddle_me_this Jun 29 '16 at 07:27
  • not required to add `org.glassfish.web` dependency, check @Bruno Marinho answer. – Vishrant Nov 08 '17 at 01:32
  • To everyone who is also confused: If you use JBoss/Wildfly, this is still the right way to go, even though using a glassfish library is counterintuitive. – Thomas Jul 31 '19 at 13:39
  • for me also ` javax.el el-api 2.2 ` worked – phil Mar 24 '20 at 12:29
60

do just

<dependency>
   <groupId>javax.el</groupId>
   <artifactId>javax.el-api</artifactId>
   <version>2.2.4</version>
</dependency>
Bruno Lee
  • 1,867
  • 16
  • 17
40

In case you don't need javax.el (for example in a JavaSE application), use ParameterMessageInterpolator from Hibernate validator. Hibernate validator is a standalone component, which can be used without Hibernate itself.

Depend on hibernate-validator

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

Use 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();
Markus Schulte
  • 4,171
  • 3
  • 47
  • 58
23

If you are using tomcat as your server runtime and you get this error in tests (because tomcat runtime is not available during tests) than it makes make sense to include tomcat el runtime instead of the one from glassfish). This would be:

    <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>
walkeros
  • 4,736
  • 4
  • 35
  • 47
  • 1
    Still love you. It looks like you can include just the `tomcat-jasper-el` dependency, since it seems to transitively include the `tomcat-el-api` dependency. – xdhmoore Jul 18 '19 at 00:46
16

If you're using spring boot with starters - this dependency adds both tomcat-embed-el and hibernate-validator dependencies:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Michał Stochmal
  • 5,895
  • 4
  • 36
  • 44
14

Regarding the Hibernate validator documentation page, you have to define a dependency to a JSR-341 implementation:

<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.el</artifactId>
   <version>3.0.1-b11</version>
</dependency>
herau
  • 1,466
  • 2
  • 18
  • 36
13

The Hibernate Validator requires — but does not include — an Expression Language (EL) implementation. Adding a dependency on one will will fix the issue.

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

This requirement is documented in the Getting started with Hibernate Validator documentation. In a Java EE environment, it would be provided by the container. In a standalone application such as yours, it needs to be provided.

Hibernate Validator also requires an implementation of the Unified Expression Language (JSR 341) for evaluating dynamic expressions in constraint violation messages.

When your application runs in a Java EE container such as WildFly, an EL implementation is already provided by the container.

In a Java SE environment, however, you have to add an implementation as dependency to your POM file. For instance, you can add the following dependency to use the JSR 341 reference implementation:

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

Expression Language Implementation

Several EL implementations exist. One is the Jakarta EE Glassfish reference implementation mentioned in the documentation. Another is embedded Tomcat, which is used by default by the current version of Spring Boot. That version of EL can be used as follows:

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

As noted in this comment, a compatible version of the Expression Language must be chosen. The Glassfish implementation is specified as a provided-scope dependency of Hibernate Validator, so the version specified there should work without issue. In particular, Hibernate Validator 7 uses version 4 of the Glassfish EL implementation and Hibernate 6 uses version 3.

Spring Boot

In a Spring Boot project, the spring-boot-starter-validation dependency would typically be used rather than specifying the Hibernate validator & EL libraries directly. That dependency includes both org.hibernate.validator:hibernate-validator and tomcat-embed-el.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.4.3.RELEASE</version>
</dependency>
M. Justin
  • 14,487
  • 7
  • 91
  • 130
  • 2
    Beware of version compatibility: I just found out Hibernate Validator 6.1 will not work with `org.glassfish:jakarta.el:4.0.1`, I need to stick to `org.glassfish:jakarta.el:3.0.3` (until I upgrade Hibernate Validator I guess). – Étienne Miret Mar 14 '21 at 07:22
  • @EtienneMiret [Hibernate 7 documentation](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=7.0#validator-gettingstarted-uel) uses 4.0.0, so it looks like updating to that would indeed let you use an EL 4 implementation. [Hibernate 6 documentation](https://docs.jboss.org/hibernate/validator/6.1/reference/en-US/html_single/#preface) on the other hand uses 3.0.3. – M. Justin Mar 14 '21 at 17:13
  • 1
    @EtienneMiret I've updated the answer to mention the version compatibility issue and one way of ensuring that a compatible version is chosen – M. Justin Mar 15 '21 at 05:16
9

Jakarta namespace

As part of the handover from Oracle to the Eclipse Foundation, Java EE is being renamed to Jakarta EE. With Jakarta EE 9, the Java package names were changed from javax.* to jakarta.*.

The Answer by M. Justin is correct with regard to Jakarta. I added this Answer to provide more explanation and specific examples.

Interface versus Implementation

Jakarta Bean Validation is a specification of an API in Java. The binary library for this spec contains only interfaces, not executable code. So we also need an implementation of these interfaces.

I know of only one implementation of Jakarta Bean Validation versions 2 & 3 specifications: Hibernate Validator versions 6 and 7 (respectively).

Desktop & console apps

For web apps, a Jakarta-compliant web container will provide both the interface and the implementation needed to perform Bean Validation.

For desktop and console apps, we have no such Jakarta-compliant web container. So you must bundle both the interface jar and the implementation jar with your app.

You can use a dependency-management tool such as Maven, Gradle, or Ivy to download and bundle the interface & implementation jars.

Jakarta Expression Language

To run Jakarta Bean Validation, we need another Jakarta tool as well: Jakarta Expression Language, a special purpose programming language for embedding and evaluating expressions. Jakarta Expression Language is also known simply as EL.

Jakarta Expression Language is defined by Jakarta EE as a specification for which you must download a jar of interfaces. And you also need to obtain an implementation of these interfaces in another jar.

You may have choice of implementations. As of 2021-03, I know of Eclipse Glassfish by Eclipse Foundation providing an implementation as a separate library we can download free-of-cost. There may be other implementations, such as Open Liberty by IBM Corporation. Shop around for an implementation that suits your needs.

Maven POM dependencies

Pulling all this info together, you need four jars: A pair of interface and implementation jars for each of two projects, Jakarta Bean Validation and Jakarta Expression Language.

  • Jakarta Bean Validation
    • Interface
    • Implementation
  • Jakarta Expression Language
    • Interface
    • Implementation

The following are the four dependencies you need to add to your Maven POM file, if Maven is your tool of choice.

As mentioned above, you may be able to find another implementation of EL to substitute for the Glassfish library I use here.

<!--********| 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>

That should eliminate the javax.validation.ValidationException: HV000183: Unable to load 'javax.el.ExpressionFactory' error.

Example usage

You can test your setup with the following simple class, Car. We have validations on each of the three member fields.

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 +
                " }";
    }
}

Or, if using Java 16 and later, use a more brief record instead.

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
)
{
}

Run the validation. First we run with a successfully configured Car object. Then we instantiate a second Car object that is faulty, violating one constraint on each of the three fields.

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() ) );
        }
    }
}

When run.

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
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
4

If using Spring Boot this works well. Even with Spring Reactive Mongo.

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

and validation config:

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();
    }
}
Razor
  • 719
  • 8
  • 18
2

for sbt, use below versions

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"

prathameshr
  • 59
  • 1
  • 2
  • 10
2

I ran into the same issue and the above answers didn't help. I need to debug and find it.

 <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>

After excluding the jsp-api, it worked for me.

Java Carzy
  • 65
  • 1
  • 7
  • This worked with Hadoop. For anyone using gradle : `implementation(group: 'org.apache.hadoop', name: 'hadoop-common', version: '3.3.6') { exclude module: 'jsp-api' }` – ChamodyaDias Aug 04 '23 at 09:28
2

For anyone using Hibernate Validator 7 (org.hibernate.validator:hibernate-validator:7.0.0.Final) as Jakarta Bean Validation 3.0 implementation should use the dependency:

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

as stated in Hibernate Validator documentation

alexis
  • 41
  • 5
1

I am stranded on old technologies, so I had to add the following:

    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>3.0.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.el</artifactId>
        <version>3.0.0</version>
        <scope>test</scope>
    </dependency>

Other answers report the same dependencies, I only updated the versions.

jmgonet
  • 1,134
  • 18
  • 18
1

for anyone using Hibernate Validator 8, you need to use

<dependency>
    <groupId>org.glassfish.expressly</groupId>
    <artifactId>expressly</artifactId>
    <version>5.0.0</version>
 </dependency>
basicange
  • 31
  • 7
0

for gradle :

compile 'javax.el:javax.el-api:2.2.4'
borino
  • 1,720
  • 1
  • 16
  • 24
0

If your server is websphere and you used spring-boot-starter-validation , exclude tomcat-embed-el.

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

    <exclusions>
         <exclusion>
              <groupId>org.apache.tomcat.embed</groupId>
              <artifactId>tomcat-embed-el</artifactId>
         </exclusion>
    </exclusions>
</dependency>
Shapur
  • 498
  • 7
  • 17