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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Boost Spring Boot Validation with Apache BVal: A Complete Hands‑On Guide

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 characters

Validate 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 <= 150

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

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

Validation result illustration
Validation result illustration

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.

JavaBean ValidationValidationSpring BootApache BVal
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.