@@ -63,31 +63,45 @@ private ValidationHelper(Validator validator) {
63
63
@ Nullable
64
64
public Consumer <Object []> getValidationHelperFor (HandlerMethod handlerMethod ) {
65
65
66
- boolean required = false ;
67
- Class <?>[] groups = null ;
66
+ boolean requiresMethodValidation = false ;
67
+ Class <?>[] methodValidationGroups = null ;
68
68
69
69
Validated validatedAnnotation = findAnnotation (handlerMethod , Validated .class );
70
70
if (validatedAnnotation != null ) {
71
- required = true ;
72
- groups = validatedAnnotation .value ();
71
+ requiresMethodValidation = true ;
72
+ methodValidationGroups = validatedAnnotation .value ();
73
73
}
74
74
else if (findAnnotation (handlerMethod , Valid .class ) != null ) {
75
- required = true ;
75
+ requiresMethodValidation = true ;
76
76
}
77
77
78
- for (MethodParameter parameter : handlerMethod .getMethodParameters ()) {
79
- if (required ) {
80
- break ;
81
- }
78
+ Consumer <Object []> parameterValidator = null ;
79
+ MethodParameter [] parameters = handlerMethod .getMethodParameters ();
80
+
81
+ for (int i = 0 ; i < parameters .length ; i ++) {
82
+ MethodParameter parameter = parameters [i ];
82
83
for (Annotation annot : parameter .getParameterAnnotations ()) {
83
84
MergedAnnotations merged = MergedAnnotations .from (annot );
84
- if (merged .isPresent (Valid .class ) || merged .isPresent (Constraint .class ) || merged .isPresent (Validated .class )) {
85
- required = true ;
85
+ if (merged .isPresent (Valid .class ) || merged .isPresent (Constraint .class )) {
86
+ requiresMethodValidation = true ;
87
+ }
88
+ else if (annot .annotationType ().equals (Validated .class )) {
89
+ Class <?>[] groups = ((Validated ) annot ).value ();
90
+ parameterValidator = (parameterValidator != null ?
91
+ parameterValidator .andThen (new MethodParameterValidator (i , groups )) :
92
+ new MethodParameterValidator (i , groups ));
86
93
}
87
94
}
88
95
}
89
96
90
- return (required ? new HandlerMethodValidator (handlerMethod , groups ) : null );
97
+ Consumer <Object []> result = (requiresMethodValidation ?
98
+ new HandlerMethodValidator (handlerMethod , methodValidationGroups ) : null );
99
+
100
+ if (parameterValidator != null ) {
101
+ return (result != null ? result .andThen (parameterValidator ) : parameterValidator );
102
+ }
103
+
104
+ return result ;
91
105
}
92
106
93
107
@ Nullable
@@ -131,10 +145,9 @@ private class HandlerMethodValidator implements Consumer<Object[]> {
131
145
132
146
private final HandlerMethod handlerMethod ;
133
147
134
- @ Nullable
135
148
private final Class <?>[] validationGroups ;
136
149
137
- private HandlerMethodValidator (HandlerMethod handlerMethod , @ Nullable Class <?>[] validationGroups ) {
150
+ HandlerMethodValidator (HandlerMethod handlerMethod , @ Nullable Class <?>[] validationGroups ) {
138
151
Assert .notNull (handlerMethod , "HandlerMethod is required" );
139
152
this .handlerMethod = handlerMethod ;
140
153
this .validationGroups = (validationGroups != null ? validationGroups : new Class <?>[] {});
@@ -143,12 +156,41 @@ private HandlerMethodValidator(HandlerMethod handlerMethod, @Nullable Class<?>[]
143
156
@ Override
144
157
public void accept (Object [] arguments ) {
145
158
146
- Set <ConstraintViolation <Object >> result =
159
+ Set <ConstraintViolation <Object >> violations =
147
160
ValidationHelper .this .validator .forExecutables ().validateParameters (
148
161
this .handlerMethod .getBean (), this .handlerMethod .getMethod (), arguments , this .validationGroups );
149
162
150
- if (!result .isEmpty ()) {
151
- throw new ConstraintViolationException (result );
163
+ if (!violations .isEmpty ()) {
164
+ throw new ConstraintViolationException (violations );
165
+ }
166
+ }
167
+ }
168
+
169
+
170
+ /**
171
+ * Callback to apply validation to a {@link MethodParameter}, typically
172
+ * because it's annotated with Spring's {@code @Validated} rather than with
173
+ * {@code @Valid}.
174
+ */
175
+ private class MethodParameterValidator implements Consumer <Object []> {
176
+
177
+ private final int index ;
178
+
179
+ private final Class <?>[] validationGroups ;
180
+
181
+ MethodParameterValidator (int index , @ Nullable Class <?>[] validationGroups ) {
182
+ this .index = index ;
183
+ this .validationGroups = (validationGroups != null ? validationGroups : new Class <?>[] {});
184
+ }
185
+
186
+ @ Override
187
+ public void accept (Object [] arguments ) {
188
+
189
+ Set <ConstraintViolation <Object >> violations =
190
+ ValidationHelper .this .validator .validate (arguments [this .index ], this .validationGroups );
191
+
192
+ if (!violations .isEmpty ()) {
193
+ throw new ConstraintViolationException (violations );
152
194
}
153
195
}
154
196
}
0 commit comments