Skip to content

Commit 5cf8b69

Browse files
committed
Add chapter on Spring Web Reactive support
Issue: SPR-14497
1 parent af4415e commit 5cf8b69

File tree

3 files changed

+198
-0
lines changed

3 files changed

+198
-0
lines changed
46.9 KB
Loading

src/asciidoc/web-reactive.adoc

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
[[web-reactive]]
2+
= Web Reactive Framework
3+
This section provides basic information on the Spring Web Reactive support in Spring Framework 5.
4+
5+
6+
[[web-reactive-intro]]
7+
== Introduction
8+
9+
10+
[[web-reactive-programming]]
11+
=== Reactive Programming
12+
13+
In plain terms reactive programming is about non-blocking applications that are asynchronous
14+
and event-driven and require a small number of threads to scale. A key aspect of that
15+
definition is the concept of backpressure which is a mechanism to ensures producers
16+
don't overwhelm consumers. For example in a pipeline of reactive components that extends
17+
from the database to the HTTP server when an HTTP connection slows down the data
18+
repository slows down as well or stops until capacity frees up.
19+
20+
Reactive programming involves a shift from imperative to declarative, async composition
21+
of logic. This is comparable to how `CompletableFuture` in Java 8 allows declaring
22+
follow-up actions in lambda expressions to be executed when the future completes.
23+
24+
A proper introduction to Reactive programming is beyond scope of this documentation.
25+
For a more extended introduction check the excellent multi-part series
26+
https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape["Notes on Reactive Programming"]
27+
by Dave Syer.
28+
29+
30+
[[web-reactive-api]]
31+
=== Spring Web Reactive Types
32+
33+
Spring Framework 5 embraces
34+
https://github.com/reactive-streams/reactive-streams-jvm#reactive-streams[Reactive Streams]
35+
as the contract for communicating backpressure across async components and
36+
libraries. Reactive Streams is the result of an industry collaboration and is also
37+
adopted in Java 9 as `java.util.concurrent.Flow`.
38+
39+
For its own reactive support the Spring Framework relies on
40+
https://projectreactor.io/[Reactor] which implements Reactive Streams and extends
41+
the Reactive Streams `Publisher` contract with the `Flux` and `Mono` composable API
42+
types that provide declarative operations on data sequence of `0..N` and `0..1`.
43+
44+
The Spring Framework exposes `Flux` and `Mono` in many of its reactive APIs.
45+
At the application level however as always Spring provides choice and fully supports
46+
the use of RxJava. For more on reactive types check the blog post
47+
https://spring.io/blog/2016/04/19/understanding-reactive-types["Understanding Reactive Types"]
48+
by Sebastien Deleuze.
49+
50+
51+
[[web-reactive-feature-overview]]
52+
== Spring Reactive Web Overview
53+
54+
55+
[[web-reactive-module]]
56+
=== Spring Web Reactive Module
57+
58+
59+
Spring Framework 5 adds a new `spring-web-reactive` module that supports the same
60+
`@Controller` and `@RestController` programming model as Spring MVC but executed
61+
on a reactive and non-blocking foundation. The diagram below shows how Spring MVC
62+
and Spring Web Reactive side by side:
63+
64+
image::images/web-reactive-overview.png[width=720]
65+
66+
Spring Web Reactive makes use of the Servlet 3.1 non-blocking I/O API and runs on
67+
Servlet 3.1 containers and also on other non-blocking runtimes such as Netty and Undertow.
68+
Each runtime is adapted to a set of shared, reactive `ServerHttpRequest` and
69+
`ServerHttpResponse` abstractions that expose the request and response body
70+
as `Flux<DataBuffer>` with full backpressure support on the read and the
71+
write side.
72+
73+
The `spring-core` module provides reactive `Encoder` and `Decoder` contracts
74+
that enable the serialization of a `Flux` of bytes to and from typed objects
75+
along with some basic implementations.
76+
77+
The `spring-web` modules adds JSON and XML implementations for use in reactive
78+
web applications and also provides support for SSE streaming and zero-copy
79+
file transfer.
80+
81+
The `spring-web-reactive` module defines many of the same contracts as
82+
Spring MVC such as `HandlerMapping` and `HandlerAdapter` among others.
83+
These reactive counterparts have asynchronous and non-blocking semantics and
84+
operate on the reactive HTTP request and response abstractions.
85+
86+
The end result is a programming model identical to today's Spring MVC but
87+
supporting reactive types and executing on a reactive, non-blocking foundation.
88+
For example a controller method can declare any of the following as a method argument:
89+
90+
* `@RequestBody Account account` -- the account is deserialized without
91+
blocking before the controller method is invoked.
92+
* `@RequestBody Mono<Account> account` -- the controller can use the `Mono`
93+
type to declare the logic execute when the account is deserialized.
94+
* `@RequestBody Single<Account> account` -- same but with RxJava
95+
* `@RequestBody Flux<Account>` accounts` -- streaming scenario.
96+
* `@RequestBody Observable<Account> accounts` -- streaming with RxJava.
97+
98+
The same principle also applies on the side of return value handling.
99+
100+
101+
[[web-reactive-client]]
102+
=== Reactive Web Client
103+
104+
Spring Framework 5 adds a new reactive `WebClient` in addition to the existing `RestTemplate`.
105+
106+
Much like on the server side each supported HTTP client is adapted to a set of shared,
107+
reactive `ClientHttpRequest` and `ClientHttpResponse` abstractions that expose the request
108+
and response body as `Flux<DataBuffer>` with full backpressure support on the read and
109+
the write side. The `Encoder` and `Decoder` abstractions from `spring-core` also used on
110+
the client side for serialization of a `Flux` of bytes to and from typed objects.
111+
112+
Below is an example:
113+
114+
[source,java,indent=0]
115+
[subs="verbatim,quotes"]
116+
----
117+
ClientHttpConnector httpConnector = new ReactorClientHttpConnector();
118+
WebClient webClient = new WebClient(httpConnector);
119+
120+
Mono<Account> response = webClient
121+
.perform(get("http://example.com/accounts/1").accept(APPLICATION_JSON))
122+
.extract(body(Account.class));
123+
----
124+
125+
The above example assumes the import of static methods from `ClientWebRequestBuilder`
126+
and `ResponseExtractors`. The enable a fluent syntax similar to that of the MockMvc API
127+
from Spring MVC Test. The same can also be done with RxJava. Simply replace with static
128+
imports from `RxJava1ClientWebRequestBuilder` and `RxJava1ResponseExtractors`:
129+
130+
[source,java,indent=0]
131+
[subs="verbatim,quotes"]
132+
----
133+
Single<Account> response = webClient
134+
.perform(get("http://example.com/accounts/1").accept(APPLICATION_JSON))
135+
.extract(body(Account.class));
136+
----
137+
138+
139+
[[web-reactive-getting-started]]
140+
== Getting Started
141+
142+
143+
[[web-reactive-getting-started-boot]]
144+
=== Spring Boot Starter
145+
146+
The quickest way to get started is through the experimental Spring Boot Web Reactive
147+
starter available on http://start.spring.io. It does all the work so you can simply start
148+
writing `@Controller` classes. By default the starter runs with Tomcat but you can change
149+
the dependencies and use one of the other supported HTTP runtimes.
150+
151+
152+
[[web-reactive-getting-started-manual]]
153+
=== Manual Bootstrapping
154+
155+
It is also easy to get started by writing a few lines of code:
156+
157+
[source,java,indent=0]
158+
[subs="verbatim,quotes"]
159+
----
160+
AnnotationConfigApplicationContext context;
161+
context = new AnnotationConfigApplicationContext();
162+
context.register(WebReactiveConfiguration.class); // (1)
163+
context.refresh();
164+
165+
DispatcherHandler handler = new DispatcherHandler(); // (2)
166+
handler.setApplicationContext(context);
167+
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(handler).build();
168+
169+
HttpServer server = new TomcatHttpServer(); // (3)
170+
server.setPort(8080);
171+
server.setHandler(httpHandler);
172+
server.afterPropertiesSet();
173+
server.start();
174+
----
175+
176+
The `WebReactiveConfiguration` at (1) is the Web Reactive Java config from the `spring-web-reactive`
177+
and is similar in purpose to the MVC Java config from `spring-webmvc`. It provides the
178+
the web framework configuration required to get started leaving you only to
179+
declare your own `@Controller' beans.
180+
181+
The `DispatcherHandler` at (2) is the equivalent of the `DispatcherServlet` in Spring MVC.
182+
183+
The `HttpServer` at (3) is an abstraction from the
184+
https://github.com/spring-projects/spring-framework/tree/master/spring-web/src/test/java/org/springframework/http/server/reactive/bootstrap[test sources]
185+
of the `spring-web-reactive` module that's used for the framework's own integration tests.
186+
It comes with basic implementations of all supported runtimes.
187+
188+
189+
[[web-reactive-getting-started-M1]]
190+
=== Extent of M1 Support
191+
192+
For M1 the Spring Web Reactive module focuses on support for REST scenarios both
193+
client and server-side. Basic HTML rendering with Freemarker is also supported but
194+
limited to rendering, i.e. there is no support form submissions yet.
195+
196+
On the client side for M1 the Reactor Netty HTTP client is supported.

src/asciidoc/web.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ include::web-cors.adoc[leveloffset=+1]
2929
include::web-integration.adoc[leveloffset=+1]
3030

3131
include::web-websocket.adoc[leveloffset=+1]
32+
33+
include::web-reactive.adoc[leveloffset=+1]

0 commit comments

Comments
 (0)