spring-framework/framework-docs/modules/ROOT/pages/web/webflux/ann-rest-exceptions.adoc

166 lines
7.0 KiB
Plaintext
Raw Normal View History

2023-04-19 23:26:16 +08:00
[[webflux-ann-rest-exceptions]]
= Error Responses
2023-04-19 23:26:17 +08:00
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc[See equivalent in the Servlet stack]#
2023-04-19 23:26:16 +08:00
A common requirement for REST services is to include details in the body of error
responses. The Spring Framework supports the "Problem Details for HTTP APIs"
specification, {rfc-site}/rfc9457.html[RFC 9457].
2023-04-19 23:26:16 +08:00
The following are the main abstractions for this support:
- `ProblemDetail` -- representation for an RFC 9457 problem detail; a simple container
2023-04-19 23:26:16 +08:00
for both standard fields defined in the spec, and for non-standard ones.
- `ErrorResponse` -- contract to expose HTTP error response details including HTTP
status, response headers, and a body in the format of RFC 9457; this allows exceptions to
2023-04-19 23:26:16 +08:00
encapsulate and expose the details of how they map to an HTTP response. All Spring WebFlux
exceptions implement this.
- `ErrorResponseException` -- basic `ErrorResponse` implementation that others
can use as a convenient base class.
- `ResponseEntityExceptionHandler` -- convenient base class for an
2023-04-19 23:26:17 +08:00
xref:web/webflux/controller/ann-advice.adoc[@ControllerAdvice] that handles all Spring WebFlux exceptions,
2023-04-19 23:26:16 +08:00
and any `ErrorResponseException`, and renders an error response with a body.
[[webflux-ann-rest-exceptions-render]]
== Render
2023-04-19 23:26:17 +08:00
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc#mvc-ann-rest-exceptions-render[See equivalent in the Servlet stack]#
2023-04-19 23:26:16 +08:00
You can return `ProblemDetail` or `ErrorResponse` from any `@ExceptionHandler` or from
any `@RequestMapping` method to render an RFC 9457 response. This is processed as follows:
2023-04-19 23:26:16 +08:00
- The `status` property of `ProblemDetail` determines the HTTP status.
- The `instance` property of `ProblemDetail` is set from the current URL path, if not
already set.
- For content negotiation, the Jackson `HttpMessageConverter` prefers
"application/problem+json" over "application/json" when rendering a `ProblemDetail`,
and also falls back on it if no compatible media type is found.
To enable RFC 9457 responses for Spring WebFlux exceptions and for any
2023-04-19 23:26:16 +08:00
`ErrorResponseException`, extend `ResponseEntityExceptionHandler` and declare it as an
2023-04-19 23:26:17 +08:00
xref:web/webflux/controller/ann-advice.adoc[@ControllerAdvice] in Spring configuration. The handler
2023-04-19 23:26:16 +08:00
has an `@ExceptionHandler` method that handles any `ErrorResponse` exception, which
includes all built-in web exceptions. You can add more exception handling methods, and
use a protected method to map any exception to a `ProblemDetail`.
You can register `ErrorResponse` interceptors through the
xref:web/webflux/config.adoc[WebFlux Config] with a `WebFluxConfigurer`. Use that to intercept
any RFC 7807 response and take some action.
2023-04-19 23:26:16 +08:00
[[webflux-ann-rest-exceptions-non-standard]]
== Non-Standard Fields
2023-04-19 23:26:17 +08:00
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc#mvc-ann-rest-exceptions-non-standard[See equivalent in the Servlet stack]#
2023-04-19 23:26:16 +08:00
You can extend an RFC 9457 response with non-standard fields in one of two ways.
2023-04-19 23:26:16 +08:00
One, insert into the "properties" `Map` of `ProblemDetail`. When using the Jackson
library, the Spring Framework registers `ProblemDetailJacksonMixin` that ensures this
"properties" `Map` is unwrapped and rendered as top level JSON properties in the
response, and likewise any unknown property during deserialization is inserted into
this `Map`.
You can also extend `ProblemDetail` to add dedicated non-standard properties.
The copy constructor in `ProblemDetail` allows a subclass to make it easy to be created
from an existing `ProblemDetail`. This could be done centrally, e.g. from an
`@ControllerAdvice` such as `ResponseEntityExceptionHandler` that re-creates the
`ProblemDetail` of an exception into a subclass with the additional non-standard fields.
[[webflux-ann-rest-exceptions-i18n]]
== Customization and i18n
2023-04-19 23:26:17 +08:00
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc#mvc-ann-rest-exceptions-i18n[See equivalent in the Servlet stack]#
2023-04-19 23:26:16 +08:00
It is a common requirement to customize and internationalize error response details.
It is also good practice to customize the problem details for Spring WebFlux exceptions
to avoid revealing implementation details. This section describes the support for that.
2023-04-19 23:26:16 +08:00
An `ErrorResponse` exposes message codes for "type", "title", and "detail", as well as
message code arguments for the "detail" field. `ResponseEntityExceptionHandler` resolves
these through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
and updates the corresponding `ProblemDetail` fields accordingly.
2023-04-19 23:26:16 +08:00
The default strategy for message codes follows the pattern:
`problemDetail.[type|title|detail].[fully qualified exception class name]`
An `ErrorResponse` may expose more than one message code, typically adding a suffix
to the default message code. The table below lists message codes, and arguments for
Spring WebFlux exceptions:
2023-04-19 23:26:16 +08:00
[[webflux-ann-rest-exceptions-codes]]
[cols="1,1,2", options="header"]
|===
| Exception | Message Code | Message Code Arguments
| `HandlerMethodValidationException`
2023-04-19 23:26:16 +08:00
| (default)
| `+{0}+` list all validation errors.
Message codes and arguments for each error are also resolved via `MessageSource`.
2023-04-19 23:26:16 +08:00
| `MethodNotAllowedException`
| (default)
| `+{0}+` the current HTTP method, `+{1}+` the list of supported HTTP methods
2023-04-19 23:26:16 +08:00
| `MissingRequestValueException`
| (default)
2023-04-19 05:37:25 +08:00
| `+{0}+` a label for the value (e.g. "request header", "cookie value", ...), `+{1}+` the value name
2023-04-19 23:26:16 +08:00
| `NotAcceptableStatusException`
| (default)
2023-04-19 05:37:25 +08:00
| `+{0}+` list of supported media types
2023-04-19 23:26:16 +08:00
| `NotAcceptableStatusException`
| (default) + ".parseError"
|
| `ServerErrorException`
| (default)
2023-04-19 05:37:25 +08:00
| `+{0}+` the failure reason provided to the class constructor
2023-04-19 23:26:16 +08:00
| `UnsupportedMediaTypeStatusException`
2023-04-19 23:26:16 +08:00
| (default)
| `+{0}+` the media type that is not supported, `+{1}+` list of supported media types
| `UnsupportedMediaTypeStatusException`
| (default) + ".parseError"
|
| `UnsatisfiedRequestParameterException`
| (default)
| `+{0}+` the list of parameter conditions
| `WebExchangeBindException`
| (default)
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
Message codes and arguments for each error are also resolved via `MessageSource`.
2023-04-19 23:26:16 +08:00
|===
NOTE: Unlike other exceptions, the message arguments for
`WebExchangeBindException` and `HandlerMethodValidationException` are based on a list of
`MessageSourceResolvable` errors that can also be customized through a
xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
resource bundle. See
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method-i18n[Customizing Validation Errors]
for more details.
2023-04-19 23:26:16 +08:00
[[webflux-ann-rest-exceptions-client]]
== Client Handling
2023-04-19 23:26:17 +08:00
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc#mvc-ann-rest-exceptions-client[See equivalent in the Servlet stack]#
2023-04-19 23:26:16 +08:00
A client application can catch `WebClientResponseException`, when using the `WebClient`,
or `RestClientResponseException` when using the `RestTemplate`, and use their
`getResponseBodyAs` methods to decode the error response body to any target type such as
`ProblemDetail`, or a subclass of `ProblemDetail`.