What is Bean Validation (JSR-380) and how does Spring expose a Jakarta Validator you can inject?
answer
- jakarta.validation.Validator
- LocalValidatorFactoryBean = 3 interfaces
- validate() returns Set<ConstraintViolation>
- starter-validation = Hibernate Validator
- factory bean -> DI-able custom validators
basics
~10 sBean Validation is a standard for declaring rules on fields with annotations like @NotNull and @Size. Spring's LocalValidatorFactoryBean builds a Validator you can inject and call validate() on.
solid answer
~40 sBean Validation (JSR-380 / Jakarta Validation) is a specification for expressing constraints on object fields and methods using annotations such as @NotNull, @Size, @Email, and @Min; a provider like Hibernate Validator enforces them. Spring integrates it via LocalValidatorFactoryBean, which implements both the Jakarta jakarta.validation.Validator and Spring's own org.springframework.validation.Validator. Boot auto-configures this bean when a provider is on the classpath (spring-boot-starter-validation). You inject jakarta.validation.Validator and call validate(obj), getting back a Set<ConstraintViolation<T>>; each violation carries the message, property path, and invalid value. An empty set means valid. The key advantage of the Spring-managed factory bean over building a ValidatorFactory yourself is that it makes custom ConstraintValidators Spring beans, so they can be dependency-injected.
code
java · 21 linesimport jakarta.validation.Validator;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.constraints.*;
import org.springframework.stereotype.Service;
import java.util.Set;
class Order {
@NotBlank String customer;
@Min(1) int quantity;
}
@Service
class OrderChecker {
private final Validator validator; // jakarta.validation.Validator
OrderChecker(Validator validator) { this.validator = validator; }
boolean isValid(Order order) {
Set<ConstraintViolation<Order>> v = validator.validate(order);
return v.isEmpty(); // no exception thrown; inspect v for messages
}
}go deeper
Know the common constraint annotations and that LocalValidatorFactoryBean gives an injectable Validator whose validate() returns violations.
Explain the spec-vs-provider split and that Boot auto-configures the factory bean; know validate() doesn't throw.
Explain the three interfaces LocalValidatorFactoryBean implements and why the Spring factory bean enables DI into custom validators.
Discuss SpringConstraintValidatorFactory, MessageSource interpolation wiring, and when programmatic vs declarative validation is architecturally right.
**Bean Validation** (originally JSR-303, then JSR-349, then JSR-380 for Bean Validation 2.0, now branded **Jakarta Validation**) is a Java specification for declaring and enforcing **constraints** on object state. You annotate fields, getters, method parameters, or return values with **constraint annotations** and a runtime **provider** checks them. **Provider vs spec:** The spec lives in the `jakarta.validation` package (`jakarta.validation.Validator`, `jakarta.validation.ConstraintViolation`, the annotations in `jakarta.validation.constraints.*`). The most common implementation is **Hibernate Validator** (unrelated to Hibernate ORM). You need both on the classpath; `spring-boot-starter-validation` pulls them in. **Standard constraints** include `@NotNull` (not null), `@NotBlank` (non-null, non-whitespace string), `@NotEmpty` (non-empty collection/string), `@Size(min, max)`, `@Min`/`@Max`, `@Positive`, `@Email`, `@Pattern(regexp=...)`, `@Past`/`@Future`, `@Digits`, and `@DecimalMin`. **How Spring exposes a Validator:** `org.springframework.validation.beanvalidation.LocalValidatorFactoryBean` is a Spring `FactoryBean` that bootstraps a Jakarta `ValidatorFactory` and adapts it. Crucially it implements **three** interfaces at once: `jakarta.validation.ValidatorFactory`, `jakarta.validation.Validator`, and Spring's older `org.springframework.validation.Validator`. So you can inject it as any of those. In Spring Boot, `ValidationAutoConfiguration` registers a `LocalValidatorFactoryBean` automatically (named `defaultValidator`) whenever a Bean Validation provider is present and no other `Validator` bean is defined. **Programmatic use:** ```java @Autowired jakarta.validation.Validator validator; Set<ConstraintViolation<Order>> violations = validator.validate(order); ``` Each `ConstraintViolation` exposes `getMessage()`, `getPropertyPath()`, `getInvalidValue()`, and the constraint descriptor. An **empty set** means the object satisfied all constraints. Programmatic `validate()` does **not** throw — it returns violations; you decide what to do. **Why the Spring factory bean matters:** If you built a `ValidatorFactory` yourself via `Validation.buildDefaultValidatorFactory()`, any custom `ConstraintValidator` would be instantiated by the provider with no access to the Spring context. `LocalValidatorFactoryBean` installs a `SpringConstraintValidatorFactory`, so your custom validators become **Spring-managed** and can `@Autowired` other beans (e.g., a repository to check uniqueness). It also wires a `MessageSource` for message interpolation and can be told the constraint mappings. **Gotchas:** (1) Injecting `org.springframework.validation.Validator` vs `jakarta.validation.Validator` — the same bean satisfies both, but pick the type your code needs. (2) Validation is **not automatic** on plain bean method calls just because fields are annotated — programmatic `validate()` or the `@Validated` method-validation mechanism must trigger it. (3) `@Valid` on a nested field triggers **cascade** validation into that object graph. **When to use programmatic validation:** service-layer checks where you want to inspect violations without an exception, batch validation, or conditional flows. For declarative method validation prefer `@Validated` + `MethodValidationPostProcessor` (a sibling concept covered separately).
- Does calling validator.validate() throw when the object is invalid?No. Programmatic validate() returns a Set<ConstraintViolation>; an empty set means valid. It never throws for constraint failures — the caller decides. Only the @Validated method-validation path throws ConstraintViolationException.
- Why prefer LocalValidatorFactoryBean over Validation.buildDefaultValidatorFactory()?The Spring factory bean uses a SpringConstraintValidatorFactory, so custom ConstraintValidators are Spring beans and can @Autowired dependencies; it also hooks Spring's MessageSource for message interpolation.
saying these in an interview costs you the question
- Thinking annotating fields alone validates them automatically on any method call
- Claiming validate() throws an exception on invalid input
- Confusing Hibernate Validator with Hibernate ORM
- Assuming you must build the ValidatorFactory manually in Spring Boot