20
20
import java .io .StringWriter ;
21
21
import java .util .Date ;
22
22
import java .util .LinkedHashMap ;
23
+ import java .util .List ;
23
24
import java .util .Map ;
24
25
import java .util .Optional ;
25
26
32
33
import org .springframework .util .StringUtils ;
33
34
import org .springframework .validation .BindingResult ;
34
35
import org .springframework .validation .ObjectError ;
36
+ import org .springframework .validation .method .MethodValidationResult ;
35
37
import org .springframework .web .bind .annotation .ResponseStatus ;
36
38
import org .springframework .web .reactive .function .server .ServerRequest ;
37
39
import org .springframework .web .server .ResponseStatusException ;
46
48
* <li>error - The error reason</li>
47
49
* <li>exception - The class name of the root exception (if configured)</li>
48
50
* <li>message - The exception message (if configured)</li>
49
- * <li>errors - Any {@link ObjectError}s from a {@link BindingResult} exception (if
50
- * configured)</li>
51
+ * <li>errors - Any {@link ObjectError}s from a {@link BindingResult} or
52
+ * {@link MethodValidationResult} exception (if configured)</li>
51
53
* <li>trace - The exception stack trace (if configured)</li>
52
54
* <li>path - The URL path when the exception was raised</li>
53
55
* <li>requestId - Unique ID associated with the current request</li>
58
60
* @author Michele Mancioppi
59
61
* @author Scott Frederick
60
62
* @author Moritz Halbritter
63
+ * @author Yanming Zhou
61
64
* @since 2.0.0
62
65
* @see ErrorAttributes
63
66
*/
@@ -97,9 +100,8 @@ private Map<String, Object> getErrorAttributes(ServerRequest request, boolean in
97
100
HttpStatus errorStatus = determineHttpStatus (error , responseStatusAnnotation );
98
101
errorAttributes .put ("status" , errorStatus .value ());
99
102
errorAttributes .put ("error" , errorStatus .getReasonPhrase ());
100
- errorAttributes .put ("message" , determineMessage (error , responseStatusAnnotation ));
101
103
errorAttributes .put ("requestId" , request .exchange ().getRequest ().getId ());
102
- handleException (errorAttributes , determineException ( error ) , includeStackTrace );
104
+ handleException (errorAttributes , error , responseStatusAnnotation , includeStackTrace );
103
105
return errorAttributes ;
104
106
}
105
107
@@ -113,44 +115,51 @@ private HttpStatus determineHttpStatus(Throwable error, MergedAnnotation<Respons
113
115
return responseStatusAnnotation .getValue ("code" , HttpStatus .class ).orElse (HttpStatus .INTERNAL_SERVER_ERROR );
114
116
}
115
117
116
- private String determineMessage (Throwable error , MergedAnnotation <ResponseStatus > responseStatusAnnotation ) {
117
- if (error instanceof BindingResult ) {
118
- return error .getMessage ();
119
- }
120
- if (error instanceof ResponseStatusException responseStatusException ) {
121
- return responseStatusException .getReason ();
122
- }
123
- String reason = responseStatusAnnotation .getValue ("reason" , String .class ).orElse ("" );
124
- if (StringUtils .hasText (reason )) {
125
- return reason ;
126
- }
127
- return (error .getMessage () != null ) ? error .getMessage () : "" ;
128
- }
129
-
130
- private Throwable determineException (Throwable error ) {
131
- if (error instanceof ResponseStatusException ) {
132
- return (error .getCause () != null ) ? error .getCause () : error ;
133
- }
134
- return error ;
135
- }
136
-
137
118
private void addStackTrace (Map <String , Object > errorAttributes , Throwable error ) {
138
119
StringWriter stackTrace = new StringWriter ();
139
120
error .printStackTrace (new PrintWriter (stackTrace ));
140
121
stackTrace .flush ();
141
122
errorAttributes .put ("trace" , stackTrace .toString ());
142
123
}
143
124
144
- private void handleException (Map <String , Object > errorAttributes , Throwable error , boolean includeStackTrace ) {
145
- errorAttributes .put ("exception" , error .getClass ().getName ());
146
- if (includeStackTrace ) {
147
- addStackTrace (errorAttributes , error );
125
+ private void handleException (Map <String , Object > errorAttributes , Throwable error ,
126
+ MergedAnnotation <ResponseStatus > responseStatusAnnotation , boolean includeStackTrace ) {
127
+ Throwable exception ;
128
+ if (error instanceof BindingResult bindingResult ) {
129
+ errorAttributes .put ("message" , error .getMessage ());
130
+ errorAttributes .put ("errors" , bindingResult .getAllErrors ());
131
+ exception = error ;
148
132
}
149
- if (error instanceof BindingResult result ) {
150
- if (result .hasErrors ()) {
151
- errorAttributes .put ("errors" , result .getAllErrors ());
152
- }
133
+ else if (error instanceof MethodValidationResult methodValidationResult ) {
134
+ addMessageAndErrorsFromMethodValidationResult (errorAttributes , methodValidationResult );
135
+ exception = error ;
136
+ }
137
+ else if (error instanceof ResponseStatusException responseStatusException ) {
138
+ errorAttributes .put ("message" , responseStatusException .getReason ());
139
+ exception = (responseStatusException .getCause () != null ) ? responseStatusException .getCause () : error ;
140
+ }
141
+ else {
142
+ exception = error ;
143
+ String reason = responseStatusAnnotation .getValue ("reason" , String .class ).orElse ("" );
144
+ String message = StringUtils .hasText (reason ) ? reason : error .getMessage ();
145
+ errorAttributes .put ("message" , (message != null ) ? message : "" );
153
146
}
147
+ errorAttributes .put ("exception" , exception .getClass ().getName ());
148
+ if (includeStackTrace ) {
149
+ addStackTrace (errorAttributes , exception );
150
+ }
151
+ }
152
+
153
+ private void addMessageAndErrorsFromMethodValidationResult (Map <String , Object > errorAttributes ,
154
+ MethodValidationResult result ) {
155
+ List <ObjectError > errors = result .getAllErrors ()
156
+ .stream ()
157
+ .filter (ObjectError .class ::isInstance )
158
+ .map (ObjectError .class ::cast )
159
+ .toList ();
160
+ errorAttributes .put ("message" ,
161
+ "Validation failed for method='" + result .getMethod () + "'. Error count: " + errors .size ());
162
+ errorAttributes .put ("errors" , errors );
154
163
}
155
164
156
165
@ Override
0 commit comments