-
Notifications
You must be signed in to change notification settings - Fork 0
/
web-reactive.html
12881 lines (12444 loc) · 870 KB
/
web-reactive.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.12">
<title>Web on Reactive Stack</title>
<link rel="stylesheet" href="css/site.css">
<script src="js/setup.js"></script><script defer src="js/site.js"></script>
<script type="application/json" id="anchor-rewrite">
{
"aot":"core.aot",
"aot-basics":"core.aot.basics",
"aot-bean-factory-initialization-contributions":"core.aot.bean-factory-initialization-contributions",
"aot-bean-registration-contributions":"core.aot.bean-registration-contributions",
"aot-hints":"core.aot.hints",
"aot-hints-import-runtime-hints":"core.aot.hints.import-runtime-hints",
"aot-hints-reflective":"core.aot.hints.reflective",
"aot-hints-register-reflection-for-binding":"core.aot.hints.register-reflection-for-binding",
"aot-refresh":"core.aot.refresh"
}
</script>
</head>
<body id="spring-web-reactive" class="book toc2 toc-left"><div id="banner-container" class="container" role="banner">
<div id="banner" class="contained" role="banner">
<div id="switch-theme">
<input type="checkbox" id="switch-theme-checkbox"/>
<label for="switch-theme-checkbox">Dark Theme</label>
</div>
</div>
</div>
<div id="tocbar-container" class="container" role="navigation">
<div id="tocbar" class="contained" role="navigation">
<button id="toggle-toc"></button>
</div>
</div>
<div id="main-container" class="container">
<div id="main" class="contained">
<div id="doc" class="doc">
<div id="header">
<h1>Web on Reactive Stack</h1>
<div class="details">
<span id="revnumber">version 6.0.8</span>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<span id="back-to-index"><a href="index.html">Back to index</a></span><ul class="sectlevel1">
<li><a href="#webflux">1. Spring WebFlux</a>
<ul class="sectlevel2">
<li><a href="#webflux-new-framework">1.1. Overview</a>
<ul class="sectlevel3">
<li><a href="#webflux-why-reactive">1.1.1. Define “Reactive”</a></li>
<li><a href="#webflux-reactive-api">1.1.2. Reactive API</a></li>
<li><a href="#webflux-programming-models">1.1.3. Programming Models</a></li>
<li><a href="#webflux-framework-choice">1.1.4. Applicability</a></li>
<li><a href="#webflux-server-choice">1.1.5. Servers</a></li>
<li><a href="#webflux-performance">1.1.6. Performance</a></li>
<li><a href="#webflux-concurrency-model">1.1.7. Concurrency Model</a>
<ul class="sectlevel4">
<li><a href="#invoking-a-blocking-api">Invoking a Blocking API</a></li>
<li><a href="#mutable-state">Mutable State</a></li>
<li><a href="#threading-model">Threading Model</a></li>
<li><a href="#configuring">Configuring</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#webflux-reactive-spring-web">1.2. Reactive Core</a>
<ul class="sectlevel3">
<li><a href="#webflux-httphandler">1.2.1. <code>HttpHandler</code></a></li>
<li><a href="#webflux-web-handler-api">1.2.2. <code>WebHandler</code> API</a>
<ul class="sectlevel4">
<li><a href="#webflux-web-handler-api-special-beans">Special bean types</a></li>
<li><a href="#webflux-form-data">Form Data</a></li>
<li><a href="#webflux-multipart">Multipart Data</a></li>
<li><a href="#webflux-forwarded-headers">Forwarded Headers</a></li>
</ul>
</li>
<li><a href="#webflux-filters">1.2.3. Filters</a>
<ul class="sectlevel4">
<li><a href="#webflux-filters-cors">CORS</a></li>
</ul>
</li>
<li><a href="#webflux-exception-handler">1.2.4. Exceptions</a></li>
<li><a href="#webflux-codecs">1.2.5. Codecs</a>
<ul class="sectlevel4">
<li><a href="#webflux-codecs-jackson">Jackson JSON</a></li>
<li><a href="#webflux-codecs-forms">Form Data</a></li>
<li><a href="#webflux-codecs-multipart">Multipart</a></li>
<li><a href="#webflux-codecs-limits">Limits</a></li>
<li><a href="#webflux-codecs-streaming">Streaming</a></li>
<li><a href="#webflux-codecs-buffers"><code>DataBuffer</code></a></li>
</ul>
</li>
<li><a href="#webflux-logging">1.2.6. Logging</a>
<ul class="sectlevel4">
<li><a href="#webflux-logging-id">Log Id</a></li>
<li><a href="#webflux-logging-sensitive-data">Sensitive Data</a></li>
<li><a href="#webflux-logging-appenders">Appenders</a></li>
<li><a href="#webflux-codecs-custom">Custom codecs</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#webflux-dispatcher-handler">1.3. <code>DispatcherHandler</code></a>
<ul class="sectlevel3">
<li><a href="#webflux-special-bean-types">1.3.1. Special Bean Types</a></li>
<li><a href="#webflux-framework-config">1.3.2. WebFlux Config</a></li>
<li><a href="#webflux-dispatcher-handler-sequence">1.3.3. Processing</a></li>
<li><a href="#webflux-resulthandling">1.3.4. Result Handling</a></li>
<li><a href="#webflux-dispatcher-exceptions">1.3.5. Exceptions</a></li>
<li><a href="#webflux-viewresolution">1.3.6. View Resolution</a>
<ul class="sectlevel4">
<li><a href="#webflux-viewresolution-handling">Handling</a></li>
<li><a href="#webflux-redirecting-redirect-prefix">Redirecting</a></li>
<li><a href="#webflux-multiple-representations">Content Negotiation</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#webflux-controller">1.4. Annotated Controllers</a>
<ul class="sectlevel3">
<li><a href="#webflux-ann-controller">1.4.1. <code>@Controller</code></a>
<ul class="sectlevel4">
<li><a href="#webflux-ann-requestmapping-proxying">AOP Proxies</a></li>
</ul>
</li>
<li><a href="#webflux-ann-requestmapping">1.4.2. Request Mapping</a>
<ul class="sectlevel4">
<li><a href="#webflux-ann-requestmapping-uri-templates">URI Patterns</a></li>
<li><a href="#webflux-ann-requestmapping-pattern-comparison">Pattern Comparison</a></li>
<li><a href="#webflux-ann-requestmapping-consumes">Consumable Media Types</a></li>
<li><a href="#webflux-ann-requestmapping-produces">Producible Media Types</a></li>
<li><a href="#webflux-ann-requestmapping-params-and-headers">Parameters and Headers</a></li>
<li><a href="#webflux-ann-requestmapping-head-options">HTTP HEAD, OPTIONS</a></li>
<li><a href="#webflux-ann-requestmapping-composed">Custom Annotations</a></li>
<li><a href="#webflux-ann-requestmapping-registration">Explicit Registrations</a></li>
</ul>
</li>
<li><a href="#webflux-ann-methods">1.4.3. Handler Methods</a>
<ul class="sectlevel4">
<li><a href="#webflux-ann-arguments">Method Arguments</a></li>
<li><a href="#webflux-ann-return-types">Return Values</a></li>
<li><a href="#webflux-ann-typeconversion">Type Conversion</a></li>
<li><a href="#webflux-ann-matrix-variables">Matrix Variables</a></li>
<li><a href="#webflux-ann-requestparam"><code>@RequestParam</code></a></li>
<li><a href="#webflux-ann-requestheader"><code>@RequestHeader</code></a></li>
<li><a href="#webflux-ann-cookievalue"><code>@CookieValue</code></a></li>
<li><a href="#webflux-ann-modelattrib-method-args"><code>@ModelAttribute</code></a></li>
<li><a href="#webflux-ann-sessionattributes"><code>@SessionAttributes</code></a></li>
<li><a href="#webflux-ann-sessionattribute"><code>@SessionAttribute</code></a></li>
<li><a href="#webflux-ann-requestattrib"><code>@RequestAttribute</code></a></li>
<li><a href="#webflux-multipart-forms">Multipart Content</a></li>
<li><a href="#webflux-ann-requestbody"><code>@RequestBody</code></a></li>
<li><a href="#webflux-ann-httpentity"><code>HttpEntity</code></a></li>
<li><a href="#webflux-ann-responsebody"><code>@ResponseBody</code></a></li>
<li><a href="#webflux-ann-responseentity"><code>ResponseEntity</code></a></li>
<li><a href="#webflux-ann-jackson">Jackson JSON</a></li>
</ul>
</li>
<li><a href="#webflux-ann-modelattrib-methods">1.4.4. <code>Model</code></a></li>
<li><a href="#webflux-ann-initbinder">1.4.5. <code>DataBinder</code></a>
<ul class="sectlevel4">
<li><a href="#webflux-ann-initbinder-model-design">Model Design</a></li>
</ul>
</li>
<li><a href="#webflux-ann-controller-exceptions">1.4.6. Exceptions</a>
<ul class="sectlevel4">
<li><a href="#webflux-ann-exceptionhandler-args">Method Arguments</a></li>
<li><a href="#webflux-ann-exceptionhandler-return-values">Return Values</a></li>
</ul>
</li>
<li><a href="#webflux-ann-controller-advice">1.4.7. Controller Advice</a></li>
</ul>
</li>
<li><a href="#webflux-fn">1.5. Functional Endpoints</a>
<ul class="sectlevel3">
<li><a href="#webflux-fn-overview">1.5.1. Overview</a></li>
<li><a href="#webflux-fn-handler-functions">1.5.2. HandlerFunction</a>
<ul class="sectlevel4">
<li><a href="#webflux-fn-request">ServerRequest</a></li>
<li><a href="#webflux-fn-response">ServerResponse</a></li>
<li><a href="#webflux-fn-handler-classes">Handler Classes</a></li>
<li><a href="#webflux-fn-handler-validation">Validation</a></li>
</ul>
</li>
<li><a href="#webflux-fn-router-functions">1.5.3. <code>RouterFunction</code></a>
<ul class="sectlevel4">
<li><a href="#webflux-fn-predicates">Predicates</a></li>
<li><a href="#webflux-fn-routes">Routes</a></li>
<li><a href="#nested-routes">Nested Routes</a></li>
</ul>
</li>
<li><a href="#webflux-fn-running">1.5.4. Running a Server</a></li>
<li><a href="#webflux-fn-handler-filter-function">1.5.5. Filtering Handler Functions</a></li>
</ul>
</li>
<li><a href="#webflux-uri-building">1.6. URI Links</a>
<ul class="sectlevel3">
<li><a href="#webflux.web-uricomponents">1.6.1. UriComponents</a></li>
<li><a href="#webflux.web-uribuilder">1.6.2. UriBuilder</a></li>
<li><a href="#webflux.web-uri-encoding">1.6.3. URI Encoding</a></li>
</ul>
</li>
<li><a href="#webflux-cors">1.7. CORS</a>
<ul class="sectlevel3">
<li><a href="#webflux-cors-intro">1.7.1. Introduction</a></li>
<li><a href="#webflux-cors-processing">1.7.2. Processing</a></li>
<li><a href="#webflux-cors-controller">1.7.3. <code>@CrossOrigin</code></a></li>
<li><a href="#webflux-cors-global">1.7.4. Global Configuration</a></li>
<li><a href="#webflux-cors-webfilter">1.7.5. CORS <code>WebFilter</code></a></li>
</ul>
</li>
<li><a href="#webflux-ann-rest-exceptions">1.8. Error Responses</a>
<ul class="sectlevel3">
<li><a href="#webflux-ann-rest-exceptions-render">1.8.1. Render</a></li>
<li><a href="#webflux-ann-rest-exceptions-non-standard">1.8.2. Non-Standard Fields</a></li>
<li><a href="#webflux-ann-rest-exceptions-i18n">1.8.3. Internationalization</a></li>
<li><a href="#webflux-ann-rest-exceptions-client">1.8.4. Client Handling</a></li>
</ul>
</li>
<li><a href="#webflux-web-security">1.9. Web Security</a></li>
<li><a href="#webflux-caching">1.10. HTTP Caching</a>
<ul class="sectlevel3">
<li><a href="#webflux-caching-cachecontrol">1.10.1. <code>CacheControl</code></a></li>
<li><a href="#webflux-caching-etag-lastmodified">1.10.2. Controllers</a></li>
<li><a href="#webflux-caching-static-resources">1.10.3. Static Resources</a></li>
</ul>
</li>
<li><a href="#webflux-view">1.11. View Technologies</a>
<ul class="sectlevel3">
<li><a href="#webflux-view-thymeleaf">1.11.1. Thymeleaf</a></li>
<li><a href="#webflux-view-freemarker">1.11.2. FreeMarker</a>
<ul class="sectlevel4">
<li><a href="#webflux-view-freemarker-contextconfig">View Configuration</a></li>
<li><a href="#webflux-views-freemarker">FreeMarker Configuration</a></li>
<li><a href="#webflux-view-freemarker-forms">Form Handling</a></li>
</ul>
</li>
<li><a href="#webflux-view-script">1.11.3. Script Views</a>
<ul class="sectlevel4">
<li><a href="#webflux-view-script-dependencies">Requirements</a></li>
<li><a href="#webflux-view-script-integrate">Script Templates</a></li>
</ul>
</li>
<li><a href="#webflux-view-httpmessagewriter">1.11.4. JSON and XML</a></li>
</ul>
</li>
<li><a href="#webflux-config">1.12. WebFlux Config</a>
<ul class="sectlevel3">
<li><a href="#webflux-config-enable">1.12.1. Enabling WebFlux Config</a></li>
<li><a href="#webflux-config-customize">1.12.2. WebFlux config API</a></li>
<li><a href="#webflux-config-conversion">1.12.3. Conversion, formatting</a></li>
<li><a href="#webflux-config-validation">1.12.4. Validation</a></li>
<li><a href="#webflux-config-content-negotiation">1.12.5. Content Type Resolvers</a></li>
<li><a href="#webflux-config-message-codecs">1.12.6. HTTP message codecs</a></li>
<li><a href="#webflux-config-view-resolvers">1.12.7. View Resolvers</a></li>
<li><a href="#webflux-config-static-resources">1.12.8. Static Resources</a></li>
<li><a href="#webflux-config-path-matching">1.12.9. Path Matching</a></li>
<li><a href="#webflux-config-websocket-service">1.12.10. WebSocketService</a></li>
<li><a href="#webflux-config-advanced-java">1.12.11. Advanced Configuration Mode</a></li>
</ul>
</li>
<li><a href="#webflux-http2">1.13. HTTP/2</a></li>
</ul>
</li>
<li><a href="#webflux-client">2. WebClient</a>
<ul class="sectlevel2">
<li><a href="#webflux-client-builder">2.1. Configuration</a>
<ul class="sectlevel3">
<li><a href="#webflux-client-builder-maxinmemorysize">2.1.1. MaxInMemorySize</a></li>
<li><a href="#webflux-client-builder-reactor">2.1.2. Reactor Netty</a>
<ul class="sectlevel4">
<li><a href="#webflux-client-builder-reactor-resources">Resources</a></li>
<li><a href="#webflux-client-builder-reactor-timeout">Timeouts</a></li>
</ul>
</li>
<li><a href="#webflux-client-builder-jdk-httpclient">2.1.3. JDK HttpClient</a></li>
<li><a href="#webflux-client-builder-jetty">2.1.4. Jetty</a></li>
<li><a href="#webflux-client-builder-http-components">2.1.5. HttpComponents</a></li>
</ul>
</li>
<li><a href="#webflux-client-retrieve">2.2. <code>retrieve()</code></a></li>
<li><a href="#webflux-client-exchange">2.3. Exchange</a></li>
<li><a href="#webflux-client-body">2.4. Request Body</a>
<ul class="sectlevel3">
<li><a href="#webflux-client-body-form">2.4.1. Form Data</a></li>
<li><a href="#webflux-client-body-multipart">2.4.2. Multipart Data</a>
<ul class="sectlevel4">
<li><a href="#partevent-2"><code>PartEvent</code></a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#webflux-client-filter">2.5. Filters</a></li>
<li><a href="#webflux-client-attributes">2.6. Attributes</a></li>
<li><a href="#webflux-client-context">2.7. Context</a></li>
<li><a href="#webflux-client-synchronous">2.8. Synchronous Use</a></li>
<li><a href="#webflux-client-testing">2.9. Testing</a></li>
</ul>
</li>
<li><a href="#webflux-http-interface-client">3. HTTP Interface Client</a></li>
<li><a href="#webflux-websocket">4. WebSockets</a>
<ul class="sectlevel2">
<li><a href="#webflux.websocket-intro">4.1. Introduction to WebSocket</a>
<ul class="sectlevel3">
<li><a href="#webflux.websocket-intro-architecture">4.1.1. HTTP Versus WebSocket</a></li>
<li><a href="#webflux.websocket-intro-when-to-use">4.1.2. When to Use WebSockets</a></li>
</ul>
</li>
<li><a href="#webflux-websocket-server">4.2. WebSocket API</a>
<ul class="sectlevel3">
<li><a href="#webflux-websocket-server-handler">4.2.1. Server</a></li>
<li><a href="#webflux-websockethandler">4.2.2. <code>WebSocketHandler</code></a></li>
<li><a href="#webflux-websocket-databuffer">4.2.3. <code>DataBuffer</code></a></li>
<li><a href="#webflux-websocket-server-handshake">4.2.4. Handshake</a></li>
<li><a href="#webflux-websocket-server-config">4.2.5. Server Configuration</a></li>
<li><a href="#webflux-websocket-server-cors">4.2.6. CORS</a></li>
<li><a href="#webflux-websocket-client">4.2.7. Client</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#webflux-test">5. Testing</a></li>
<li><a href="#rsocket">6. RSocket</a>
<ul class="sectlevel2">
<li><a href="#rsocket-overview">6.1. Overview</a>
<ul class="sectlevel3">
<li><a href="#rsocket-protocol">6.1.1. The Protocol</a></li>
<li><a href="#rsocket-java">6.1.2. Java Implementation</a></li>
<li><a href="#rsocket-spring">6.1.3. Spring Support</a></li>
</ul>
</li>
<li><a href="#rsocket-requester">6.2. RSocketRequester</a>
<ul class="sectlevel3">
<li><a href="#rsocket-requester-client">6.2.1. Client Requester</a>
<ul class="sectlevel4">
<li><a href="#rsocket-requester-client-setup">Connection Setup</a></li>
<li><a href="#rsocket-requester-client-strategies">Strategies</a></li>
<li><a href="#rsocket-requester-client-responder">Client Responders</a></li>
<li><a href="#rsocket-requester-client-advanced">Advanced</a></li>
</ul>
</li>
<li><a href="#rsocket-requester-server">6.2.2. Server Requester</a></li>
<li><a href="#rsocket-requester-requests">6.2.3. Requests</a></li>
</ul>
</li>
<li><a href="#rsocket-annot-responders">6.3. Annotated Responders</a>
<ul class="sectlevel3">
<li><a href="#rsocket-annot-responders-server">6.3.1. Server Responders</a></li>
<li><a href="#rsocket-annot-responders-client">6.3.2. Client Responders</a></li>
<li><a href="#rsocket-annot-messagemapping">6.3.3. @MessageMapping</a></li>
<li><a href="#rsocket-annot-connectmapping">6.3.4. @ConnectMapping</a></li>
</ul>
</li>
<li><a href="#rsocket-metadata-extractor">6.4. MetadataExtractor</a></li>
<li><a href="#rsocket-interface">6.5. RSocket Interface</a>
<ul class="sectlevel3">
<li><a href="#rsocket-interface-method-parameters">6.5.1. Method Parameters</a></li>
<li><a href="#rsocket-interface-return-values">6.5.2. Return Values</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#webflux-reactive-libraries">7. Reactive Libraries</a></li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This part of the documentation covers support for reactive-stack web applications built
on a <a href="https://www.reactive-streams.org/">Reactive Streams</a> API to run on non-blocking
servers, such as Netty, Undertow, and Servlet containers. Individual chapters cover
the <a href="#webflux">Spring WebFlux</a> framework,
the reactive <a href="#webflux-client"><code>WebClient</code></a>, support for <a href="#webflux-test">testing</a>,
and <a href="#webflux-reactive-libraries">reactive libraries</a>. For Servlet-stack web applications,
see <a href="web.html#spring-web">Web on Servlet Stack</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="webflux"><a class="anchor" href="#webflux"></a>1. Spring WebFlux</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The original web framework included in the Spring Framework, Spring Web MVC, was
purpose-built for the Servlet API and Servlet containers. The reactive-stack web framework,
Spring WebFlux, was added later in version 5.0. It is fully non-blocking, supports
<a href="https://www.reactive-streams.org/">Reactive Streams</a> back pressure, and runs on such servers as
Netty, Undertow, and Servlet containers.</p>
</div>
<div class="paragraph">
<p>Both web frameworks mirror the names of their source modules
(<a href="https://github.com/spring-projects/spring-framework/tree/main/spring-webmvc">spring-webmvc</a> and
<a href="https://github.com/spring-projects/spring-framework/tree/main/spring-webflux">spring-webflux</a>) and co-exist side by side in the
Spring Framework. Each module is optional. Applications can use one or the other module or,
in some cases, both — for example, Spring MVC controllers with the reactive <code>WebClient</code>.</p>
</div>
<div class="sect2">
<h3 id="webflux-new-framework"><a class="anchor" href="#webflux-new-framework"></a>1.1. Overview</h3>
<div class="paragraph">
<p>Why was Spring WebFlux created?</p>
</div>
<div class="paragraph">
<p>Part of the answer is the need for a non-blocking web stack to handle concurrency with a
small number of threads and scale with fewer hardware resources. Servlet non-blocking I/O
leads away from the rest of the Servlet API, where contracts are synchronous
(<code>Filter</code>, <code>Servlet</code>) or blocking (<code>getParameter</code>, <code>getPart</code>). This was the motivation
for a new common API to serve as a foundation across any non-blocking runtime. That is
important because of servers (such as Netty) that are well-established in the async,
non-blocking space.</p>
</div>
<div class="paragraph">
<p>The other part of the answer is functional programming. Much as the addition of annotations
in Java 5 created opportunities (such as annotated REST controllers or unit tests), the
addition of lambda expressions in Java 8 created opportunities for functional APIs in Java.
This is a boon for non-blocking applications and continuation-style APIs (as popularized
by <code>CompletableFuture</code> and <a href="https://reactivex.io/">ReactiveX</a>) that allow declarative
composition of asynchronous logic. At the programming-model level, Java 8 enabled Spring
WebFlux to offer functional web endpoints alongside annotated controllers.</p>
</div>
<div class="sect3">
<h4 id="webflux-why-reactive"><a class="anchor" href="#webflux-why-reactive"></a>1.1.1. Define “Reactive”</h4>
<div class="paragraph">
<p>We touched on “non-blocking” and “functional” but what does reactive mean?</p>
</div>
<div class="paragraph">
<p>The term, “reactive,” refers to programming models that are built around reacting to change — network components reacting to I/O events, UI controllers reacting to mouse events, and others.
In that sense, non-blocking is reactive, because, instead of being blocked, we are now in the mode
of reacting to notifications as operations complete or data becomes available.</p>
</div>
<div class="paragraph">
<p>There is also another important mechanism that we on the Spring team associate with “reactive”
and that is non-blocking back pressure. In synchronous, imperative code, blocking calls
serve as a natural form of back pressure that forces the caller to wait. In non-blocking
code, it becomes important to control the rate of events so that a fast producer does not
overwhelm its destination.</p>
</div>
<div class="paragraph">
<p>Reactive Streams is a
<a href="https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md#specification">small spec</a>
(also <a href="https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html">adopted</a> in Java 9)
that defines the interaction between asynchronous components with back pressure.
For example a data repository (acting as
<a href="https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/org/reactivestreams/Publisher.html">Publisher</a>)
can produce data that an HTTP server (acting as
<a href="https://www.reactive-streams.org/reactive-streams-1.0.1-javadoc/org/reactivestreams/Subscriber.html">Subscriber</a>)
can then write to the response. The main purpose of Reactive Streams is to let the
subscriber control how quickly or how slowly the publisher produces data.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<strong>Common question: what if a publisher cannot slow down?</strong><br>
The purpose of Reactive Streams is only to establish the mechanism and a boundary.
If a publisher cannot slow down, it has to decide whether to buffer, drop, or fail.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="webflux-reactive-api"><a class="anchor" href="#webflux-reactive-api"></a>1.1.2. Reactive API</h4>
<div class="paragraph">
<p>Reactive Streams plays an important role for interoperability. It is of interest to libraries
and infrastructure components but less useful as an application API, because it is too
low-level. Applications need a higher-level and richer, functional API to
compose async logic — similar to the Java 8 <code>Stream</code> API but not only for collections.
This is the role that reactive libraries play.</p>
</div>
<div class="paragraph">
<p><a href="https://github.com/reactor/reactor">Reactor</a> is the reactive library of choice for
Spring WebFlux. It provides the
<a href="https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html"><code>Mono</code></a> and
<a href="https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html"><code>Flux</code></a> API types
to work on data sequences of 0..1 (<code>Mono</code>) and 0..N (<code>Flux</code>) through a rich set of operators aligned with the
ReactiveX <a href="https://reactivex.io/documentation/operators.html">vocabulary of operators</a>.
Reactor is a Reactive Streams library and, therefore, all of its operators support non-blocking back pressure.
Reactor has a strong focus on server-side Java. It is developed in close collaboration
with Spring.</p>
</div>
<div class="paragraph">
<p>WebFlux requires Reactor as a core dependency but it is interoperable with other reactive
libraries via Reactive Streams. As a general rule, a WebFlux API accepts a plain <code>Publisher</code>
as input, adapts it to a Reactor type internally, uses that, and returns either a
<code>Flux</code> or a <code>Mono</code> as output. So, you can pass any <code>Publisher</code> as input and you can apply
operations on the output, but you need to adapt the output for use with another reactive library.
Whenever feasible (for example, annotated controllers), WebFlux adapts transparently to the use
of RxJava or another reactive library. See <a href="#webflux-reactive-libraries">Reactive Libraries</a> for more details.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
In addition to Reactive APIs, WebFlux can also be used with
<a href="languages.html#coroutines">Coroutines</a> APIs in Kotlin which provides a more imperative style of programming.
The following Kotlin code samples will be provided with Coroutines APIs.
</td>
</tr>
</table>
</div>
</div>
<div class="sect3">
<h4 id="webflux-programming-models"><a class="anchor" href="#webflux-programming-models"></a>1.1.3. Programming Models</h4>
<div class="paragraph">
<p>The <code>spring-web</code> module contains the reactive foundation that underlies Spring WebFlux,
including HTTP abstractions, Reactive Streams <a href="#webflux-httphandler">adapters</a> for supported
servers, <a href="#webflux-codecs">codecs</a>, and a core <a href="#webflux-web-handler-api"><code>WebHandler</code> API</a> comparable to
the Servlet API but with non-blocking contracts.</p>
</div>
<div class="paragraph">
<p>On that foundation, Spring WebFlux provides a choice of two programming models:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="#webflux-controller">Annotated Controllers</a>: Consistent with Spring MVC and based on the same annotations
from the <code>spring-web</code> module. Both Spring MVC and WebFlux controllers support reactive
(Reactor and RxJava) return types, and, as a result, it is not easy to tell them apart. One notable
difference is that WebFlux also supports reactive <code>@RequestBody</code> arguments.</p>
</li>
<li>
<p><a href="#webflux-fn">Functional Endpoints</a>: Lambda-based, lightweight, and functional programming model. You can think of
this as a small library or a set of utilities that an application can use to route and
handle requests. The big difference with annotated controllers is that the application
is in charge of request handling from start to finish versus declaring intent through
annotations and being called back.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="webflux-framework-choice"><a class="anchor" href="#webflux-framework-choice"></a>1.1.4. Applicability</h4>
<div class="paragraph">
<p>Spring MVC or WebFlux?</p>
</div>
<div class="paragraph">
<p>A natural question to ask but one that sets up an unsound dichotomy. Actually, both
work together to expand the range of available options. The two are designed for
continuity and consistency with each other, they are available side by side, and feedback
from each side benefits both sides. The following diagram shows how the two relate, what they
have in common, and what each supports uniquely:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="images/spring-mvc-and-webflux-venn.png" alt="spring mvc and webflux venn">
</div>
</div>
<div class="paragraph">
<p>We suggest that you consider the following specific points:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If you have a Spring MVC application that works fine, there is no need to change.
Imperative programming is the easiest way to write, understand, and debug code.
You have maximum choice of libraries, since, historically, most are blocking.</p>
</li>
<li>
<p>If you are already shopping for a non-blocking web stack, Spring WebFlux offers the same
execution model benefits as others in this space and also provides a choice of servers
(Netty, Tomcat, Jetty, Undertow, and Servlet containers), a choice of programming models
(annotated controllers and functional web endpoints), and a choice of reactive libraries
(Reactor, RxJava, or other).</p>
</li>
<li>
<p>If you are interested in a lightweight, functional web framework for use with Java 8 lambdas
or Kotlin, you can use the Spring WebFlux functional web endpoints. That can also be a good choice
for smaller applications or microservices with less complex requirements that can benefit
from greater transparency and control.</p>
</li>
<li>
<p>In a microservice architecture, you can have a mix of applications with either Spring MVC
or Spring WebFlux controllers or with Spring WebFlux functional endpoints. Having support
for the same annotation-based programming model in both frameworks makes it easier to
re-use knowledge while also selecting the right tool for the right job.</p>
</li>
<li>
<p>A simple way to evaluate an application is to check its dependencies. If you have blocking
persistence APIs (JPA, JDBC) or networking APIs to use, Spring MVC is the best choice
for common architectures at least. It is technically feasible with both Reactor and
RxJava to perform blocking calls on a separate thread but you would not be making the
most of a non-blocking web stack.</p>
</li>
<li>
<p>If you have a Spring MVC application with calls to remote services, try the reactive <code>WebClient</code>.
You can return reactive types (Reactor, RxJava, <a href="#webflux-reactive-libraries">or other</a>)
directly from Spring MVC controller methods. The greater the latency per call or the
interdependency among calls, the more dramatic the benefits. Spring MVC controllers
can call other reactive components too.</p>
</li>
<li>
<p>If you have a large team, keep in mind the steep learning curve in the shift to non-blocking,
functional, and declarative programming. A practical way to start without a full switch
is to use the reactive <code>WebClient</code>. Beyond that, start small and measure the benefits.
We expect that, for a wide range of applications, the shift is unnecessary. If you are
unsure what benefits to look for, start by learning about how non-blocking I/O works
(for example, concurrency on single-threaded Node.js) and its effects.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="webflux-server-choice"><a class="anchor" href="#webflux-server-choice"></a>1.1.5. Servers</h4>
<div class="paragraph">
<p>Spring WebFlux is supported on Tomcat, Jetty, Servlet containers, as well as on
non-Servlet runtimes such as Netty and Undertow. All servers are adapted to a low-level,
<a href="#webflux-httphandler">common API</a> so that higher-level
<a href="#webflux-programming-models">programming models</a> can be supported across servers.</p>
</div>
<div class="paragraph">
<p>Spring WebFlux does not have built-in support to start or stop a server. However, it is
easy to <a href="#webflux-web-handler-api">assemble</a> an application from Spring configuration and
<a href="#webflux-config">WebFlux infrastructure</a> and <a href="#webflux-httphandler">run it</a> with a few
lines of code.</p>
</div>
<div class="paragraph">
<p>Spring Boot has a WebFlux starter that automates these steps. By default, the starter uses
Netty, but it is easy to switch to Tomcat, Jetty, or Undertow by changing your
Maven or Gradle dependencies. Spring Boot defaults to Netty, because it is more widely
used in the asynchronous, non-blocking space and lets a client and a server share resources.</p>
</div>
<div class="paragraph">
<p>Tomcat and Jetty can be used with both Spring MVC and WebFlux. Keep in mind, however, that
the way they are used is very different. Spring MVC relies on Servlet blocking I/O and
lets applications use the Servlet API directly if they need to. Spring WebFlux
relies on Servlet non-blocking I/O and uses the Servlet API behind a low-level
adapter. It is not exposed for direct use.</p>
</div>
<div class="paragraph">
<p>For Undertow, Spring WebFlux uses Undertow APIs directly without the Servlet API.</p>
</div>
</div>
<div class="sect3">
<h4 id="webflux-performance"><a class="anchor" href="#webflux-performance"></a>1.1.6. Performance</h4>
<div class="paragraph">
<p>Performance has many characteristics and meanings. Reactive and non-blocking generally
do not make applications run faster. They can, in some cases, (for example, if using the
<code>WebClient</code> to run remote calls in parallel). On the whole, it requires more work to do
things the non-blocking way and that can slightly increase the required processing time.</p>
</div>
<div class="paragraph">
<p>The key expected benefit of reactive and non-blocking is the ability to scale with a small,
fixed number of threads and less memory. That makes applications more resilient under load,
because they scale in a more predictable way. In order to observe those benefits, however, you
need to have some latency (including a mix of slow and unpredictable network I/O).
That is where the reactive stack begins to show its strengths, and the differences can be
dramatic.</p>
</div>
</div>
<div class="sect3">
<h4 id="webflux-concurrency-model"><a class="anchor" href="#webflux-concurrency-model"></a>1.1.7. Concurrency Model</h4>
<div class="paragraph">
<p>Both Spring MVC and Spring WebFlux support annotated controllers, but there is a key
difference in the concurrency model and the default assumptions for blocking and threads.</p>
</div>
<div class="paragraph">
<p>In Spring MVC (and servlet applications in general), it is assumed that applications can
block the current thread, (for example, for remote calls). For this reason, servlet containers
use a large thread pool to absorb potential blocking during request handling.</p>
</div>
<div class="paragraph">
<p>In Spring WebFlux (and non-blocking servers in general), it is assumed that applications
do not block. Therefore, non-blocking servers use a small, fixed-size thread pool
(event loop workers) to handle requests.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
<td class="content">
“To scale” and “small number of threads” may sound contradictory but to never block the
current thread (and rely on callbacks instead) means that you do not need extra threads, as
there are no blocking calls to absorb.
</td>
</tr>
</table>
</div>
<div class="sect4">
<h5 id="invoking-a-blocking-api"><a class="anchor" href="#invoking-a-blocking-api"></a>Invoking a Blocking API</h5>
<div class="paragraph">
<p>What if you do need to use a blocking library? Both Reactor and RxJava provide the
<code>publishOn</code> operator to continue processing on a different thread. That means there is an
easy escape hatch. Keep in mind, however, that blocking APIs are not a good fit for
this concurrency model.</p>
</div>
</div>
<div class="sect4">
<h5 id="mutable-state"><a class="anchor" href="#mutable-state"></a>Mutable State</h5>
<div class="paragraph">
<p>In Reactor and RxJava, you declare logic through operators. At runtime, a reactive
pipeline is formed where data is processed sequentially, in distinct stages. A key benefit
of this is that it frees applications from having to protect mutable state because
application code within that pipeline is never invoked concurrently.</p>
</div>
</div>
<div class="sect4">
<h5 id="threading-model"><a class="anchor" href="#threading-model"></a>Threading Model</h5>
<div class="paragraph">
<p>What threads should you expect to see on a server running with Spring WebFlux?</p>
</div>
<div class="ulist">
<ul>
<li>
<p>On a “vanilla” Spring WebFlux server (for example, no data access nor other optional
dependencies), you can expect one thread for the server and several others for request
processing (typically as many as the number of CPU cores). Servlet containers, however,
may start with more threads (for example, 10 on Tomcat), in support of both servlet (blocking) I/O
and servlet 3.1 (non-blocking) I/O usage.</p>
</li>
<li>
<p>The reactive <code>WebClient</code> operates in event loop style. So you can see a small, fixed
number of processing threads related to that (for example, <code>reactor-http-nio-</code> with the Reactor
Netty connector). However, if Reactor Netty is used for both client and server, the two
share event loop resources by default.</p>
</li>
<li>
<p>Reactor and RxJava provide thread pool abstractions, called schedulers, to use with the
<code>publishOn</code> operator that is used to switch processing to a different thread pool.
The schedulers have names that suggest a specific concurrency strategy — for example, “parallel”
(for CPU-bound work with a limited number of threads) or “elastic” (for I/O-bound work with
a large number of threads). If you see such threads, it means some code is using a
specific thread pool <code>Scheduler</code> strategy.</p>
</li>
<li>
<p>Data access libraries and other third party dependencies can also create and use threads
of their own.</p>
</li>
</ul>
</div>
</div>
<div class="sect4">
<h5 id="configuring"><a class="anchor" href="#configuring"></a>Configuring</h5>
<div class="paragraph">
<p>The Spring Framework does not provide support for starting and stopping
<a href="#webflux-server-choice">servers</a>. To configure the threading model for a server,
you need to use server-specific configuration APIs, or, if you use Spring Boot,
check the Spring Boot configuration options for each server. You can
<a href="#webflux-client-builder">configure</a> the <code>WebClient</code> directly.
For all other libraries, see their respective documentation.</p>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-reactive-spring-web"><a class="anchor" href="#webflux-reactive-spring-web"></a>1.2. Reactive Core</h3>
<div class="paragraph">
<p>The <code>spring-web</code> module contains the following foundational support for reactive web
applications:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>For server request processing there are two levels of support.</p>
<div class="ulist">
<ul>
<li>
<p><a href="#webflux-httphandler">HttpHandler</a>: Basic contract for HTTP request handling with
non-blocking I/O and Reactive Streams back pressure, along with adapters for Reactor Netty,
Undertow, Tomcat, Jetty, and any Servlet container.</p>
</li>
<li>
<p><a href="#webflux-web-handler-api"><code>WebHandler</code> API</a>: Slightly higher level, general-purpose web API for
request handling, on top of which concrete programming models such as annotated
controllers and functional endpoints are built.</p>
</li>
</ul>
</div>
</li>
<li>
<p>For the client side, there is a basic <code>ClientHttpConnector</code> contract to perform HTTP
requests with non-blocking I/O and Reactive Streams back pressure, along with adapters for
<a href="https://github.com/reactor/reactor-netty">Reactor Netty</a>, reactive
<a href="https://github.com/jetty-project/jetty-reactive-httpclient">Jetty HttpClient</a>
and <a href="https://hc.apache.org/">Apache HttpComponents</a>.
The higher level <a href="#webflux-client">WebClient</a> used in applications
builds on this basic contract.</p>
</li>
<li>
<p>For client and server, <a href="#webflux-codecs">codecs</a> for serialization and
deserialization of HTTP request and response content.</p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="webflux-httphandler"><a class="anchor" href="#webflux-httphandler"></a>1.2.1. <code>HttpHandler</code></h4>
<div class="paragraph">
<p><a href="https://docs.spring.io/spring-framework/docs/6.0.8/javadoc-api/org/springframework/http/server/reactive/HttpHandler.html">HttpHandler</a>
is a simple contract with a single method to handle a request and a response. It is
intentionally minimal, and its main and only purpose is to be a minimal abstraction
over different HTTP server APIs.</p>
</div>
<div class="paragraph">
<p>The following table describes the supported server APIs:</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 20%;">
<col style="width: 40%;">
<col style="width: 40%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Server name</th>
<th class="tableblock halign-left valign-top">Server API used</th>
<th class="tableblock halign-left valign-top">Reactive Streams support</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Netty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Netty API</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/reactor/reactor-netty">Reactor Netty</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Undertow</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Undertow API</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">spring-web: Undertow to Reactive Streams bridge</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Tomcat</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Servlet non-blocking I/O; Tomcat API to read and write ByteBuffers vs byte[]</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">spring-web: Servlet non-blocking I/O to Reactive Streams bridge</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Jetty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Servlet non-blocking I/O; Jetty API to write ByteBuffers vs byte[]</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">spring-web: Servlet non-blocking I/O to Reactive Streams bridge</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Servlet container</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Servlet non-blocking I/O</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">spring-web: Servlet non-blocking I/O to Reactive Streams bridge</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The following table describes server dependencies (also see
<a href="https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-the-Spring-Framework">supported versions</a>):</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Server name</th>
<th class="tableblock halign-left valign-top">Group id</th>
<th class="tableblock halign-left valign-top">Artifact name</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Reactor Netty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">io.projectreactor.netty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">reactor-netty</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Undertow</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">io.undertow</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">undertow-core</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Tomcat</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">org.apache.tomcat.embed</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">tomcat-embed-core</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Jetty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">org.eclipse.jetty</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">jetty-server, jetty-servlet</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>The code snippets below show using the <code>HttpHandler</code> adapters with each server API:</p>
</div>
<div class="paragraph">
<p><strong>Reactor Netty</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">HttpHandler handler = ...
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create().host(host).port(port).handle(adapter).bindNow();
</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val handler: HttpHandler = ...
val adapter = ReactorHttpHandlerAdapter(handler)
HttpServer.create().host(host).port(port).handle(adapter).bindNow()
</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Undertow</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">HttpHandler handler = ...
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();
</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val handler: HttpHandler = ...
val adapter = UndertowHttpHandlerAdapter(handler)
val server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build()
server.start()
</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Tomcat</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">HttpHandler handler = ...
Servlet servlet = new TomcatHttpHandlerAdapter(handler);
Tomcat server = new Tomcat();
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootContext = server.addContext("", base.getAbsolutePath());
Tomcat.addServlet(rootContext, "main", servlet);
rootContext.addServletMappingDecoded("/", "main");
server.setHost(host);
server.setPort(port);
server.start();
</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val handler: HttpHandler = ...
val servlet = TomcatHttpHandlerAdapter(handler)
val server = Tomcat()
val base = File(System.getProperty("java.io.tmpdir"))
val rootContext = server.addContext("", base.absolutePath)
Tomcat.addServlet(rootContext, "main", servlet)
rootContext.addServletMappingDecoded("/", "main")
server.host = host
server.setPort(port)
server.start()
</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Jetty</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlight"><code class="language-java" data-lang="java">HttpHandler handler = ...
Servlet servlet = new JettyHttpHandlerAdapter(handler);
Server server = new Server();
ServletContextHandler contextHandler = new ServletContextHandler(server, "");
contextHandler.addServlet(new ServletHolder(servlet), "/");
contextHandler.start();
ServerConnector connector = new ServerConnector(server);
connector.setHost(host);
connector.setPort(port);
server.addConnector(connector);
server.start();
</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlight"><code class="language-kotlin" data-lang="kotlin">val handler: HttpHandler = ...
val servlet = JettyHttpHandlerAdapter(handler)