@@ -3234,39 +3234,36 @@ See the Javadoc of `DeferredResult` for more details. `Callable` can be substitu
3234
3234
[[mvc-ann-async-vs-webflux]]
3235
3235
==== Compared to WebFlux
3236
3236
3237
- The Servlet API was originally built for sequential processing, i.e. making a single pass
3238
- through the Filter-Servlet chain. The asynchronous request processing feature added in
3239
- Servlet 3.0 allows applications to exit the Filter-Servlet chain but leave the response
3240
- open, therefore breaking this thread-per-request model.
3241
-
3242
- Spring MVC async support is built around that model. When a controller returns a
3243
- `DeferredResult`, the Filter-Servlet chain is exited and the Servlet container thread is
3244
- released. Later when the `DeferredResult` is set, an ASYNC dispatch (to the same URL) is
3245
- made during which the controller is mapped again but not invoked. Instead the
3246
- `DeferredResult` value is used to resume processing.
3247
-
3248
- Spring WebFlux is not aware of the Servlet API nor does it such an asynchronous request
3249
- processing feature because it is asynchronous by design. It processes each request in
3250
- stages (continuations) rather than making a single pass through the callstack on a single
3251
- thread. That means asynchronous handling is built into all framework contracts and is
3252
- therefore intrinsically supported at all stages of request processing.
3253
-
3254
- Essentially both Spring MVC and Spring WebFlux support asynchronous and
3255
- <<mvc-ann-async-reactive-types>> for return values from controller methods. Spring MVC
3256
- even supports streaming, including reactive back pressure, however individual writes to
3257
- the response remain blocking (performed in a separate thread) and that is one major
3258
- difference with WebFlux which relies on non-blocking I/O.
3237
+ The Servlet API was originally built for making a single pass through the Filter-Servlet
3238
+ chain. Asynchronous request processing, added in Servlet 3.0, allows applications to exit
3239
+ the Filter-Servlet chain but leave the response open for further processing. The Spring MVC
3240
+ async support is built around that mechanism. When a controller returns a `DeferredResult`,
3241
+ the Filter-Servlet chain is exited and the Servlet container thread is released. Later when
3242
+ the `DeferredResult` is set, an ASYNC dispatch (to the same URL) is made during which the
3243
+ controller is mapped again but rather than invoking it, the `DeferredResult` value is used
3244
+ (as if the controller returned it) to resume processing.
3245
+
3246
+ By contrast Spring WebFlux is neither built on the Servlet API, nor does it need such an
3247
+ asynchronous request processing feature because it is asynchronous by design. Asynchronous
3248
+ handling is built into all framework contracts and is intrinsically supported through ::
3249
+ stages of request processing.
3250
+
3251
+ From a programming model perspective, both Spring MVC and Spring WebFlux support
3252
+ asynchronous and <<mvc-ann-async-reactive-types>> as return values in controller methods.
3253
+ Spring MVC even supports streaming, including reactive back pressure. However individual
3254
+ writes to the response remain blocking (and performed on a separate thread) unlike WebFlux
3255
+ that relies on non-blocking I/O and does not need an extra thread for each write.
3259
3256
3260
3257
Another fundamental difference is that Spring MVC does not support asynchronous or
3261
3258
reactive types in controller method arguments, e.g. `@RequestBody`, `@RequestPart`, and
3262
3259
others, nor does it have any explicit support for asynchronous and reactive types as
3263
- model attributes, all of which Spring WebFlux does support.
3260
+ model attributes. Spring WebFlux does support all that .
3264
3261
3265
3262
3266
3263
3267
3264
[[mvc-ann-async-http-streaming]]
3268
3265
=== HTTP Streaming
3269
- [.small]#<<mvc-ann-async-vs-webflux,Compared to WebFlux>>#
3266
+ [.small]#<<web-reactive.adoc#webflux-codecs-streaming,Same in Spring WebFlux>>#
3270
3267
3271
3268
`DeferredResult` and `Callable` can be used for a single asynchronous return value.
3272
3269
What if you want to produce multiple asynchronous values and have those written to the
@@ -3377,7 +3374,7 @@ customize the status and headers of the response.
3377
3374
3378
3375
[[mvc-ann-async-reactive-types]]
3379
3376
=== Reactive types
3380
- [.small]#<<mvc-ann-async-vs-webflux,Compared to WebFlux>>#
3377
+ [.small]#<<web-reactive.adoc#webflux-codecs-streaming,Same in Spring WebFlux>>#
3381
3378
3382
3379
Spring MVC supports use of reactive client libraries in a controller. This includes the
3383
3380
`WebClient` from `spring-webflux` and others such as Spring Data reactive data
@@ -3402,12 +3399,31 @@ Spring MVC supports Reactor and RxJava through the
3402
3399
`spring-core` which allows it to adapt from multiple reactive libraries.
3403
3400
====
3404
3401
3405
- When streaming to the response with a reactive type, Spring MVC performs (blocking)
3406
- writes to the response through the
3407
- through the <<mvc-ann-async-configuration-spring-mvc,configured>> MVC `TaskExecutor`.
3408
- By default this is a `SyncTaskExecutor` and not suitable for production.
3409
- https://jira.spring.io/browse/SPR-16203[SPR-16203] will provide better defaults.
3410
- In the mean time please configure the executor through the MVC config.
3402
+ When streaming to the response via reactive types, Spring MVC supports reactive back
3403
+ pressure, but still needs to use blocking I/O to perform actual writes. This is done
3404
+ through the <<mvc-ann-async-configuration-spring-mvc,configured>> MVC `TaskExecutor` on
3405
+ a separate thread in order to avoid blocking the upstream source (e.g. a `Flux` returned
3406
+ from the `WebClient`). By default a `SyncTaskExecutor` is used which is not suitable for
3407
+ production. https://jira.spring.io/browse/SPR-16203[SPR-16203] will provide better
3408
+ defaults in Spring Framework 5.1. In the mean time please configure the executor through
3409
+ the <<mvc-ann-async-configuration-spring-mvc,MVC config>>.
3410
+
3411
+
3412
+
3413
+ [[mvc-ann-async-disconnects]]
3414
+ === Disconnects
3415
+ [.small]#<<web-reactive.adoc#webflux-codecs-streaming,Same in Spring WebFlux>>#
3416
+
3417
+ The Servlet API does not provide any notification when a remote client goes away.
3418
+ Therefore while streaming to the response, whether via <<mvc-ann-async-sse,SseEmitter>> or
3419
+ <<mvc-ann-async-reactive-types,reactive types>, it is important to send data periodically,
3420
+ since the write would fail if the client has disconnected. The send could take the form
3421
+ of an empty (comment-only) SSE event, or any other data that the other side would have to
3422
+ to interpret as a heartbeat and ignore.
3423
+
3424
+ Alternatively consider using web messaging solutions such as
3425
+ <<websocket-stomp,STOMP over WebSocket>> or WebSocket with <<websocket-fallback,SockJS>>
3426
+ that have a built-in heartbeat mechanism.
3411
3427
3412
3428
3413
3429
0 commit comments