Skip to content

Commit 65fdd0e

Browse files
committed
[docs] Updates for exception handling in web sections
Issue: SPR-16394
1 parent 9dd3cd9 commit 65fdd0e

File tree

2 files changed

+372
-108
lines changed

2 files changed

+372
-108
lines changed

src/docs/asciidoc/web/webflux.adoc

Lines changed: 192 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -448,31 +448,21 @@ This can be automated through the use of
448448

449449

450450
[[webflux-web-handler-api]]
451-
=== WebHandler
451+
=== WebHandler API
452452

453-
`HttpHandler` is the lowest level contract for running on different HTTP servers.
454-
On top of that foundation, the WebHandler API provides a slightly higher level, but
455-
still general purpose, set of components that form a chain of
456-
{api-spring-framework}/web/server/WebExceptionHandler.html[WebExceptionHandler's],
457-
{api-spring-framework}/web/server/WebFilter.html[WebFilter's], and a
458-
{api-spring-framework}/web/server/WebHandler.html[WebHandler].
453+
The WebHandler API is a general purpose, server, web API for processing requests through a
454+
chain of {api-spring-framework}/web/server/WebExceptionHandler.html[WebExceptionHandler's],
455+
{api-spring-framework}/web/server/WebFilter.html[WebFilter's], and a target
456+
{api-spring-framework}/web/server/WebHandler.html[WebHandler]. The chain can be assembled
457+
with `WebHttpHandlerBuilder` either by adding components to the builder or by having them
458+
detected from a Spring `ApplicationContext`. The builder returns an
459+
<<webflux-httphandler>> that can then be used to run on any of the supported servers.
459460

460-
All WebHandler API components take `ServerWebExchange` as input which goes beyond
461-
`ServerHttpRequest` and `ServerHttpResponse` to provide extra building blocks for
462-
use in web applications such as request attributes, session attributes, access to parsed
463-
form data, multipart data, and more.
464-
465-
`WebHttpHandlerBuilder` is used to assemble a request processing chain. You can use
466-
methods on the builder to add components manually, or more likely have them detected from
467-
a Spring `ApplicationContext`, with the resulting `HttpHandler` ready to run via a
468-
<<webflux-httphandler,server adapter>>:
469-
470-
[source,java,indent=0]
471-
[subs="verbatim,quotes"]
472-
----
473-
ApplicationContext context = ...
474-
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build()
475-
----
461+
While `HttpHandler` aims to be the most minimal contract across HTTP servers, the
462+
WebHandler API provides essential features commonly used to build web applications.
463+
For example, the `ServerWebExchange` available to WebHandler API components provides
464+
access not only to the request and response, but also to request and session attributes,
465+
access to parsed form data, multipart data, and more.
476466

477467

478468

@@ -488,12 +478,14 @@ The table below lists the components that `WebHttpHandlerBuilder` detects:
488478
| <any>
489479
| `WebExceptionHandler`
490480
| 0..N
491-
| Exception handlers to apply after all ``WebFilter``'s and the target `WebHandler`.
481+
| Provide handling for exceptions from the chain of ``WebFilter``'s and the target
482+
`WebHandler`. For more details, see <<webflux-exception-handler>>.
492483

493484
| <any>
494485
| `WebFilter`
495486
| 0..N
496-
| Filters to invoke before and after the target `WebHandler`.
487+
| Apply interception style logic to before and after the rest of the filter chain and
488+
the target `WebHandler`. For more details, see <<webflux-filters>>.
497489

498490
| "webHandler"
499491
| `WebHandler`
@@ -645,9 +637,13 @@ a heartbeat and ignore.
645637
=== Filters
646638
[.small]#<<web.adoc#filters,Same in Spring MVC>>#
647639

648-
As part of the <<webflux-web-handler-api>>, the `spring-web` module provides a number of
649-
`WebFilter` implementations.
640+
In the <<webflux-web-handler-api>>, a `WebFilter` can be used to apply interception-style
641+
logic before and after the rest of the processing chain of filters and the target
642+
`WebHandler`. When using the <<webflux-config>>, registering a `WebFilter` is as simple
643+
as declaring it as a Spring bean, and optionally expressing precedence via `@Order` on
644+
the bean declaration or by implementing `Ordered`.
650645

646+
The following describe the available `WebFilter` implementations:
651647

652648

653649
[[webflux-filters-forwarded-headers]]
@@ -690,6 +686,37 @@ See the section on <<webflux-cors>> and the <<webflux-cors-webfilter>> for more
690686

691687

692688

689+
[[webflux-exception-handler]]
690+
=== Exceptions
691+
[.small]#<<web.adoc#mvc-ann-customer-servlet-container-error-page,Same in Spring MVC>>#
692+
693+
In the <<webflux-web-handler-api>>, a `WebExceptionHandler` can be used to to handle
694+
exceptions from the chain of ``WebFilter``'s and the target `WebHandler`. When using the
695+
<<webflux-config>>, registering a `WebExceptionHandler` is as simple as declaring it as a
696+
Spring bean, and optionally expressing precedence via `@Order` on the bean declaration or
697+
by implementing `Ordered`.
698+
699+
Below are the available `WebExceptionHandler` implementations:
700+
701+
[cols="1,2", options="header"]
702+
|===
703+
| Exception Handler | Description
704+
705+
| `ResponseStatusExceptionHandler`
706+
| Provides handling for exceptions of type
707+
{api-spring-framework}/web/server/ResponseStatusException.html[ResponseStatusException]
708+
by setting the response to the HTTP status code of the exception.
709+
710+
| `WebFluxResponseStatusExceptionHandler`
711+
| Extension of `ResponseStatusExceptionHandler` that can also determine the HTTP status
712+
code an `@ResponseStatus` annotation on any exception.
713+
714+
This handler is declared in the <<webflux-config>>.
715+
716+
|===
717+
718+
719+
693720

694721
[[webflux-dispatcher-handler]]
695722
== DispatcherHandler
@@ -805,24 +832,60 @@ processing by writing to the response directly or using a view to render.
805832
[[webflux-resulthandling]]
806833
=== Result Handling
807834

808-
When `DispatcherHandler` needs to process the return value from a handler, it finds a
809-
`HandlerResultHandler` that support it and invokes it. The available implementations are
810-
listed below with their default order (all are declared in the <<webflux-config>>):
835+
The return value from the invocation of a handler, through a `HandlerAdapter`, is wrapped
836+
as `HandlerResult`, along with some additional context, and passed to the first
837+
`HandlerResultHandler` that claims support for it. The table below shows the available
838+
`HandlerResultHandler` implementations all of which are declared in the <<webflux-config>>:
839+
840+
[cols="1,2,1", options="header"]
841+
|===
842+
| Result Handler Type | Return Values | Default Order
843+
844+
| `ResponseEntityResultHandler`
845+
| `ResponseEntity`, typically from ``@Controller``'s.
846+
| 0
847+
848+
| `ServerResponseResultHandler`
849+
| `ServerResponse`, typically from functional endpoints.
850+
| 0
851+
852+
| `ResponseBodyResultHandler`
853+
| Handle return values from `@ResponseBody` methods or `@RestController` classes.
854+
| 100
855+
856+
| `ViewResolutionResultHandler`
857+
| `CharSequence` or {api-spring-framework}/web/reactive/result/view/View.html[View],
858+
{api-spring-framework}/ui/Model.html[Model] or `Map`,
859+
{api-spring-framework}/web/reactive/result/view/Rendering.html[Rendering],
860+
or any other Object is treated as a model attribute.
861+
862+
Also see <<webflux-viewresolution>>.
863+
| `Integer.MAX_VALUE`
864+
865+
|===
866+
867+
868+
869+
[[webflux-dispatcher-exceptions]]
870+
=== Exceptions
871+
[.small]#<<web.adoc#mvc-exceptionhandlers,Same in Spring MVC>>#
872+
873+
The `HandlerResult` returned from a `HandlerAdapter` may expose a function for error
874+
handling based on some handler-specific mechanism. This error function is called if:
875+
876+
* the handler (e.g. `@Controller`) invocation fails.
877+
* handling of the handler return value through a `HandlerResultHandler` fails.
811878

812-
* `ResponseEntityResultHandler` -- handles `ResponseEntity` return values typically
813-
returned from annotated controllers. The order is set to 0 since it safely matches return
814-
values by type.
815-
* `ServerResponseResultHandler` -- supports `ServerResponse` return values typically
816-
returned from functional endpoints. The order is set to 0 since it safely matches return
817-
values by type.
818-
* `ResponseBodyResultHandler` -- handles return values from `@ResponseBody` methods or
819-
`@RestController` classes. The order is set to 100, i.e. after result handlers that
820-
check for a specific type.
821-
* `ViewResolutionResultHandler` -- performs the <<webflux-viewresolution>> algorithm for
822-
HTML template rendering. The order is set to `Ordered.LOWEST_PRECEDENCE` since it
823-
supports several specific types, e.g. `String`, `Map`, `Rendering`, and others, but will
824-
also treat any other Object as a model attribute. This is why it needs to be last in
825-
the order.
879+
The error function can change the response, e.g. to an error status, as long as an error
880+
signal occurs before the reactive type returned from the handler produces any data items.
881+
882+
This is how `@ExceptionHandler` methods in `@Controller` classes are supported.
883+
By contrast, support for the same in Spring MVC is built on a `HandlerExceptionResolver`.
884+
This generally shouldn't matter, however, keep in mind that in WebFlux you cannot use a
885+
`@ControllerAdvice` to handle exceptions that occur before a handler is chosen.
886+
887+
See also <<webflux-ann-controller-exceptions>> in the Annotated Controller section, or
888+
<<webflux-exception-handler>> in the WebHandler API section.
826889

827890

828891

@@ -2159,15 +2222,19 @@ controller method. Use a composite interface if you need to activate multiple vi
21592222

21602223

21612224
[[webflux-ann-modelattrib-methods]]
2162-
=== Model Methods
2225+
=== Model
21632226
[.small]#<<web.adoc#mvc-ann-modelattrib-methods,Same in Spring MVC>>#
21642227

2165-
The `@ModelAttribute` annotation can be used on `@RequestMapping`
2166-
<<webflux-ann-modelattrib-method-args,method arguments>> to create or access an Object
2167-
from the model and bind it to the request. `@ModelAttribute` can also be used as a
2168-
method-level annotation on controller methods whose purpose is not to handle requests
2169-
but to add commonly needed model attributes prior to request handling.
2228+
The `@ModelAttribute` annotation can be used:
2229+
2230+
* On a <<webflux-ann-modelattrib-method-args,method argument>> in `@RequestMapping` methods
2231+
to create or access an Object from the model, and to bind it to the request through a
2232+
`WebDataBinder`.
2233+
* As a method-level annotation in `@Controller` or `@ControllerAdvice` classes helping
2234+
to initialize the model prior to any `@RequestMapping` method invocation.
2235+
* On a `@RequestMapping` method to mark its return value is a model attribute.
21702236

2237+
This section discusses `@ModelAttribute` methods, or the 2nd from the list above.
21712238
A controller can have any number of `@ModelAttribute` methods. All such methods are
21722239
invoked before `@RequestMapping` methods in the same controller. A `@ModelAttribute`
21732240
method can also be shared across controllers via `@ControllerAdvice`. See the section on
@@ -2253,14 +2320,16 @@ as a view name. `@ModelAttribute` can also help to customize the model attribute
22532320

22542321

22552322
[[webflux-ann-initbinder]]
2256-
=== Binder Methods
2323+
=== DataBinder
22572324
[.small]#<<web.adoc#mvc-ann-initbinder,Same in Spring MVC>>#
22582325

2259-
`@InitBinder` methods in an `@Controller` or `@ControllerAdvice` class can be used to
2260-
customize type conversion for method arguments that represent String-based request values
2261-
(e.g. request parameters, path variables, headers, cookies, and others). Type conversion
2262-
also applies during data binding of request parameters onto `@ModelAttribute` arguments
2263-
(i.e. command objects).
2326+
`@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods in order to
2327+
initialize instances of `WebDataBinder`, and those in turn are used to:
2328+
2329+
* Bind request parameters (i.e. form data or query) to a model object.
2330+
* Convert String-based request values such as request parameters, path variables,
2331+
headers, cookies, and others, to the target type of controller method arguments.
2332+
* Format model object values as String values when rendering HTML forms.
22642333

22652334
`@InitBinder` methods can register controller-specific `java.bean.PropertyEditor`, or
22662335
Spring `Converter` and `Formatter` components. In addition, the
@@ -2310,6 +2379,73 @@ controller-specific ``Formatter``'s:
23102379

23112380

23122381

2382+
[[webflux-ann-controller-exceptions]]
2383+
=== Exceptions
2384+
[.small]#<<web.adoc#mvc-ann-exceptionhandler,Same in Spring MVC>>#
2385+
2386+
`@Controller` and <<mvc-ann-controller-advice,@ControllerAdvice>> classes can have
2387+
`@ExceptionHandler` methods to handle exceptions from controller methods. For example:
2388+
2389+
[source,java,indent=0]
2390+
[subs="verbatim,quotes"]
2391+
----
2392+
@Controller
2393+
public class SimpleController {
2394+
2395+
// ...
2396+
2397+
@ExceptionHandler
2398+
public ResponseEntity<String> handle(IOException ex) {
2399+
// ...
2400+
}
2401+
2402+
}
2403+
----
2404+
2405+
The annotation can list the exception types to match. Or simply declare the target
2406+
exception as a method argument as shown above. When multiple exception methods match,
2407+
a root exception match is generally preferred to a cause exception match. More formally
2408+
the `ExceptionDepthComparator` is used to sort exceptions based on their depth from the
2409+
thrown exception type.
2410+
2411+
In a multi-`@ControllerAdvice` arrangement, please declare your primary root exception
2412+
mappings on a `@ControllerAdvice` prioritized with a corresponding order. While a root
2413+
exception match is preferred to a cause, this is mainly among the methods of a given
2414+
controller or `@ControllerAdvice`. That means a cause match on a higher-priority
2415+
`@ControllerAdvice` is preferred to any match (e.g. root) on a lower-priority
2416+
`@ControllerAdvice`.
2417+
2418+
Support for `@ExceptionHandler` methods in Spring WebFlux is provided by the
2419+
`HandlerAdapter` for `@RequestMapping` methods. See <<webflux-dispatcher-exceptions>>
2420+
under the `DispatcherHandler` section for more details.
2421+
2422+
2423+
An `@ExceptionHandler` method in WebFlux supports the same method arguments and return
2424+
values as an `@RequestMapping` method does with the exception of request body and
2425+
`@ModelAttribute` related method arguments.
2426+
2427+
2428+
[[webflux-ann-rest-exceptions]]
2429+
==== REST API exceptions
2430+
[.small]#<<web.adoc#mvc-ann-rest-exceptions,Same in Spring MVC>>#
2431+
2432+
A common requirement for REST services is to include error details in the body of the
2433+
response. The Spring Framework does not automatically do this because the representation
2434+
of error details in the response body is application specific. However a
2435+
`@RestController` may use `@ExceptionHandler` methods with a `ResponseEntity` return
2436+
value to set the status and the body of the response. Such methods may also be declared
2437+
in `@ControllerAdvice` classes to apply them globally.
2438+
2439+
[NOTE]
2440+
====
2441+
Note that Spring WebFlux does not have an equivalent for the Spring MVC
2442+
`ResponseEntityExceptionHandler` because WebFlux only raises `ResponseStatusException`
2443+
(or sub-classes of), which and those do not need to be translated translation to an HTTP
2444+
status code.
2445+
====
2446+
2447+
2448+
23132449
[[webflux-ann-controller-advice]]
23142450
=== Controller Advice
23152451
[.small]#<<web.adoc#mvc-ann-controller-advice,Same in Spring MVC>>#

0 commit comments

Comments
 (0)