Contraintes de validation des composants et groupes de contraintes
Appliquez les annotations Jakarta Bean Validation avec un regroupement afin d’imposer des règles propres au contexte.
Contraintes de validation des composants et groupes de contraintes est une leçon Spring Boot 4 Complete Guide gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Spring Boot 4 Complete Guide, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Spring Boot 4 Complete Guide comprend 4 leçons au total.
Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.
Why Bean Validation?
In a Spring Boot 4 application you constantly receive untrusted data: request bodies, query params, form submissions. Jakarta Bean Validation (the jakarta.validation API) lets you declare rules as annotations directly on your model fields instead of writing manual if checks everywhere.
- Declarative — the rule lives next to the field it protects.
- Centralized — Spring triggers validation automatically at the controller boundary.
- Consistent — the same annotated class can be validated in the web layer, service layer, or persistence layer.
The reference implementation behind the API is Hibernate Validator, pulled in by the spring-boot-starter-validation dependency.
Adding the Starter
Validation is not bundled with the web starter anymore, so you must add it explicitly. Once present, Hibernate Validator is auto-configured and Spring wires a Validator bean for you.
Add the dependency to your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>Annotating a DTO
You attach constraints to the fields of a Data Transfer Object. Each annotation carries an optional message and validation parameters.
@NotBlank— the string must contain at least one non-whitespace character.@Email— must look like a valid email address.@Size(min, max)— length must fall within range.@Min/@Max— numeric bounds.
public class UserRegistrationRequest {
@NotBlank(message = "Username is required")
@Size(min = 3, max = 20)
private String username;
@NotBlank
@Email(message = "Provide a valid email")
private String email;
@Min(value = 18, message = "Must be at least 18")
private int age;
// getters and setters
}Triggering Validation with @Valid
Annotating the DTO alone does nothing. You must tell Spring to validate the argument by placing @Valid on the controller method parameter. If validation fails, Spring throws a MethodArgumentNotValidException before your method body ever runs, and returns a 400 Bad Request.
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public ResponseEntity<String> register(
@Valid @RequestBody UserRegistrationRequest request) {
// reaches here only if all constraints pass
return ResponseEntity.ok("Registered " + request.getUsername());
}
}The Problem: One DTO, Many Contexts
Imagine the same UserRegistrationRequest is reused for two operations:
- Create — the client must NOT send an
id(the server generates it). - Update — the client MUST send an existing
idto know what to modify.
A field that should be @Null on create but @NotNull on update cannot be expressed with plain annotations, because they always fire. This is exactly the problem constraint groups solve.
Defining Constraint Groups
A constraint group is just a marker interface — an empty interface used purely as a tag. You create one per validation context.
Every constraint annotation accepts a groups attribute. When you assign a constraint to a group, that constraint only runs when validation is requested for that group.
public interface OnCreate {}
public interface OnUpdate {}Assigning Constraints to Groups
Now tag each constraint with the group(s) it belongs to. A constraint with no groups attribute implicitly belongs to the built-in Default group and runs unless you switch groups.
Here the id field obeys opposite rules depending on context:
public class ProductRequest {
@Null(groups = OnCreate.class,
message = "id must be empty when creating")
@NotNull(groups = OnUpdate.class,
message = "id is required when updating")
private Long id;
@NotBlank(groups = {OnCreate.class, OnUpdate.class})
private String name;
@Positive(groups = {OnCreate.class, OnUpdate.class})
private BigDecimal price;
// getters and setters
}Selecting a Group with @Validated
Here is the crucial distinction: @Valid always validates the Default group only and cannot select a group. To activate a specific group you must use Spring's @Validated annotation, which accepts the target group class.
Each endpoint picks the group that matches its operation:
@RestController
@RequestMapping("/api/products")
public class ProductController {
@PostMapping
public ResponseEntity<Void> create(
@Validated(OnCreate.class) @RequestBody ProductRequest req) {
// @Null id, @NotBlank name, @Positive price enforced
return ResponseEntity.status(HttpStatus.CREATED).build();
}
@PutMapping
public ResponseEntity<Void> update(
@Validated(OnUpdate.class) @RequestBody ProductRequest req) {
// @NotNull id enforced instead
return ResponseEntity.ok().build();
}
}@Valid vs @Validated
This pair trips up many developers, so commit it to memory:
@Valid— comes fromjakarta.validation. Works on fields for nested/cascading validation, but cannot specify a group (usesDefault).@Validated— comes fromorg.springframework.validation.annotation. Accepts group classes, and also enables method-level validation on Spring beans. Cannot be placed on a field for cascading.
Rule of thumb: use @Validated(Group.class) at the controller parameter to pick a group; use @Valid on inner object fields to cascade into them.
Cascading and Group Sequences
Two advanced needs come up often:
- Cascading — to validate a nested object, mark its field with
@Valid. Without it, the nested object's constraints are skipped. - Ordering — a
@GroupSequenceruns groups in order and stops at the first group that fails, so you can enforce cheap checks before expensive ones.
@GroupSequence({First.class, Second.class})
public interface OrderedChecks {}
public class OrderRequest {
@NotEmpty(groups = First.class)
private List<@Valid LineItem> items; // @Valid cascades into each item
@AssertTrue(groups = Second.class,
message = "Total must match line items")
public boolean isTotalConsistent() {
return /* expensive cross-field check */ true;
}
}Reading the Errors
When a grouped validation fails, the resulting MethodArgumentNotValidException still carries the standard BindingResult. You can translate it into a clean JSON response with a @RestControllerAdvice handler, mapping each field to its message.
@RestControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> handle(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getFieldErrors().forEach(err ->
errors.put(err.getField(), err.getDefaultMessage()));
return errors;
}
}Quick Check
Test your understanding of how Spring selects a constraint group.
Recap
You learned how to enforce context-specific validation rules with Jakarta Bean Validation in Spring Boot 4:
- Add
spring-boot-starter-validation, then annotate DTO fields with constraints like@NotBlank,@Email,@Size,@Min. - Trigger validation at the controller boundary; a failure yields a 400 via
MethodArgumentNotValidException. - Constraint groups are marker interfaces assigned via each annotation's
groupsattribute, letting one DTO carry different rules per operation (e.g.@Nullon create vs@NotNullon update). - Use
@Validated(Group.class)to select a group —@Validonly runs theDefaultgroup and is for cascading into nested objects. @GroupSequenceorders groups and short-circuits on the first failure;@Validon a collection cascades into each element.
Apprends Java avec un tuteur IA — gratuit
Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.
- Cours
- 21
- Leçons
- 84
Questions Fréquemment Posées
La leçon « Contraintes de validation des composants et groupes de contraintes » est-elle gratuite ?
Oui — le texte complet de « Contraintes de validation des composants et groupes de contraintes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Spring Boot 4 Complete Guide, passe à CoddyKit PRO. Le cours Spring Boot 4 Complete Guide comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Contraintes de validation des composants et groupes de contraintes » ?
Appliquez les annotations Jakarta Bean Validation avec un regroupement afin d’imposer des règles propres au contexte. Tu pratiques Spring Boot 4 Complete Guide avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer Spring Boot 4 Complete Guide ?
Aucune expérience préalable n'est requise. Spring Boot 4 Complete Guide sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.
Combien de temps prend la leçon « Contraintes de validation des composants et groupes de contraintes » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon Spring Boot 4 Complete Guide ?
Oui. Chaque leçon Spring Boot 4 Complete Guide inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Contraintes de validation des composants et groupes de contraintes
- Création d’annotations de contrainte personnalisées
- Gestion globale des exceptions avec @ControllerAdvice
- Réponses ProblemDetail conformes à la RFC 7807