@@ -4827,47 +4827,50 @@ include::webmvc-cors.adoc[leveloffset=+1]
4827
4827
== REST API exceptions
4828
4828
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions, WebFlux>>#
4829
4829
4830
- A common requirement for REST services is to include error details in the body of the
4831
- response. The Spring Framework provides support for
4832
- https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807] formatted error responses.
4833
-
4834
- Main abstractions and supporting infrastructure:
4835
-
4836
- - `ProblemDetail` in the `spring-web` module is the core abstraction that represents an
4837
- RFC 7807 problem detail. It helps to enable a range of features in Spring MVC for the
4838
- handling and rendering of such responses.
4839
- - `ErrorResponse` is an interface that defines an error response, including status, headers,
4840
- and `ProblemDetail` as its body. All Spring web exceptions implement this interface, and
4841
- thus encapsulate a default opinion on how they map to an RFC 7807 error response.
4842
- - `ErrorResponseException` is a `RuntimeException` that implements `ErrorResponse`, which
4843
- can be raised directly or serve as a base class for other exceptions.
4844
- - {api-spring-framework}/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html[`ResponseEntityExceptionHandler`]
4845
- provides handling for Spring MVC exceptions and for any `ErrorResponseException`.
4846
- Applications can extend this as an <<mvc-ann-controller-advice>> to enable RFC 7807 support.
4847
-
4848
- `ProblemDetail` and `ErrorResponse` are supported as return values from
4849
- `@ExceptionHandler` and `@RequestMapping` controller methods. The `status` property of
4850
- `ProblemDetail` is used to set the response status, while the `instance` property is set
4851
- from the current URL path, if not already set.
4852
-
4853
- The Jackson `HttpMessageConverter` returns "application/problem+json" as a preferred
4854
- choice to serialize `ProblemDetail` to JSON as part of content negotiation. If no suitable
4855
- media type is found to render a `ProblemDetail` response body, content negotiation falls
4856
- back on "application/problem+json".
4857
-
4858
- Applications can extend `ProblemDetail` with non-standard fields in one of two ways:
4859
-
4860
- . Add properties to the generic `properties` map in `ProblemDetail`. When using
4861
- the Jackson library, this `properties` map is unwrapped and as top level JSON
4862
- properties with the help of `ProblemDetailJacksonMixin`.
4863
- . Create a `ProblemDetail` subclass that defines the extra, non-standard fields.
4864
- Subclasses can use a protected copy constructor in order to re-create an existing
4865
- `ProblemDetail` as a subclass. This can be done centrally from an `@ControllerAdvice`
4866
- such as `ResponseEntityExceptionHandler`.
4867
-
4868
- On the client side, `WebClientResponseException` and `RestClientResponseException` provide
4869
- methods that decode the response body to some target type. This is useful to decode to a
4870
- `ProblemDetail`, or to any other class, including subclasses of `ProblemDetail`.
4830
+ A common requirement for REST services is to include details in the body of an error
4831
+ response. The Spring Framework supports the "Problem Details for HTTP APIs"
4832
+ specification, https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807]. These are the main
4833
+ abstractions for this support:
4834
+
4835
+ - `ProblemDetail` -- representation for an RFC 7807 problem detail; a simple container
4836
+ for both standard fields defined in the spec, and for non-standard ones.
4837
+ - `ErrorResponse` -- contract to expose HTTP error response details including HTTP
4838
+ status, response headers, and a body in the format of RFC 7807; this allows exceptions to
4839
+ encapsulate and expose the details of how they map to an HTTP response. All Spring MVC
4840
+ exceptions implement this.
4841
+ - `ErrorResponseException` -- basic `ErrorResponse` implementation that others
4842
+ can use as a convenient base class.
4843
+ - `ResponseEntityExceptionHandler` -- convenient base class for an
4844
+ <<mvc-ann-controller-advice,@ControllerAdvice>> that handles all Spring MVC exceptions,
4845
+ and any `ErrorResponseException`, and renders an error response with a body.
4846
+
4847
+ You can return `ProblemDetail` or `ErrorResponse` directly from `@RequestMapping` or
4848
+ from `@ExceptionHandler` controller methods to render an RFC 7807 response as follows:
4849
+
4850
+ - The `status` property of `ProblemDetail` determines the HTTP status.
4851
+ - The `instance` property of `ProblemDetail` is set from the current URL path, if not
4852
+ already set.
4853
+ - For content negotiation, the Jackson `HttpMessageConverter` prefers
4854
+ "application/problem+json" over "application/json" when rendering a `ProblemDetail`,
4855
+ and also falls back on it if no compatible media type is found.
4856
+
4857
+ You can extend an RFC 7807 response with non-standard fields as follows:
4858
+
4859
+ - Insert into the "properties" `Map` of `ProblemDetail`. When using the Jackson
4860
+ library, the Spring Framework registers `ProblemDetailJacksonMixin` that ensures this
4861
+ "properties" `Map` is unwrapped and rendered as top level JSON properties in the
4862
+ response, and likewise any unknown property during deserialization is inserted into
4863
+ this `Map`.
4864
+ - Extend `ProblemDetail` to add dedicated non-standard properties. The copy constructor
4865
+ in `ProblemDetail` allows a sub-class to make it easy to be created from an existing
4866
+ `ProblemDetail`. This could be done centrally, e.g. from an `@ControllerAdvice` such as
4867
+ `ResponseEntityExceptionHandler` that re-creates the `ProblemDetail` of an exception into
4868
+ a subclass with the additional non-standard fields.
4869
+
4870
+ A client application can catch `WebClientResponseException`, when using the `WebClient`,
4871
+ or `RestClientResponseException` when using the `RestTemplate`, and use their
4872
+ `getResponseBodyAs` methods to decode the error response body to any target type such as
4873
+ `ProblemDetail`, or a subclass of `ProblemDetail`.
4871
4874
4872
4875
4873
4876
0 commit comments