diff --git a/src/asciidoc/images/web-reactive-overview.png b/src/asciidoc/images/web-reactive-overview.png new file mode 100644 index 0000000000..65538cf8c4 Binary files /dev/null and b/src/asciidoc/images/web-reactive-overview.png differ diff --git a/src/asciidoc/web-reactive.adoc b/src/asciidoc/web-reactive.adoc new file mode 100644 index 0000000000..e439d8b986 --- /dev/null +++ b/src/asciidoc/web-reactive.adoc @@ -0,0 +1,196 @@ +[[web-reactive]] += Web Reactive Framework +This section provides basic information on the Spring Web Reactive support in Spring Framework 5. + + +[[web-reactive-intro]] +== Introduction + + +[[web-reactive-programming]] +=== Reactive Programming + +In plain terms reactive programming is about non-blocking applications that are asynchronous +and event-driven and require a small number of threads to scale. A key aspect of that +definition is the concept of backpressure which is a mechanism to ensures producers +don't overwhelm consumers. For example in a pipeline of reactive components that extends +from the database to the HTTP server when an HTTP connection slows down the data +repository slows down as well or stops until capacity frees up. + +Reactive programming involves a shift from imperative to declarative, async composition +of logic. This is comparable to how `CompletableFuture` in Java 8 allows declaring +follow-up actions in lambda expressions to be executed when the future completes. + +A proper introduction to Reactive programming is beyond scope of this documentation. +For a more extended introduction check the excellent multi-part series +https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape["Notes on Reactive Programming"] +by Dave Syer. + + +[[web-reactive-api]] +=== Spring Web Reactive Types + +Spring Framework 5 embraces +https://github.com/reactive-streams/reactive-streams-jvm#reactive-streams[Reactive Streams] +as the contract for communicating backpressure across async components and +libraries. Reactive Streams is the result of an industry collaboration and is also +adopted in Java 9 as `java.util.concurrent.Flow`. + +For its own reactive support the Spring Framework relies on +https://projectreactor.io/[Reactor] which implements Reactive Streams and extends +the Reactive Streams `Publisher` contract with the `Flux` and `Mono` composable API +types that provide declarative operations on data sequence of `0..N` and `0..1`. + +The Spring Framework exposes `Flux` and `Mono` in many of its reactive APIs. +At the application level however as always Spring provides choice and fully supports +the use of RxJava. For more on reactive types check the blog post +https://spring.io/blog/2016/04/19/understanding-reactive-types["Understanding Reactive Types"] +by Sebastien Deleuze. + + +[[web-reactive-feature-overview]] +== Spring Reactive Web Overview + + +[[web-reactive-module]] +=== Spring Web Reactive Module + + +Spring Framework 5 adds a new `spring-web-reactive` module that supports the same +`@Controller` and `@RestController` programming model as Spring MVC but executed +on a reactive and non-blocking foundation. The diagram below shows how Spring MVC +and Spring Web Reactive side by side: + +image::images/web-reactive-overview.png[width=720] + +Spring Web Reactive makes use of the Servlet 3.1 non-blocking I/O API and runs on +Servlet 3.1 containers and also on other non-blocking runtimes such as Netty and Undertow. +Each runtime is adapted to a set of shared, reactive `ServerHttpRequest` and +`ServerHttpResponse` abstractions that expose the request and response body +as `Flux` with full backpressure support on the read and the +write side. + +The `spring-core` module provides reactive `Encoder` and `Decoder` contracts +that enable the serialization of a `Flux` of bytes to and from typed objects +along with some basic implementations. + +The `spring-web` modules adds JSON and XML implementations for use in reactive +web applications and also provides support for SSE streaming and zero-copy +file transfer. + +The `spring-web-reactive` module defines many of the same contracts as +Spring MVC such as `HandlerMapping` and `HandlerAdapter` among others. +These reactive counterparts have asynchronous and non-blocking semantics and +operate on the reactive HTTP request and response abstractions. + +The end result is a programming model identical to today's Spring MVC but +supporting reactive types and executing on a reactive, non-blocking foundation. +For example a controller method can declare any of the following as a method argument: + +* `@RequestBody Account account` -- the account is deserialized without +blocking before the controller method is invoked. +* `@RequestBody Mono account` -- the controller can use the `Mono` +type to declare the logic execute when the account is deserialized. +* `@RequestBody Single account` -- same but with RxJava +* `@RequestBody Flux` accounts` -- streaming scenario. +* `@RequestBody Observable accounts` -- streaming with RxJava. + +The same principle also applies on the side of return value handling. + + +[[web-reactive-client]] +=== Reactive Web Client + +Spring Framework 5 adds a new reactive `WebClient` in addition to the existing `RestTemplate`. + +Much like on the server side each supported HTTP client is adapted to a set of shared, +reactive `ClientHttpRequest` and `ClientHttpResponse` abstractions that expose the request +and response body as `Flux` with full backpressure support on the read and +the write side. The `Encoder` and `Decoder` abstractions from `spring-core` also used on +the client side for serialization of a `Flux` of bytes to and from typed objects. + +Below is an example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +ClientHttpConnector httpConnector = new ReactorClientHttpConnector(); +WebClient webClient = new WebClient(httpConnector); + +Mono response = webClient + .perform(get("http://example.com/accounts/1").accept(APPLICATION_JSON)) + .extract(body(Account.class)); +---- + +The above example assumes the import of static methods from `ClientWebRequestBuilder` +and `ResponseExtractors`. The enable a fluent syntax similar to that of the MockMvc API +from Spring MVC Test. The same can also be done with RxJava. Simply replace with static +imports from `RxJava1ClientWebRequestBuilder` and `RxJava1ResponseExtractors`: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +Single response = webClient + .perform(get("http://example.com/accounts/1").accept(APPLICATION_JSON)) + .extract(body(Account.class)); +---- + + +[[web-reactive-getting-started]] +== Getting Started + + +[[web-reactive-getting-started-boot]] +=== Spring Boot Starter + +The quickest way to get started is through the experimental Spring Boot Web Reactive +starter available on http://start.spring.io. It does all the work so you can simply start +writing `@Controller` classes. By default the starter runs with Tomcat but you can change +the dependencies and use one of the other supported HTTP runtimes. + + +[[web-reactive-getting-started-manual]] +=== Manual Bootstrapping + +It is also easy to get started by writing a few lines of code: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- +AnnotationConfigApplicationContext context; +context = new AnnotationConfigApplicationContext(); +context.register(WebReactiveConfiguration.class); // (1) +context.refresh(); + +DispatcherHandler handler = new DispatcherHandler(); // (2) +handler.setApplicationContext(context); +HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(handler).build(); + +HttpServer server = new TomcatHttpServer(); // (3) +server.setPort(8080); +server.setHandler(httpHandler); +server.afterPropertiesSet(); +server.start(); +---- + +The `WebReactiveConfiguration` at (1) is the Web Reactive Java config from the `spring-web-reactive` +and is similar in purpose to the MVC Java config from `spring-webmvc`. It provides the +the web framework configuration required to get started leaving you only to +declare your own `@Controller' beans. + +The `DispatcherHandler` at (2) is the equivalent of the `DispatcherServlet` in Spring MVC. + +The `HttpServer` at (3) is an abstraction from the +https://github.com/spring-projects/spring-framework/tree/master/spring-web/src/test/java/org/springframework/http/server/reactive/bootstrap[test sources] +of the `spring-web-reactive` module that's used for the framework's own integration tests. +It comes with basic implementations of all supported runtimes. + + +[[web-reactive-getting-started-M1]] +=== Extent of M1 Support + +For M1 the Spring Web Reactive module focuses on support for REST scenarios both +client and server-side. Basic HTML rendering with Freemarker is also supported but +limited to rendering, i.e. there is no support form submissions yet. + +On the client side for M1 the Reactor Netty HTTP client is supported. diff --git a/src/asciidoc/web.adoc b/src/asciidoc/web.adoc index 380934cc41..8a7a56bda3 100644 --- a/src/asciidoc/web.adoc +++ b/src/asciidoc/web.adoc @@ -29,3 +29,5 @@ include::web-cors.adoc[leveloffset=+1] include::web-integration.adoc[leveloffset=+1] include::web-websocket.adoc[leveloffset=+1] + +include::web-reactive.adoc[leveloffset=+1]