Boost Spring Boot Validation with Apache BVal: A Complete Hands‑On Guide
This tutorial shows how to replace Spring Boot's default Hibernate Validator with Apache BVal, covering Maven dependencies, basic bean validation, property‑level checks, value validation, custom constraints, and seamless Spring Boot integration with full code examples.
Overview
Apache BVal is a lightweight, high‑performance implementation of the Jakarta Bean Validation 3.0 (JSR‑380) specification. It can replace Spring Boot's default Hibernate Validator and adds a collection of non‑standard constraints via the bval-extras module.
Maven dependencies
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-jsr</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>bval-extras</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>Standard bean validation
public class User {
@NotNull
private String email;
@Size(min = 6, message = "Password must be at least 6 characters")
private String password;
@Size(min = 1, max = 20)
private String name;
@Min(value = 1, message = "Age must be >= 1")
@Max(value = 150, message = "Age must be <= 150")
private Integer age;
// getters & setters
}Create a singleton ValidatorFactory (expensive operation) and obtain a Validator from it:
ValidatorFactory validatorFactory = Validation
.byProvider(ApacheValidationProvider.class)
.configure()
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();Validate an instance:
User user = new User("[email protected]", "12345", "pack_xg", 0);
Set<ConstraintViolation<User>> violations = validator.validate(user);
violations.forEach(cv -> System.err.println(cv.getPropertyPath() + ", " + cv.getMessage()));Sample output:
age, Age must be >= 1
password, Password must be at least 6 charactersValidate a specific property
Set<ConstraintViolation<User>> ageViolations = validator.validateProperty(user, "age");
ageViolations.forEach(cv -> System.err.println(cv.getPropertyPath() + ", " + cv.getMessage()));The validateProperty() method checks only the given attribute.
Validate a value without an object
Set<ConstraintViolation<User>> valueViolations = validator.validateValue(User.class, "age", 200);
valueViolations.forEach(cv -> System.err.println(cv.getPropertyPath() + ", " + cv.getMessage()));Output:
age, Age must be <= 150Extra constraints (bval‑extras)
The bval-extras module adds many useful non‑standard annotations such as @IBAN, @Isbn, @Visa, @Domain, @InetAddress, @Directory, etc.
public class User {
// ... standard fields
@Visa(message = "Invalid card number")
private String cardNumber;
@IBAN(message = "Invalid IBAN")
private String iban;
@Domain(message = "Invalid website")
private String website;
@InetAddress(message = "Invalid IP address")
private String ip;
@Directory(message = "Not a directory")
private File dir = new File(".");
}Validate an instance that uses these constraints:
User user = new User("[email protected]", "123456", "pack_xg", 100,
"4242424242424242", "1234-5678", "www.pack.com", "192.168.1.2550",
new File("d:/123.txt"));
Set<ConstraintViolation<User>> violations = validator.validate(user);
violations.forEach(cv -> System.err.println(cv.getPropertyPath() + ", " + cv.getMessage()));Sample output:
ip, Invalid IP address
iban, Invalid IBAN
dir, Not a directoryIntegration with Spring Boot
No additional configuration is required because BVal follows the standard JSR annotations. To replace the default Hibernate implementation, expose the BVal factory and validator as Spring beans:
@Bean(destroyMethod = "close")
public ValidatorFactory validatorFactory() {
return Validation.byProvider(ApacheValidationProvider.class)
.configure()
.buildValidatorFactory();
}
@Bean
public Validator bvalValidator(ValidatorFactory validatorFactory) {
return validatorFactory.getValidator();
}When spring-boot-starter-validation is on the classpath, these beans override the auto‑configured Hibernate validator.
Controller example
@PostMapping("/create")
public Object create(@Validated @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
return result.getFieldErrors()
.stream()
.map(err -> err.getField() + ", " + err.getDefaultMessage())
.toList();
}
return user;
}The endpoint returns a list of field, message strings when validation fails.
Conclusion
Apache BVal can be used as a drop‑in replacement for Hibernate Validator, offering full JSR‑380 compliance plus a rich set of extra constraints. Combined with Spring Boot's validation infrastructure, it provides a concise and extensible solution for both standard and custom data validation requirements.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
