Affects: 6.0.3
After migrating to Boot 3 in my Boot application that has a @ControllerAdvice
extending ResponseEntityExceptionHandler
, my application started retrieving Errors using the ProblemDetail
spec, overriding Boot's Error Handling mechanism.
All good up to that point, but my input validations are not retrieving the validation messages anywhere.
For example, I might have this constraint in my DTO:
@NotNull(message = "a custom validation error")
Long foo,
But the response for a request sending a null
value for this field looks as follows:
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "Invalid request content.",
"instance": "/bar"
}
Shouldn't the detail
contain the validation message, or, since there can be a number of binding errors, be included as an ProblemDetail.properties
entry, resulting in an extra response body field?
Comment From: bclozel
I'm not sure how we should handle this at the Framework level. In Spring Boot error handling support, this is configurable through a property and is disabled by default because this leaks implementation details and can be considered a security issue.
Comment From: rozagerardo
Thanks for the response @bclozel
I haven't analyzed this in detail, but couldn't we consistently make all the ResponseEntityExceptionHandler.handleXXX
methods call the createProblemDetail
method, instead of just the "Lower level exceptions, and exceptions used symmetrically on client and server" ones?
Note: We can simply make createProblemDetail
retrieve the ProblemDetail
right away by default if we see it is an ErrorResponse
exception with a ProblemDetail
body
, instead of (or in addition) doing that inside the handleExceptionInternal
method as we're currently doing.
With this, the user can override the createProblemDetail
method, having access to the actual exception, and include the binding errors only if they want to.
Otherwise, in the createResponseEntity
method we can customize the response that is finally retrieved, but at this stage we don't have access to the original exception to use it accordingly.
Let me know if this makes sense, or if I should clarify the suggested solution using code snippets.
Comment From: rstoyanchev
As Brian mentioned, we don't include such details by default because it exposes implementation details. However, there are a couple of ways to customize this.
The easiest one is to use the ResourceBundle
support, and add a problemDetail.title.MethodArgumentNotValidException
property. You'll see in the documentation that we expose the list of global errors at {0}
and the list of field errors at {1}
.
If you want more control, you can override the appropriate exception handling method. Note that you don't need createProblemDetail
, because all exceptions in spring-web
and spring-webmvc
implement ErrorResponse
, and already contain a ProblemDetail
body. You can access it and modify it:
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request) {
Map<ObjectError, String> messages =
ex.resolveErrorMessages(getMessageSource(), LocaleContextHolder.getLocale());
ProblemDetail problemDetail = ex.getBody();
problemDetail.setProperty("validation-errors", ...);
return super.handleMethodArgumentNotValid(ex, headers, status, request);
}
We only use createProblemDetail
for lower level exceptions that aren't from any of the web modules, and therefore cannot implement ErrorResponse
.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Comment From: tech-conqueror
As Brian mentioned, we don't include such details by default because it exposes implementation details. However, there are a couple of ways to customize this.
The easiest one is to use the
ResourceBundle
support, and add aproblemDetail.title.MethodArgumentNotValidException
property. You'll see in the documentation that we expose the list of global errors at{0}
and the list of field errors at{1}
.If you want more control, you can override the appropriate exception handling method. Note that you don't need
createProblemDetail
, because all exceptions inspring-web
andspring-webmvc
implementErrorResponse
, and already contain aProblemDetail
body. You can access it and modify it:```java @Override protected ResponseEntity
Map
messages = ex.resolveErrorMessages(getMessageSource(), LocaleContextHolder.getLocale()); ProblemDetail problemDetail = ex.getBody(); problemDetail.setProperty("validation-errors", ...);
return super.handleMethodArgumentNotValid(ex, headers, status, request); } ```
We only use
createProblemDetail
for lower level exceptions that aren't from any of the web modules, and therefore cannot implementErrorResponse
.
Hi @rstoyanchev, could you please give an example of how we can customize the ProblemDetail
using the first approach you mentioned in this comment?