Skip to content

Commit 9ab43b1

Browse files
committed
Enhancement in HandlerMethodValidationException
Add dedicated method to Visitor for constraints directly on a RequestBody method parameter (rather than nested). Closes gh-34549
1 parent 09ae080 commit 9ab43b1

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

spring-web/src/main/java/org/springframework/web/method/annotation/HandlerMethodValidationException.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -146,7 +146,12 @@ public void visitResults(Visitor visitor) {
146146
}
147147
RequestBody requestBody = param.getParameterAnnotation(RequestBody.class);
148148
if (requestBody != null) {
149-
visitor.requestBody(requestBody, asErrors(result));
149+
if (result instanceof ParameterErrors errors) {
150+
visitor.requestBody(requestBody, errors);
151+
}
152+
else {
153+
visitor.requestBodyValidationResult(requestBody, result);
154+
}
150155
continue;
151156
}
152157
RequestHeader requestHeader = param.getParameterAnnotation(RequestHeader.class);
@@ -216,6 +221,20 @@ public interface Visitor {
216221
*/
217222
void requestBody(RequestBody requestBody, ParameterErrors errors);
218223

224+
/**
225+
* An additional {@code @RequestBody} callback for validation failures
226+
* for constraints on the method parameter. For example:
227+
* <pre>
228+
* &#064;RequestBody List<&#064;NotEmpty String> ids
229+
* </pre>
230+
* Handle results for {@code @RequestBody} method parameters.
231+
* @param requestBody the annotation declared on the parameter
232+
* @param result the validation result
233+
* @since 7.0
234+
*/
235+
default void requestBodyValidationResult(RequestBody requestBody, ParameterValidationResult result) {
236+
}
237+
219238
/**
220239
* Handle results for {@code @RequestHeader} method parameters.
221240
* @param requestHeader the annotation declared on the parameter

spring-web/src/test/java/org/springframework/web/method/support/HandlerMethodValidationExceptionTests.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
2525
import java.util.function.Predicate;
2626

2727
import jakarta.validation.Valid;
28+
import jakarta.validation.constraints.NotEmpty;
2829
import jakarta.validation.constraints.Size;
2930
import org.junit.jupiter.api.Test;
3031

@@ -67,7 +68,7 @@ class HandlerMethodValidationExceptionTests {
6768

6869

6970
private final HandlerMethod handlerMethod = handlerMethod(new ValidController(),
70-
controller -> controller.handle(person, person, person, person, "", "", "", "", "", ""));
71+
controller -> controller.handle(person, person, person, List.of(), person, "", "", "", "", "", ""));
7172

7273
private final TestVisitor visitor = new TestVisitor();
7374

@@ -84,7 +85,7 @@ void traverse() {
8485

8586
assertThat(this.visitor.getOutput()).isEqualTo("""
8687
@ModelAttribute: modelAttribute1, @ModelAttribute: modelAttribute2, \
87-
@RequestBody: requestBody, @RequestPart: requestPart, \
88+
@RequestBody: requestBody, @RequestBody: requestBodyList, @RequestPart: requestPart, \
8889
@RequestParam: requestParam1, @RequestParam: requestParam2, \
8990
@RequestHeader: header, @PathVariable: pathVariable, \
9091
@CookieValue: cookie, @MatrixVariable: matrixVariable""");
@@ -100,7 +101,7 @@ void traverseRemaining() {
100101

101102
assertThat(this.visitor.getOutput()).isEqualTo("""
102103
Other: modelAttribute1, @ModelAttribute: modelAttribute2, \
103-
@RequestBody: requestBody, @RequestPart: requestPart, \
104+
@RequestBody: requestBody, @RequestBody: requestBodyList, @RequestPart: requestPart, \
104105
Other: requestParam1, @RequestParam: requestParam2, \
105106
@RequestHeader: header, @PathVariable: pathVariable, \
106107
@CookieValue: cookie, @MatrixVariable: matrixVariable""");
@@ -155,6 +156,7 @@ void handle(
155156
@Valid Person modelAttribute1,
156157
@Valid @ModelAttribute Person modelAttribute2,
157158
@Valid @RequestBody Person requestBody,
159+
@RequestBody List<@NotEmpty String> requestBodyList,
158160
@Valid @RequestPart Person requestPart,
159161
@Size(min = 5) String requestParam1,
160162
@Size(min = 5) @RequestParam String requestParam2,
@@ -222,6 +224,11 @@ public void requestBody(RequestBody requestBody, ParameterErrors errors) {
222224
handle(requestBody, errors);
223225
}
224226

227+
@Override
228+
public void requestBodyValidationResult(RequestBody requestBody, ParameterValidationResult result) {
229+
handle(requestBody, result);
230+
}
231+
225232
@Override
226233
public void requestHeader(RequestHeader requestHeader, ParameterValidationResult result) {
227234
handle(requestHeader, result);

0 commit comments

Comments
 (0)