8. Web Stacks in Spring 5
7
Servlet Container
Servlet API
Spring MVC
Servlet Stack
9. Web Stacks in Spring 5
7
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
10. Web Stacks in Spring 5
7
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet StackBlocking
11. Web Stacks in Spring 5
7
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet StackBlocking
12. Web Stacks in Spring 5
7
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet StackBlocking
Non-Blocking
13. Web Stacks in Spring 5
7
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet StackBlocking
Non-Blocking
17. ❓Why are we introducing Spring WebFlux?
10
The goal of Spring WebFlux is to offer Spring
developers a non-blocking event-loop style
programming model similar to node.js.
18. the non-blocking async programming model is more
efficient for latency-sensitive workloads.
– Blocking threads consume resources
– mobile applications and interconnected
microservices
❓Why are we introducing Spring WebFlux?
10
The goal of Spring WebFlux is to offer Spring
developers a non-blocking event-loop style
programming model similar to node.js.
19. Web Stacks in Spring 5
11
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
46. flatMap
28
Flux<GHUser> github = findGitHubUsers("foo", "bar",
"hoge");
Flux<User> users = github.map(g
-> findTweets(g)
.collectList()
.map(tweets -> new User(g, tweets)));
users.subscribe();
⚠ Can be compiled but
findTweets won't be
subscribed
47. flatMap
29
Flux<GHUser> github = findGitHubUsers("foo", "bar",
"hoge");
Flux<User> users = github.map(g -> {
Mono<User> u = findTweets(g)
.collectList()
.map(tweets -> new User(g, tweets));
u.subscribe();
return u;
});
users.subscribe();
This will work,
but use flatMap instead
48. Web Stacks in Spring 5
30
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
49. Spring MVC controller
31
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public String hello() {
return hello.sayHello();
}
}
50. Spring MVC controller
31
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public String hello() {
return hello.sayHello();
}
}
Blocking / Synchronous
51. Spring WebFlux controller
32
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public String hello() {
return hello.sayHello();
}
}
52. Spring WebFlux controller
32
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public String hello() {
return hello.sayHello();
}
}
Non-blocking / Synchronous
53. Spring WebFlux controller
33
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello);
}
}
54. Spring WebFlux controller
33
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello);
}
}
Non-blocking / Asynchronous
55. Spring WebFlux controller
33
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello);
}
}
Non-blocking / Asynchronous
You don't need to subscribe the stream
56. Spring WebFlux controller
34
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello)
.flatMap(foo::abc)
.map(bar::xyz);}
Non-blocking / Asynchronous
57. Spring WebFlux controller
34
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello)
.flatMap(foo::abc)
.map(bar::xyz);}
Non-blocking / Asynchronous
Could be executed
in the other thread
58. Spring MVC controller
35
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello)
.flatMap(foo::abc)
.map(bar::xyz);}
Blocking / Asynchronous
59. Spring MVC controller
35
@RestController
public class HelloController {
private final Hello hello;
public HelloController(Hello hello) {
this.hello = hello;
}
@GetMapping("hello")
public Mono<String> hello() {
return Mono.fromCallable(hello::sayHello)
.flatMap(foo::abc)
.map(bar::xyz);}
Blocking / Asynchronous
Async support in
Servlet 3
60. ∞ Stream
36
@RestController
public class HelloController {
@GetMapping("hello")
public Flux<String> hello() {
Flux<String> hello = Flux.just("hello")
.delayElement(Duration.ofMillis(100));
hello.subscribe();
return hello.repeat(); // ∞ Stream
}
}
79. Flux -> Mono
45
@GetMapping("hello")
public Mono<List<Message>> hello() {
return Mono.just(new Message("a"))
.repeat()
.take(100)
.collectList()
.log("message");
}
$ curl -v -H "Accept: application/stream+json" localhost:8080/
messages
> GET /messages HTTP/1.1
> Host: localhost:8080
> Accept: application/stream+json
>
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: application/stream+json;charset=UTF-8
<
[{"text":"a"},{"text":"a"},...,{"text":"a"},{"text":"a"},
{"text":"a"},{"text":"a"}]
INFO 48330 --- [ctor-http-nio-3] message : | request(1)
INFO 48330 --- [ctor-http-nio-3] message : | onNext([a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a])
INFO 48330 --- [ctor-http-nio-3] message : | request(31)
INFO 48330 --- [ctor-http-nio-3] message : | onComplete()
80. Flux -> Mono
45
@GetMapping("hello")
public Mono<List<Message>> hello() {
return Mono.just(new Message("a"))
.repeat()
.take(100)
.collectList()
.log("message");
}
$ curl -v -H "Accept: application/stream+json" localhost:8080/
messages
> GET /messages HTTP/1.1
> Host: localhost:8080
> Accept: application/stream+json
>
< HTTP/1.1 200 OK
< transfer-encoding: chunked
< Content-Type: application/stream+json;charset=UTF-8
<
[{"text":"a"},{"text":"a"},...,{"text":"a"},{"text":"a"},
{"text":"a"},{"text":"a"}]
INFO 48330 --- [ctor-http-nio-3] message : | request(1)
INFO 48330 --- [ctor-http-nio-3] message : | onNext([a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a,
a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a])
INFO 48330 --- [ctor-http-nio-3] message : | request(31)
INFO 48330 --- [ctor-http-nio-3] message : | onComplete()
❌ Backpressure
81. Spring WebFlux controller (Receiving Flux)
46
@RestController
public class HelloController {
@PostMapping("upper")
public Flux<String>
upper(@RequestBody Flux<String> input) {
Flux<String> output = input
.map(String::toUpperCase);
return output;
}
}
88. Spring MVC controller (Receiving Flux)
51
@RestController
public class HelloController {
@PostMapping("upper")
public Flux<String>
hello(@RequestBody Flux<String> input) {
Flux<String> output = input
.map(String::toUpperCase);
return output;
}
}
89. Spring MVC controller (Receiving Flux)
51
@RestController
public class HelloController {
@PostMapping("upper")
public Flux<String>
hello(@RequestBody Flux<String> input) {
Flux<String> output = input
.map(String::toUpperCase);
return output;
}
}
🙅
90. Spring MVC controller (Receiving Flux)
51
@RestController
public class HelloController {
@PostMapping("upper")
public Flux<String>
hello(@RequestBody Flux<String> input) {
Flux<String> output = input
.map(String::toUpperCase);
return output;
}
}
🙅Reactive type are supported only as
controller method return values
91. Broadcast stream
52
@RestController
public class HelloController {
private final Flux<String> flux;
public HelloController() {
this.flux = this.createHotStream().share();
this.flux.subscribe();
}
@GetMapping("hello")
public Flux<String> hello() {
return this.flux;
}}
92. Broadcast stream
52
@RestController
public class HelloController {
private final Flux<String> flux;
public HelloController() {
this.flux = this.createHotStream().share();
this.flux.subscribe();
}
@GetMapping("hello")
public Flux<String> hello() {
return this.flux;
}}
this stream is shared by all http
clients!
96. Web Stacks in Spring 5
55
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
97. Web Stacks in Spring 5
55
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
•Annotated Controller
•Function Endpoints (WebFlux.fn)
98. @Configuration
public class RouterConfig {
@Bean
public RouterFunctions<ServerResponse> routes() {
return route(GET("hello"), req -> {
return ServerReponse.ok()
.body(Mono.just("hello"), String.class);
});
}
}
Spring WebFlux.fn
56
99. @Configuration
public class RouterConfig {
@Bean
public RouterFunctions<ServerResponse> routes() {
return route(GET("hello"), req -> {
return ServerReponse.ok()
.body(Mono.just("hello"), String.class);
});
}
}
lambda
Spring WebFlux.fn
56
100. Spring WebFlux.fn
57
@Configuration
public class RouterConfig {
@Bean
public RouterFunctions<ServerResponse>
routes(HelloHandler helloHandler) {
return route(GET("hello"), helloHandler::hello);
}
}
103. Web Stacks in Spring 5
60
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
104. Web Stacks in Spring 5
60
Servlet Container
Servlet API
Spring MVC
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Servlet Stack
Reactive Web Client
105. Reactive Web Client
61
@RestController
public class HelloController {
private final WebClient client;
public HelloController(WebClinet.Builer b) {
this.client = b.build();
}
@GetMapping("hello")
public Flux<String> hello() {
return this.client.get().uri("http://blahblah")
.retrieve().bodyToFlux(String.class);
}}
122. Reactive Support in Spring Projects
72
Spring Data
Reactive Stack
Netty, Servlet 3.1+,
Undertow
Reactive Streams
Spring WebFlux
Spring Security
Thymeleaf
123. Spring Data Kay
73
Reactive support for
• Redis
• MongoDB
• Couchbase
• Cassandra
Infinite streams from the database with @Tailable
128. But, but, JDBC is blocking .... 😭
77
Let's see what will happen in next Java
129. But, but, JDBC is blocking .... 😭
77
Let's see what will happen in next Java
https://static.rainfocus.com/oracle/oow17/sess/1491948952321001dm4m/PF/JavaOne%2017%20-
%20CON1491_1506954898905001IipH.pdf
140. Spring Cloud Gateway
86
A Gateway built on Spring Framework 5.0 and Spring
Boot 2.0 providing routing and more
http://cloud.spring.io/spring-cloud-gateway/
http://cloud.spring.io/spring-cloud-gateway/2.0.x/single/
spring-cloud-gateway.html
144. Thanks!
90
Resources
• Servlet vs Reactive Stacks in Five Use Cases
• Spring Boot 2 0 Web Applications
• Spring Framework 5: Themes & Trends
• Why Spring ❤ Kotlin