0
# Validation Groups
1
2
Group-based validation for conditional constraint application and validation sequencing with group conversion support during cascading validation.
3
4
## Capabilities
5
6
### Default Group
7
8
Marker interface representing the default validation group.
9
10
```java { .api }
11
/**
12
* Default validation group
13
* Constraints belong to this group unless explicitly assigned to other groups
14
*/
15
interface Default {}
16
```
17
18
### Group Sequence
19
20
Annotation for defining sequential validation of groups.
21
22
```java { .api }
23
/**
24
* Defines a sequence of groups that should be validated sequentially
25
* If validation fails for one group, subsequent groups are not validated
26
*/
27
@Target({TYPE})
28
@Retention(RUNTIME)
29
@interface GroupSequence {
30
/**
31
* The sequence of groups to validate
32
* @return array of group classes
33
*/
34
Class<?>[] value();
35
}
36
```
37
38
### Group Conversion
39
40
Annotation for converting validation groups during cascading validation.
41
42
```java { .api }
43
/**
44
* Converts validation groups during cascaded validation
45
* Applied to fields, method parameters, and return values marked with @Valid
46
*/
47
@Target({FIELD, METHOD, CONSTRUCTOR, PARAMETER, TYPE_USE})
48
@Retention(RUNTIME)
49
@Repeatable(ConvertGroup.List.class)
50
@interface ConvertGroup {
51
/**
52
* The source group to convert from
53
* @return source group class
54
*/
55
Class<?> from();
56
57
/**
58
* The target group to convert to
59
* @return target group class
60
*/
61
Class<?> to();
62
63
/**
64
* Container for multiple ConvertGroup annotations
65
*/
66
@Target({FIELD, METHOD, CONSTRUCTOR, PARAMETER, TYPE_USE})
67
@Retention(RUNTIME)
68
@interface List {
69
ConvertGroup[] value();
70
}
71
}
72
```
73
74
**Usage Examples:**
75
76
```java
77
import jakarta.validation.*;
78
import jakarta.validation.constraints.*;
79
import jakarta.validation.groups.*;
80
81
// 1. Define validation groups
82
interface BasicInfo {}
83
interface AdvancedInfo {}
84
interface AdminInfo {}
85
86
// 2. Apply constraints to specific groups
87
public class User {
88
@NotNull(groups = {BasicInfo.class, AdvancedInfo.class})
89
@Size(min = 2, max = 50, groups = BasicInfo.class)
90
private String name;
91
92
@NotNull(groups = BasicInfo.class)
93
@Email(groups = BasicInfo.class)
94
private String email;
95
96
@Min(value = 18, groups = AdvancedInfo.class)
97
private Integer age;
98
99
@NotNull(groups = AdminInfo.class)
100
private String adminRole;
101
102
// constructors, getters, setters...
103
}
104
105
// 3. Group sequence for ordered validation
106
@GroupSequence({BasicInfo.class, AdvancedInfo.class, AdminInfo.class})
107
interface UserValidationSequence {}
108
109
// 4. Validate with specific groups
110
public class ValidationGroupExample {
111
private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
112
113
public void validateUserGroups() {
114
User user = new User();
115
user.setName(""); // Invalid for BasicInfo
116
user.setAge(15); // Invalid for AdvancedInfo
117
118
// Validate only basic information
119
Set<ConstraintViolation<User>> basicViolations =
120
validator.validate(user, BasicInfo.class);
121
System.out.println("Basic validation violations: " + basicViolations.size());
122
123
// Validate advanced information
124
Set<ConstraintViolation<User>> advancedViolations =
125
validator.validate(user, AdvancedInfo.class);
126
System.out.println("Advanced validation violations: " + advancedViolations.size());
127
128
// Validate with sequence (stops at first failing group)
129
Set<ConstraintViolation<User>> sequenceViolations =
130
validator.validate(user, UserValidationSequence.class);
131
System.out.println("Sequence validation violations: " + sequenceViolations.size());
132
133
// Validate multiple groups at once
134
Set<ConstraintViolation<User>> multiGroupViolations =
135
validator.validate(user, BasicInfo.class, AdvancedInfo.class);
136
System.out.println("Multi-group validation violations: " + multiGroupViolations.size());
137
}
138
}
139
140
// 5. Group conversion in cascading validation
141
public class Order {
142
@NotNull
143
@Valid
144
@ConvertGroup(from = Default.class, to = BasicInfo.class)
145
private User customer; // When validating Order, customer uses BasicInfo group
146
147
@Valid
148
@ConvertGroup(from = BasicInfo.class, to = AdvancedInfo.class)
149
@ConvertGroup(from = AdvancedInfo.class, to = AdminInfo.class)
150
private User assignedAgent; // Multiple group conversions
151
152
@NotNull(groups = BasicInfo.class)
153
private String orderNumber;
154
155
// constructors, getters, setters...
156
}
157
158
// 6. Dynamic group validation
159
public class UserRegistrationService {
160
private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
161
162
public ValidationResult validateUser(User user, String validationLevel) {
163
Class<?>[] groups;
164
165
switch (validationLevel) {
166
case "basic":
167
groups = new Class<?>[]{BasicInfo.class};
168
break;
169
case "advanced":
170
groups = new Class<?>[]{BasicInfo.class, AdvancedInfo.class};
171
break;
172
case "admin":
173
groups = new Class<?>[]{UserValidationSequence.class};
174
break;
175
default:
176
groups = new Class<?>[]{Default.class};
177
}
178
179
Set<ConstraintViolation<User>> violations = validator.validate(user, groups);
180
return new ValidationResult(violations.isEmpty(), violations);
181
}
182
}
183
184
// 7. Conditional validation based on object state
185
public class ConditionalUser {
186
@NotNull
187
private String username;
188
189
@NotNull(groups = PremiumUser.class)
190
@Size(min = 10, groups = PremiumUser.class)
191
private String premiumFeature;
192
193
private boolean isPremium;
194
195
public Set<ConstraintViolation<ConditionalUser>> validate() {
196
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
197
198
if (isPremium) {
199
return validator.validate(this, Default.class, PremiumUser.class);
200
} else {
201
return validator.validate(this, Default.class);
202
}
203
}
204
205
interface PremiumUser {}
206
}
207
```