Skip to content

Commit

Permalink
Revise docs on RFC 7807
Browse files Browse the repository at this point in the history
  • Loading branch information
rstoyanchev committed Oct 5, 2022
1 parent a421085 commit 75dea98
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 82 deletions.
84 changes: 43 additions & 41 deletions src/docs/asciidoc/web/webflux.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3495,47 +3495,49 @@ include::webflux-cors.adoc[leveloffset=+1]
== REST API exceptions
[.small]#<<web.adoc#mvc-ann-rest-exceptions, Web MVC>>#

A common requirement for REST services is to include error details in the body of the
response. The Spring Framework provides support for
https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807] formatted error responses.

Main abstractions and supporting infrastructure:

- `ProblemDetail` in the `spring-web` module is the core abstraction that represents an
RFC 7807 problem detail. It helps to enable a range of features in Spring WebFlux for the
handling and rendering of such responses.
- `ErrorResponse` is an interface that defines an error response, including status, headers,
and `ProblemDetail` as its body. All Spring web exceptions implement this interface, and
thus encapsulate a default opinion on how they map to an RFC 7807 error response.
- `ErrorResponseException` is a `RuntimeException` that implements `ErrorResponse`, which
can be raised directly or serve as a base class for other exceptions.
- {api-spring-framework}/web/reactive/result/method/annotation/ResponseEntityExceptionHandler.html[`ResponseEntityExceptionHandler`]
provides handling for Spring WebFlux exceptions and for any `ErrorResponseException`.
Applications can extend this as an <<webflux-ann-controller-advice>> to enable RFC 7807 support.

`ProblemDetail` and `ErrorResponse` are supported as return values from
`@ExceptionHandler` and `@RequestMapping` controller methods. The `status` property of
`ProblemDetail` is used to set the response status, while the `instance` property is set
from the current URL path, if not already set.

The Jackson `Encoder` returns "application/problem+json" as a preferred
choice to serialize `ProblemDetail` to JSON as part of content negotiation. If no suitable
media type is found to render a `ProblemDetail` response body, content negotiation falls
back on "application/problem+json".

Applications can extend `ProblemDetail` with non-standard fields in one of two ways:

. Add properties to the generic `properties` map in `ProblemDetail`. When the Jackson JSON
library is present, this `properties` map is unwrapped and rendered as top level
key-value pairs in the output JSON, with the help of `ProblemDetailJacksonMixin`.
. Create a `ProblemDetail` subclass that defines the extra, non-standard fields.
Subclasses can use a protected copy constructor in order to re-create an existing
`ProblemDetail` as a subclass. This can be done centrally from an `@ControllerAdvice`
such as `ResponseEntityExceptionHandler`.

On the client side, `WebClientResponseException` provides methods that decode the response
body to some target type. This is useful to decode to a `ProblemDetail`, or to any other
class, including subclasses of `ProblemDetail`.
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:

- `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
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,
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:

- 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.

You can extend an RFC 7807 response with non-standard fields as follows:

- 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
`getResponseBodyAs` methods to decode the error response body to any target type such as
`ProblemDetail`, or a subclass of `ProblemDetail`.



Expand Down
85 changes: 44 additions & 41 deletions src/docs/asciidoc/web/webmvc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4827,47 +4827,50 @@ include::webmvc-cors.adoc[leveloffset=+1]
== REST API exceptions
[.small]#<<web-reactive.adoc#webflux-ann-rest-exceptions, WebFlux>>#

A common requirement for REST services is to include error details in the body of the
response. The Spring Framework provides support for
https://www.rfc-editor.org/rfc/rfc7807.html[RFC 7807] formatted error responses.

Main abstractions and supporting infrastructure:

- `ProblemDetail` in the `spring-web` module is the core abstraction that represents an
RFC 7807 problem detail. It helps to enable a range of features in Spring MVC for the
handling and rendering of such responses.
- `ErrorResponse` is an interface that defines an error response, including status, headers,
and `ProblemDetail` as its body. All Spring web exceptions implement this interface, and
thus encapsulate a default opinion on how they map to an RFC 7807 error response.
- `ErrorResponseException` is a `RuntimeException` that implements `ErrorResponse`, which
can be raised directly or serve as a base class for other exceptions.
- {api-spring-framework}/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html[`ResponseEntityExceptionHandler`]
provides handling for Spring MVC exceptions and for any `ErrorResponseException`.
Applications can extend this as an <<mvc-ann-controller-advice>> to enable RFC 7807 support.

`ProblemDetail` and `ErrorResponse` are supported as return values from
`@ExceptionHandler` and `@RequestMapping` controller methods. The `status` property of
`ProblemDetail` is used to set the response status, while the `instance` property is set
from the current URL path, if not already set.

The Jackson `HttpMessageConverter` returns "application/problem+json" as a preferred
choice to serialize `ProblemDetail` to JSON as part of content negotiation. If no suitable
media type is found to render a `ProblemDetail` response body, content negotiation falls
back on "application/problem+json".

Applications can extend `ProblemDetail` with non-standard fields in one of two ways:

. Add properties to the generic `properties` map in `ProblemDetail`. When using
the Jackson library, this `properties` map is unwrapped and as top level JSON
properties with the help of `ProblemDetailJacksonMixin`.
. Create a `ProblemDetail` subclass that defines the extra, non-standard fields.
Subclasses can use a protected copy constructor in order to re-create an existing
`ProblemDetail` as a subclass. This can be done centrally from an `@ControllerAdvice`
such as `ResponseEntityExceptionHandler`.

On the client side, `WebClientResponseException` and `RestClientResponseException` provide
methods that decode the response body to some target type. This is useful to decode to a
`ProblemDetail`, or to any other class, including subclasses of `ProblemDetail`.
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:

- `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
exceptions implement this.
- `ErrorResponseException` -- basic `ErrorResponse` implementation that others
can use as a convenient base class.
- `ResponseEntityExceptionHandler` -- convenient base class for an
<<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:

- 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.

You can extend an RFC 7807 response with non-standard fields as follows:

- 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`, 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`.



Expand Down

0 comments on commit 75dea98

Please sign in to comment.