diff --git a/javaxval/bean-validation/pom.xml b/javaxval/bean-validation/pom.xml
new file mode 100644
index 0000000000..cdb5a814e2
--- /dev/null
+++ b/javaxval/bean-validation/pom.xml
@@ -0,0 +1,42 @@
+
+ 4.0.0
+
+ com.baeldung.beanvalidation
+ beanvalidation
+ 1.0
+ jar
+ beanvalidation
+ http://maven.apache.org
+
+ UTF-8
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ javax.validation
+ validation-api
+ 2.0.0.Final
+
+
+ org.hibernate
+ hibernate-validator
+ 6.0.2.Final
+
+
+ javax.el
+ javax.el-api
+ 3.0.0
+
+
+ org.glassfish.web
+ javax.el
+ 2.2.4
+
+
+
diff --git a/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/application/Application.java b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/application/Application.java
new file mode 100644
index 0000000000..7966b1046c
--- /dev/null
+++ b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/application/Application.java
@@ -0,0 +1,17 @@
+package com.baeldung.beanvalidation.application;
+
+import javax.validation.Validation;
+import javax.validation.Validator;
+import com.baeldung.beanvalidation.model.User;
+
+public class Application {
+
+ public static void main( String[] args ) {
+ Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
+ User user = new User();
+ user.setName("Mary");
+ user.setEmail("no-email");
+ user.setAge(36);
+ validator.validate(user).stream().forEach(violation -> System.out.println(violation.getMessage()));
+ }
+}
diff --git a/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/container/IntegerContainer.java b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/container/IntegerContainer.java
new file mode 100644
index 0000000000..a6006067cc
--- /dev/null
+++ b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/container/IntegerContainer.java
@@ -0,0 +1,13 @@
+package com.baeldung.beanvalidation.container;
+
+import java.util.Optional;
+import javax.validation.constraints.Positive;
+
+public class IntegerContainer {
+
+ private Optional<@Positive(message = "Value must be a positive integer") Integer> container = Optional.empty();
+
+ public void addElement(int element) {
+ container = Optional.of(element);
+ }
+}
diff --git a/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/container/StringContainer.java b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/container/StringContainer.java
new file mode 100644
index 0000000000..eced996263
--- /dev/null
+++ b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/container/StringContainer.java
@@ -0,0 +1,14 @@
+package com.baeldung.beanvalidation.container;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.constraints.NotNull;
+
+public class StringContainer {
+
+ private List<@NotNull String> container = new ArrayList<>();
+
+ public void addElement(String element) {
+ container.add(element);
+ }
+}
diff --git a/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/model/User.java b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/model/User.java
new file mode 100644
index 0000000000..2a019c37b3
--- /dev/null
+++ b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/model/User.java
@@ -0,0 +1,48 @@
+package com.baeldung.beanvalidation.model;
+
+import java.io.Serializable;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.hibernate.validator.constraints.Email;
+
+public class User implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotNull(message = "Name cannot be null")
+ @Size(min = 2, max = 32, message = "Name must be between 2 and 32 characters")
+ private String name;
+
+ @Email(message = "Email must be a well-formed email address")
+ private String email;
+
+ @Min(value = 1, message = "Age must not be lesser than 1")
+ @Max(value = 99, message = "Age must not be greater than 99")
+ private int age;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+}
diff --git a/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/service/EntityService.java b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/service/EntityService.java
new file mode 100644
index 0000000000..5362e7fbda
--- /dev/null
+++ b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/service/EntityService.java
@@ -0,0 +1,8 @@
+package com.baeldung.beanvalidation.service;
+
+public interface EntityService {
+
+ public String toString();
+
+ public void processEntity();
+}
diff --git a/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/service/UserService.java b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/service/UserService.java
new file mode 100644
index 0000000000..7aae5b3077
--- /dev/null
+++ b/javaxval/bean-validation/src/main/java/com/baeldung/beanvalidation/service/UserService.java
@@ -0,0 +1,45 @@
+package com.baeldung.beanvalidation.service;
+
+import java.io.Serializable;
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import com.baeldung.beanvalidation.model.User;
+
+public class UserService implements EntityService, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Valid
+ private User user;
+
+ @NotNull(message = "FileName cannot be null")
+ @Size(min = 5, max = 10, message = "FileName must be between 5 and 10 characters")
+ private String fileName;
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+
+ @Override
+ public void processEntity() {
+ // process the user here
+ }
+
+ @Override
+ public String toString() {
+ return "UserService [user=" + user + ", fileName=" + fileName + "]";
+ }
+}
diff --git a/javaxval/bean-validation/src/test/java/com/baeldung/beanvalidation/ValidationTest.java b/javaxval/bean-validation/src/test/java/com/baeldung/beanvalidation/ValidationTest.java
new file mode 100644
index 0000000000..1d36cf21f0
--- /dev/null
+++ b/javaxval/bean-validation/src/test/java/com/baeldung/beanvalidation/ValidationTest.java
@@ -0,0 +1,134 @@
+package com.baeldung.beanvalidation;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import com.baeldung.beanvalidation.container.IntegerContainer;
+import com.baeldung.beanvalidation.container.StringContainer;
+import com.baeldung.beanvalidation.model.User;
+import com.baeldung.beanvalidation.service.UserService;
+import java.util.Set;
+import java.util.stream.Collectors;
+import static org.junit.Assert.*;
+
+public class ValidationTest {
+
+ private static Validator validator;
+ private static User user;
+
+ @BeforeClass
+ public static void setUpHibernateValidatorInstance() {
+ validator = Validation.buildDefaultValidatorFactory().getValidator();
+ }
+
+ @BeforeClass
+ public static void setUpUserInstance() {
+ user = new User();
+ }
+
+ @AfterClass
+ public static void tearDownHibernateValidatorInstance() {
+ validator = null;
+ }
+
+ @AfterClass
+ public static void tearDownUserInstance() {
+ user = null;
+ }
+
+ @Test
+ public void givenNullName_whenValidated_thenMessageDescriptorForName() {
+ user.setName(null);
+ user.setEmail("mary@domain.com");
+ user.setAge(36);
+ assertEquals("Name cannot be null", validator.validate(user).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenInvalidEmail_whenValidated_thenMessageDescriptorforEmail() {
+ user.setName("Mary");
+ user.setEmail("no-email");
+ user.setAge(36);
+ assertEquals("Email must be a well-formed email address", validator.validate(user).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenAgeLesserThanLowerBound_whenValidated_thenMessageDescriptorforAge() {
+ user.setName("Mary");
+ user.setEmail("mary@domain.com");
+ user.setAge(0);
+ assertEquals("Age must not be lesser than 1", validator.validate(user).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenAgeGreaterThanUpperBound_whenValidated_thenMessageDescriptorforAge() {
+ user.setName("Mary");
+ user.setEmail("mary@domain.com");
+ user.setAge(100);
+ assertEquals("Age must not be greater than 99", validator.validate(user).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenNullFileName_whenValidated_thenMessageDescriptorforFileName() {
+ user.setName("Mary");
+ user.setEmail("mary@domain.com");
+ user.setAge(36);
+ UserService userService = new UserService();
+ userService.setFileName(null);
+ userService.setUser(user);
+ assertEquals("FileName cannot be null", validator.validate(userService).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenFileNameShortherThanLowerBound_whenValidated_thenMessageDescriptorforFileName() {
+ user.setName("Mary");
+ user.setEmail("mary@domain.com");
+ user.setAge(36);
+ UserService userService = new UserService();
+ userService.setFileName("");
+ userService.setUser(user);
+ assertEquals("FileName must be between 5 and 10 characters", validator.validate(userService).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenFileNameLongerThanUpperBound_whenValidated_thenMessageDescriptorforFileName() {
+ user.setName("Mary");
+ user.setEmail("mary@domain.com");
+ user.setAge(36);
+ UserService userService = new UserService();
+ userService.setFileName("waytoolongfilename");
+ userService.setUser(user);
+ assertEquals("FileName must be between 5 and 10 characters", validator.validate(userService).stream().map(violation -> violation.getMessage()).collect(Collectors.joining()));
+ }
+
+ @Test
+ public void givenNullUserAndNullFileName_whenValidated_thenTwoConstraintViolations() {
+ user.setName(null);
+ user.setEmail("mary@domain.com");
+ user.setAge(36);
+ UserService userService = new UserService();
+ userService.setFileName(null);
+ userService.setUser(user);
+ Set> constraintViolations = validator.validate(userService);
+ assertEquals(2, constraintViolations.size());
+ }
+
+ @Test
+ public void givenNullElement_whenValidated_thenOneConstraintViolation() {
+ StringContainer container = new StringContainer();
+ container.addElement(null);
+ Set> constraintViolations = validator.validate(container);
+ assertEquals(1, constraintViolations.size());
+ }
+
+ @Test
+ public void givenNegativeInteger_whenValidated_thenOneConstraintViolation() {
+ IntegerContainer container = new IntegerContainer();
+ container.addElement(-1);
+ Set> constraintViolations = validator.validate(container);
+ assertEquals(1, constraintViolations.size());
+ }
+}