Hibernate Validator: the reference implementation behind Jakarta Bean Validation
Hibernate Validator - Jakarta Validation Reference Implementation
At a glance
- What is it?
- Hibernate Validator is the reference implementation of Jakarta Validation 3.1, the specification that defines the metadata model and API for JavaBean and method validation, with annotations as the default metadata source and XML descriptors to override them. It needs JDK 17 or above, and it requires an EL implementation to be added explicitly on plain Java SE because the API alone is not enough to evaluate a constraint.
- Who is it for?
- Hibernate Validator suits a Java team that has decided to use the Jakarta Bean Validation specification and wants the reference implementation behind it, since the specification defines the semantics and this project defines the behaviour, including the parts the spec leaves to the implementation.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A specification and its reference implementation
Hibernate Validator is the reference implementation of Jakarta Validation 3.1. Jakarta Validation defines a metadata model and API for JavaBean as well as method validation.
The distinction between the specification and the implementation is the thing to understand before adopting either. The specification, hosted at beanvalidation.org, defines what the annotations mean, what a constraint violation is, and how a validator should behave. Hibernate Validator is the artefact that implements that contract. The README also notes that the Jakarta Validation API and TCK are provided and distributed under the same Apache 2.0 licence, which is what makes the reference implementation meaningful: the TCK is a test suite that any conforming implementation has to pass.
The default metadata source is annotations, with the ability to override and extend the metadata through the use of XML validation descriptors.
That override capability is the design decision with real consequences. Annotations are convenient and live next to the code they constrain, but they cannot express everything, and they cannot be changed without recompiling. XML descriptors can override an annotation, add constraints to a class the library did not write, and carry configuration that varies per deployment. The trade-off is that you now have two sources of truth for your constraints, and the resolution order between them is something a team has to understand before it starts using both.
Method validation, meaning constraints on the parameters and return value of a method rather than on a field, is part of the same specification and the same implementation, which is why the CDI integration is a first-class part of the project rather than an add-on.
The EL dependency that trips up plain Java SE
The installation section contains the detail that catches people out, and the README states it plainly: you also need an API and implementation of the Unified Expression Language, and these dependencies must be explicitly added in an SE environment. In a Jakarta EE environment they are often already provided.
This is not an incidental requirement. A constraint can carry an expression, and evaluating that expression needs an expression language implementation. The reference implementation used in the documentation is expressly, from the GlassFish project.
<dependency>
<groupId>org.glassfish.expressly</groupId>
<artifactId>expressly</artifactId>
<version>6.0.0</version>
</dependency>The contrast between SE and Jakarta EE is the practical point. A Jakarta EE container ships an EL implementation, so an application deployed there gets it for free and adding it manually risks a version conflict with the container. On plain Java SE, or in a plain main method, nothing provides it, and forgetting the dependency produces a failure at validation time rather than at startup.
The main dependency itself is added the usual way, through Maven, Ivy or Gradle, and the version in the README matches the release at the top of the file, 9.2.0.Beta1.
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>9.2.0.Beta1</version>
</dependency>CDI integration as a separate artifact
Jakarta Validation defines integration points with CDI. The README explains that if your application runs in an environment which does not provide this integration out of the box, you may use the Hibernate Validator CDI portable extension by adding a separate dependency.
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator-cdi</artifactId>
<version>9.2.0.Beta1</version>
</dependency>The separation into a distinct artifact is the sensible design. CDI is a dependency with a scope of its own, and a project that does not use CDI should not have to resolve it. The repository layout mirrors the module structure, with a cdi/ directory alongside engine/, annotation-processor/, distribution/, documentation/, integrationtest/, performance/ and tck-runner/.
The engine is the core, the CDI module is the container integration, the annotation-processor module is a build-time tool, the tck-runner is the harness that runs the specification's test suite, and the distribution directory produces the archive that the installation instructions describe.
There is also a bom/ directory, a build-time bill of materials, and a parents/ directory for the shared parent POM configuration, both of which are the usual way a multi-module project keeps its modules on consistent versions.
One structural oddity worth noting: there are both a src/ directory and the module directories. In a project this size that usually means the src/ tree holds shared resources or a build output rather than the primary sources, but the README does not explain the layout, so it is not something to rely on without reading the build files.
The annotation processor catches constraint mistakes at build time
The optional jar hibernate-validator-annotation-processor is the feature most teams discover late, and it is worth understanding what it is for.
The README describes it as an optional jar which can be integrated with your build environment respectively IDE to verify that constraint annotations are correctly used.
That verification is the point. Constraint annotations have failure modes that a compiler will not catch. A @NotNull on a field that is always set, a @Size whose max is smaller than the min, a constraint annotation on a field the class has no setter for, a message template that references a property the object does not have. These are all mistakes the type system is happy with and that only surface when a user submits bad data.
Running the processor at build time turns a runtime data error into a compile error, which is a much cheaper place to find it. The README points at the online documentation for the details, and the repository has a dedicated annotation-processor/ module for it.
The word optional matters. It is a separate jar, so it has to be added to the annotation processor path of the build, and the README does not spell out the configuration for each build tool. A team that adopts the processor early pays a small setup cost and gets the whole class of errors caught, which is a better trade than discovering the misconfigured @Size three months after release.
The TCK runs in standalone and container modes
The Continuous Integration section describes a build that runs on Linux and Windows and executes the TCK both in standalone and in container modes, with the tck-runner README describing the modes.
That detail explains what the reference implementation actually is. The TCK is the Jakarta Validation technology compatibility kit, a suite of tests derived from the specification. An implementation that passes the TCK is conformant. Running it in standalone mode tests the engine on its own, and running it in container mode tests the integration with a CDI container, because method validation and lifecycle integration are only meaningful inside a container.
So the project is not just a library with tests, it is a library that is continuously checked against the specification by an independent suite. That is a meaningful difference in how much confidence to place in a constraint implementation, and it is the main argument for using this artefact over another implementation of the same specification.
The continuous integration itself runs on ci.hibernate.org, and the repository also includes a GitHub action build file at .github/workflows/build.yml for people who want to run builds on their own forks. There is a Jenkinsfile at the root as well, plus jenkins/ and .mvn/ directories.
The other quality signals in the README are the SonarCloud coverage and quality gate badges, a Develocity build scan badge, and a Reproducible Builds badge pointing at the jvm-repo-rebuild project, which verifies that the published artefact can be rebuilt byte for byte from the source.
Three release lines published on the same day
The release history is unusual and worth understanding before you pin a version.
The three most recent releases are 9.2.0.Beta1 from 2026-10-13, 9.1.5.Final from 2026-10-13, and 9.0.2.Final from 2026-10-13. All three on the same day.
That is maintenance branch practice rather than confusion. The 9.0 line and the 9.1 line are being kept on their own branches with their own patch releases, while 9.2 is in beta ahead of its final. A team that pinned an older 9.0 release and did not want the 9.0.2 change is on a supported line rather than on an abandoned one, and a team that wants the newest features tracks 9.2.
The version in the README header is 9.2.0.Beta1, dated 2026-10-13, which matches the newest tag. The last push was on 2026-10-15, so the tree is two days ahead of the last release.
The system requirement is JDK 17 or above. That is the constraint most likely to bite an adopter, since it rules out the long-lived Java 8 deployments that a lot of enterprise applications still have, and it means a JDK 17 or later runtime in the container or the CI image.
Licensing is clean and stated in the README: Hibernate Validator itself as well as the Jakarta Validation API and TCK are all provided and distributed under the Apache Software License 2.0, with license.txt in the repository. The project also has a dco.txt and a MAINTAINERS.txt, and the AUTHORS.txt file.
The distribution route is a downloadable archive, and the installation instructions tell you to copy dist/hibernate-validator-<version>.jar together with all jar files from dist/lib/required into the classpath, with logging handled through the JBoss Logging API, an abstraction layer that delegates to log4j or the JDK logging framework once you add one.
Editorial conclusion
Hibernate Validator suits a Java team that has decided to use the Jakarta Bean Validation specification and wants the reference implementation behind it, since the specification defines the semantics and this project defines the behaviour, including the parts the spec leaves to the implementation. It is the wrong tool if you have not chosen to standardise on Bean Validation, because adopting it means adopting every constraint the specification defines along with the annotation processor and the XML descriptor machinery. Before you add it, check that your runtime provides an EL implementation, since the README says those dependencies must be added explicitly in an SE environment, and confirm the version line you pick, because the current release is a Beta while two Final lines are being maintained in parallel at the same time.
Frequently asked questions
What do I need to add to use Hibernate Validator in a Java SE project?
The main artifact plus an API and implementation of the Unified Expression Language. The README says these dependencies must be explicitly added in an SE environment, and gives org.glassfish.expressly:expressly:6.0.0 as the example.
What is the difference between annotations and XML validation descriptors?
Annotations are the default metadata source. The XML validation descriptors allow the metadata to be overridden and extended, which means constraints can be changed or added without recompiling, at the cost of having two sources of truth.
What does the Hibernate Validator annotation processor do?
It is an optional jar that can be integrated with your build environment or IDE to verify that constraint annotations are correctly used, turning constraint mistakes into build time failures rather than runtime errors.
What Java version does Hibernate Validator require?
JDK 17 or above, according to the system requirements in the README.
How does Hibernate Validator test itself against the specification?
The continuous integration build runs on Linux and Windows and executes the TCK both in standalone and in container modes, and the official CI service is hosted on ci.hibernate.org.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hibernate-hibernate-validator)Was this useful?