Browse Source

Document i8n for RFC 7807 problem details

Expand the documentation for error responses and add details on
using a MessageSource to customize and internationalize error details.

See gh-28814
pull/29282/head
rstoyanchev 2 years ago
parent
commit
6b0f29a065
  1. 129
      src/docs/asciidoc/web/webflux.adoc
  2. 144
      src/docs/asciidoc/web/webmvc.adoc

129
src/docs/asciidoc/web/webflux.adoc

@ -3492,28 +3492,35 @@ include::webflux-cors.adoc[leveloffset=+1] @@ -3492,28 +3492,35 @@ include::webflux-cors.adoc[leveloffset=+1]
[[webflux-ann-rest-exceptions]]
== REST API exceptions
[.small]#<<web.adoc#mvc-ann-rest-exceptions, Web MVC>>#
== Error Responses
[.small]#<<webmvc.adoc#mvc-ann-rest-exceptions, Web MVC>>#
A common requirement for REST services is to include details in the body of an error
response. The Spring Framework supports the "Problem Details for HTTP APIs"
specification, https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807]. These are the main
abstractions for this support:
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, https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807].
The following are the main abstractions for this support:
- `ProblemDetail` -- representation for an RFC 7807 problem detail; a simple container
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 7807; this allows exceptions to
encapsulate and expose the details of how they map to an HTTP response. All Spring MVC
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
<<webflux-ann-controller-advice,@ControllerAdvice>> that handles all Spring MVC exceptions,
<<webflux-ann-controller-advice,@ControllerAdvice>> that handles all Spring WebFlux exceptions,
and any `ErrorResponseException`, and renders an error response with a body.
You can return `ProblemDetail` or `ErrorResponse` directly from `@RequestMapping` or
from `@ExceptionHandler` controller methods to render an RFC 7807 response as follows:
[[webflux-ann-rest-exceptions-render]]
=== Render
[.small]#<<webmvc.adoc#mvc-ann-rest-exceptions-render, Web MVC>>#
You can return `ProblemDetail` or `ErrorResponse` from any `@ExceptionHandler` or from
any `@RequestMapping` method to render an RFC 7807 response as follows:
- The `status` property of `ProblemDetail` determines the HTTP status.
- The `instance` property of `ProblemDetail` is set from the current URL path, if not
@ -3522,20 +3529,106 @@ already set. @@ -3522,20 +3529,106 @@ already set.
"application/problem+json" over "application/json" when rendering a `ProblemDetail`,
and also falls back on it if no compatible media type is found.
You can extend an RFC 7807 response with non-standard fields as follows:
To enable RFC 7807 responses for Spring WebFlux exceptions and for any
`ErrorResponseException`, extend `ResponseEntityExceptionHandler` and declare it as an
<<webflux-ann-controller-advice,@ControllerAdvice>> in Spring configuration. The handler
obtains HTTP status, headers, and error details from each exception and prepares a
`ResponseEntity`.
[[webflux-ann-rest-exceptions-non-standard]]
=== Non-Standard Fields
[.small]#<<webmvc.adoc#mvc-ann-rest-exceptions-non-standard, Web MVC>>#
You can extend an RFC 7807 response with non-standard fields in one of two ways.
- Insert into the "properties" `Map` of `ProblemDetail`. When using the Jackson
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`.
- Extend `ProblemDetail` to add dedicated non-standard properties. The copy constructor
in `ProblemDetail` allows a sub-class 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.
A client application can catch `WebClientResponseException` and use its
You can also extend `ProblemDetail` to add dedicated non-standard properties.
The copy constructor in `ProblemDetail` allows a sub-class 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-i8n]]
=== Internationalization
[.small]#<<webmvc.adoc#mvc-ann-rest-exceptions-i8n, Web MVC>>#
It is a common requirement to internationalize error response details, and good practice
to customize the problem details for Spring WebFlux exceptions. This is supported as follows:
- Each `ErrorResponse` exposes a message code and message code arguments to resolve the
problem "detail" field through a <<core.adoc#context-functionality-messagesource,MessageSource>>.
The actual message code value is parameterized with placeholders, e.g.
`"HTTP method {0} not supported"` to be expanded from the arguments.
- `ResponseEntityExceptionHandler` uses the message code and the message arguments
to resolve the problem "detail" field.
Message codes default to "problemDetail." + the fully qualified exception class name. Some
exceptions may expose additional message codes in which case a suffix is added to
the default message code. The table below lists message arguments and codes for Spring
WebFlux exceptions:
[[webflux-ann-rest-exceptions-codes]]
[cols="1,1,2", options="header"]
|===
| Exception | Message Code | Message Code Arguments
| `UnsupportedMediaTypeStatusException`
| (default)
| `{0}` the media type that is not supported, `{1}` list of supported media types
| `UnsupportedMediaTypeStatusException`
| (default) + ".parseError"
|
| `MissingRequestValueException`
| (default)
| `{0}` a label for the value (e.g. "request header", "cookie value", ...), `{1}` the value name
| `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 within the `BindingResult` are also resolved
via `MessageSource`.
| `NotAcceptableStatusException`
| (default)
| `{0}` list of supported media types
| `NotAcceptableStatusException`
| (default) + ".parseError"
|
| `ServerErrorException`
| (default)
| `{0}` the failure reason provided to the class constructor
| `MethodNotAllowedException`
| (default)
| `{0}` the current HTTP method, `{1}` the list of supported HTTP methods
|===
[[webflux-ann-rest-exceptions-client]]
=== Client Handling
[.small]#<<webmvc.adoc#mvc-ann-rest-exceptions-client, Web MVC>>#
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`.

144
src/docs/asciidoc/web/webmvc.adoc

@ -4824,13 +4824,14 @@ include::webmvc-cors.adoc[leveloffset=+1] @@ -4824,13 +4824,14 @@ include::webmvc-cors.adoc[leveloffset=+1]
[[mvc-ann-rest-exceptions]]
== REST API exceptions
== Error Responses
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions, WebFlux>>#
A common requirement for REST services is to include details in the body of an error
response. The Spring Framework supports the "Problem Details for HTTP APIs"
specification, https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807]. These are the main
abstractions for this support:
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, https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807].
The following are the main abstractions for this support:
- `ProblemDetail` -- representation for an RFC 7807 problem detail; a simple container
for both standard fields defined in the spec, and for non-standard ones.
@ -4844,8 +4845,14 @@ can use as a convenient base class. @@ -4844,8 +4845,14 @@ can use as a convenient base class.
<<mvc-ann-controller-advice,@ControllerAdvice>> that handles all Spring MVC exceptions,
and any `ErrorResponseException`, and renders an error response with a body.
You can return `ProblemDetail` or `ErrorResponse` directly from `@RequestMapping` or
from `@ExceptionHandler` controller methods to render an RFC 7807 response as follows:
[[mvc-ann-rest-exceptions-render]]
=== Render
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions-render, WebFlux>>#
You can return `ProblemDetail` or `ErrorResponse` from any `@ExceptionHandler` or from
any `@RequestMapping` method to render an RFC 7807 response as follows:
- The `status` property of `ProblemDetail` determines the HTTP status.
- The `instance` property of `ProblemDetail` is set from the current URL path, if not
@ -4854,18 +4861,127 @@ already set. @@ -4854,18 +4861,127 @@ already set.
"application/problem+json" over "application/json" when rendering a `ProblemDetail`,
and also falls back on it if no compatible media type is found.
You can extend an RFC 7807 response with non-standard fields as follows:
To enable RFC 7807 responses for Spring MVC exceptions and for any
`ErrorResponseException`, extend `ResponseEntityExceptionHandler` and declare it as an
<<mvc-ann-controller-advice,@ControllerAdvice>> in Spring configuration. The handler
obtains HTTP status, headers, and error details from each exception and prepares a
`ResponseEntity`.
- Insert into the "properties" `Map` of `ProblemDetail`. When using the Jackson
[[mvc-ann-rest-exceptions-non-standard]]
=== Non-Standard Fields
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions-non-standard, WebFlux>>#
You can extend an RFC 7807 response with non-standard fields in one of two ways.
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`.
- Extend `ProblemDetail` to add dedicated non-standard properties. The copy constructor
in `ProblemDetail` allows a sub-class 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.
You can also extend `ProblemDetail` to add dedicated non-standard properties.
The copy constructor in `ProblemDetail` allows a sub-class 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.
[[mvc-ann-rest-exceptions-i8n]]
=== Internationalization
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions-i8n, WebFlux>>#
It is a common requirement to internationalize error response details, and good practice
to customize the problem details for Spring MVC exceptions. This is supported as follows:
- Each `ErrorResponse` exposes a message code and message code arguments to resolve the
problem "detail" field through a <<core.adoc#context-functionality-messagesource,MessageSource>>.
The actual message code value is parameterized with placeholders, e.g.
`"HTTP method {0} not supported"` to be expanded from the arguments.
- `ResponseEntityExceptionHandler` uses the message code and the message arguments
to resolve the problem "detail" field.
Message codes default to "problemDetail." + the fully qualified exception class name. Some
exceptions may expose additional message codes in which case a suffix is added to
the default message code. The table below lists message arguments and codes for Spring
MVC exceptions:
[[mvc-ann-rest-exceptions-codes]]
[cols="1,1,2", options="header"]
|===
| Exception | Message Code | Message Code Arguments
| `AsyncRequestTimeoutException`
| (default)
|
| `HttpMediaTypeNotAcceptableException`
| (default)
| `{0}` list of supported media types
| `HttpMediaTypeNotAcceptableException`
| (default) + ".parseError"
|
| `HttpMediaTypeNotSupportedException`
| (default)
| `{0}` the media type that is not supported, `{1}` list of supported media types
| `HttpMediaTypeNotSupportedException`
| (default) + ".parseError"
|
| `HttpRequestMethodNotSupportedException`
| (default)
| `{0}` the current HTTP method, `{1}` the list of supported HTTP methods
| `MethodArgumentNotValidException`
| (default)
| `{0}` the list of global errors, `{1}` the list of field errors.
Message codes and arguments for each error within the `BindingResult` are also resolved
via `MessageSource`.
| `MissingRequestHeaderException`
| (default)
| `{0}` the header name
| `MissingServletRequestParameterException`
| (default)
| `{0}` the request parameter name
| `MissingMatrixVariableException`
| (default)
| `{0}` the matrix variable name
| `MissingPathVariableException`
| (default)
| `{0}` the path variable name
| `MissingRequestCookieException`
| (default)
| `{0}` the cookie name
| `MissingServletRequestPartException`
| (default)
| `{0}` the part name
| `NoHandlerFoundException`
| (default)
|
| `UnsatisfiedServletRequestParameterException`
| (default)
| `{0}` the list of parameter conditions
|===
[[mvc-ann-rest-exceptions-client]]
=== Client Handling
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions-client, WebFlux>>#
A client application can catch `WebClientResponseException`, when using the `WebClient`,
or `RestClientResponseException` when using the `RestTemplate`, and use their

Loading…
Cancel
Save