Hibernate Validator
last modified January 27, 2024
In this article we show how to validate data with Hibernate validator. Validating input received from the user to maintain data integrity is an important part of application logic. Validation is incorporated in Java web frameworks such as Stripes, Ninja framework, or Play framework.
Bean validation
Bean Validation is a validation model introduced in Java EE 6 platform. The Bean Validation model is supported by constraints in the form of annotations placed on a field, method, or class of a JavaBeans component. It is also possible to use XML validation descriptors.
Hibernate validator definition
Hibernate Validator is the reference implementation of Bean Validation. Hibernate Validator allows to express and validate application constraints. The default metadata source are annotations, with the ability to override and extend through the use of XML. It is not tied to a specific application tier or programming model and is available for both server and client application programming.
Hibernate validator command line application
In the following example, we use the Hibernate Validator in a simple command line application.
<?xml version="1.0" encoding="UTF-8"?> <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.zetcode</groupId> <artifactId>HibernateValidation</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <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> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator-cdi</artifactId> <version>5.2.4.Final</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> <scope>provided</scope> </dependency> </dependencies> </project>
The Maven pom.xml
contains dependencies for the Hibernate Validator and
for the Lombok library. The Lombok is used to reduce some boilerplate.
package com.zetcode.bean; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import lombok.Data; @Data public class Car { private Long Id; @NotNull @Size(min=4, max=50) private String name; @Min(value = 1000) @Max(value = 5000000, message="There is no such expensive car") private int price; public Car() {} public Car(String name, int price) { this.name = name; this.price = price; } }
We have a Car
bean where we validate data.
@Data public class Car {
The Car
bean is decorated with the lombok's @Data
annotation.
It automatically creates the getter and setter methods, equals
method,
toString
method, and hashCode
method.
@NotNull @Size(min=4, max=50) private String name;
The @NotNull
annotation says that the name
property
may not be null
. The @Size
annotation sets the
minimum and maximum size for the property.
@Min(value = 1000) @Max(value = 5000000, message="There is no such expensive car") private int price;
The @Min
constraint sets the minimum value for the price
property. The message
element is used to create the error message.
package com.zetcode.client; import com.zetcode.bean.Car; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; public class ClientApp { private static Validator validator; public static void main(String[] args) { Car car1 = new Car("Volvo", 29000); Car car2 = new Car("Skoda", 900); Car car3 = new Car(null, 29000); Car car4 = new Car("Cit", 21000); Car car5 = new Car("Bentley", 8000000); ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); validate(car1); validate(car2); validate(car3); validate(car4); validate(car5); } public static void validate(Car car) { Set<ConstraintViolation<Car>> cvs = validator.validate(car); for (ConstraintViolation<Car> cv : cvs) { System.out.println(cv.getPropertyPath() + ": " + cv.getMessage()); } } }
In the client application, we create five car objects and validate them.
Car car1 = new Car("Volvo", 29000); Car car2 = new Car("Skoda", 900); Car car3 = new Car(null, 29000); Car car4 = new Car("Cit", 21000); Car car5 = new Car("Bentley", 8000000);
Five car objects are created. Four cars have values that do not pass the validation process. For example, the price of the Skoda car is too low; i.e. below the minimum 1000 value.
ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator();
A validation factory is used with the buildDefaultValidatorFactory
method.
From the factory, we get the validator with the getValidator
method.
It is recommended to cache the validator factory because it is expensive to create.
Set<ConstraintViolation<Car>> cvs = validator.validate(car);
A car is validated using the validator's validate
method.
for (ConstraintViolation<Car> cv : cvs) { System.out.println(cv.getPropertyPath() + ": " + cv.getMessage()); }
We print the error messages for constraint violations.
price: must be greater than or equal to 1000 name: may not be null name: size must be between 4 and 50 price: There is no such expensive car
When running the application, we receive these error messages.
Hibernate validator web application
In the second example, we utilize Hibernate Validator in a web application. The application is deployed on Apache Tomcat server. The sources for this application are available at author's Github repository.
The figure shows the project structure in NetBeans.
<?xml version="1.0" encoding="UTF-8"?> <Context path="/HibernateValidation"/>
The context.xml
file contains the context path of
the application.
<?xml version="1.0" encoding="UTF-8"?> <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.zetcode</groupId> <artifactId>HibernateValidation2</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>HibernateValidation2</name> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <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> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator-cdi</artifactId> <version>5.2.4.Final</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project>
The Maven pom.xml
contains dependencies for the Java EE Web API,
Hibernate Validator, and for the Lombok library.
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Validation</title> </head> <body> <p> Enter your name and email: </p> <form method="post" action="Greet"> Name: <input type="text" name="username"> <br> Email: <input type="text" name="email"> <br> <input type="submit" value="Submit"> </form> </body> </html>
The index.jsp
is the entry point to our application. It contains
a HTML form with two fields: username and email. The values entered into these
fields are going to be validated by the application.
<form method="post" action="Greet"> ... </form>
Upon submitting the form, the Greet
servlet is invoked.
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Greeting</title> </head> <body> Hello <c:out value="${param.username}"/>! <br> Your email is <c:out value="${param.email}"/>. </body> </html>
When the input data passes the validation test, the hello.jsp
page
is displayed. It displays the entered data.
<%@page contentType="text/html" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Error</title> </head> <body> <p> <c:forEach var="err" items="${errMsg}"> <c:out value="${err}"/> <br> </c:forEach> </p> </body> </html>
If the validation fails, the valError.jsp
is displayed. It shows
the error messages stored in the errMsg
attribute. The attribute
is set during the validation process.
package com.zetcode.bean; import javax.validation.constraints.Pattern; import lombok.Data; import org.hibernate.validator.constraints.NotEmpty; @Data public class User { @NotEmpty private String name; @NotEmpty @Pattern(regexp="^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\\.[a-zA-Z.]{2,5}", message="Please provide a valid email address") private String email; }
The User
bean is decorated with Lombok and Hibernate Validator
annotations.
@NotEmpty private String name;
The @NotEmpty
annotation causes that the user name may not be empty.
@NotEmpty @Pattern(regexp="^[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\\.[a-zA-Z.]{2,5}", message="Please provide a valid email address") private String email;
The email may not be empty and must match the given patter. The pattern
is set with the @Pattern
annotation.
package com.zetcode.util; import com.zetcode.bean.User; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; public class DoValidate { public static List<String> validate(User user) { List<String> errors = new ArrayList(); ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set<ConstraintViolation<User>> cvs = validator.validate(user); if (!cvs.isEmpty()) { for (ConstraintViolation<User> cv : cvs) { StringBuilder err = new StringBuilder(); err.append(cv.getPropertyPath()); err.append(" "); err.append(cv.getMessage()); errors.add(err.toString()); } } return errors; } }
The validation is performed in the DoValidate
utility class.
if (!cvs.isEmpty()) { for (ConstraintViolation<User> cv : cvs) { StringBuilder err = new StringBuilder(); err.append(cv.getPropertyPath()); err.append(" "); err.append(cv.getMessage()); errors.add(err.toString()); } }
When there are constraint violations, we create a list of error messages.
The getMessage
method gets the error message of the constraint
violation.
return errors;
The list of error messages are returned to the caller. The list is empty if no violations were detected.
package com.zetcode.web; import com.zetcode.bean.User; import com.zetcode.util.DoValidate; import java.io.IOException; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "Greeting", urlPatterns = {"/Greet"}) public class Greeting extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); String page = "/hello.jsp"; String username = request.getParameter("username"); String email = request.getParameter("email"); User user = new User(); user.setName(username); user.setEmail(email); List<String> errors = DoValidate.validate(user); if (!errors.isEmpty()) { request.setAttribute("errMsg", errors); page = "/valError.jsp"; } else { request.setAttribute("user", user); } RequestDispatcher disp = getServletContext().getRequestDispatcher(page); disp.forward(request, response); } }
The Greeting
servlet retrieves the request data and calls the
DoValidate.validate
utility method. Depending on the outcome
of the validation, the servlet dispatches to the hello.jsp
or
valError.jsp
pages.
The application responds with an error message if the email has an incorrect format.
Source
Hibernate Validator documentation
This was the validation filter tutorial. We have built a console and a web application using Hibernate Validator, JSTL, JSP, Apache Tomcat, and Maven.
Author
List all Java tutorials.