SlideShare a Scribd company logo
Confidential │ ©2020 VMware, Inc.
Introduction to
WebMvc.fn
Functional Servlet Endpoints
Arjen Poutsma (@poutsma)
Sr. Staff Engineer at VMware
3rd September 2020
Confidential │ ©2020 VMware, Inc.
Agenda
2
Handler Functions
Router Functions
Filter Functions
Final Comparison
Confidential │ ©2020 VMware, Inc. 3
WebMvc.fn was introduced
in Spring 5.2 and is fully
compatible with Spring Boot
Confidential │ ©2020 VMware, Inc.
Handler Functions
Map from ServerRequest to ServerResponse
4
Confidential │ ©2020 VMware, Inc. 5
Map from ServerRequest to ServerResponse
Handler Functions
@Controller
class PersonController {
PersonRepository repository;
ResponseEntity<Person> getPerson(@PathVariable String id) {
Person person = repository.findById(id);
return ResponseEntity.ok()
.contentType(APPLICATION_JSON)
.body(person);
}
ResponseEntity<List<Person>> getPeople() {
List<Person> people = repository.findAll();
return ResponseEntity.ok()
.contentType(APPLICATION_JSON)
.body(people);
}
}
Web MVC
Confidential │ ©2020 VMware, Inc. 5
Map from ServerRequest to ServerResponse
Handler Functions
@Controller
class PersonHandler {
PersonRepository repository;
ServerResponse getPerson(ServerRequest request) {
String id = request.pathVariable("id");
Person person = repository.findById(id);
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(person);
}
ServerResponse getPeople(ServerRequest request) {
List<Person> people = repository.findAll();
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(people);
}
}
WebMvc.fn
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
6
Handler Function Comparison
@Controller
class PersonController {
PersonRepository repository;
ResponseEntity<Person> getPerson(@PathVariable String id) {
Person person = repository.findById(id);
return ResponseEntity.ok()
.contentType(APPLICATION_JSON)
.body(person);
}
ResponseEntity<List<Person>> getPeople() {
List<Person> people = repository.findAll();
return ResponseEntity.ok()
.contentType(APPLICATION_JSON)
.body(people);
}
}
@Controller
class PersonHandler {
PersonRepository repository;
ServerResponse getPerson(ServerRequest request) {
String id = request.pathVariable("id");
Person person = repository.findById(id);
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(person);
}
ServerResponse getPeople(ServerRequest request) {
List<Person> people = repository.findAll();
return ServerResponse.ok()
.contentType(APPLICATION_JSON)
.body(people);
}
}
Confidential │ ©2020 VMware, Inc. 7
Handler Functions map from
ServerRequest to ServerResponse
• both are immutable
• create response with builder
Confidential │ ©2020 VMware, Inc.
Router Functions
Map from ServerRequest to HandlerFunction
8
Confidential │ ©2020 VMware, Inc. 9
Map from ServerRequest to HandlerFunction
Router Functions
@Controller
@RequestMapping("/people")
class PersonController {
PersonRepository repository;
@RequestMapping(value = "/{id}", method = GET)
ResponseEntity<Person> getPerson(@PathVariable String id) {
...
}
@RequestMapping(method = GET)
ResponseEntity<List<Person>> getPeople() {
...
}
}
Web MVC
Confidential │ ©2020 VMware, Inc. 9
Map from ServerRequest to HandlerFunction
Router Functions
@Controller
class PersonHandler {
PersonRepository repository;
ServerResponse getPerson(ServerRequest request) {
...
}
ServerResponse getPeople(ServerRequest request) {
...
}
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.GET("/people/{id}", handler::getPerson)
.GET(“/people", handler::getPeople)
.build();
}
}
WebMvc.fn
Confidential │ ©2020 VMware, Inc. 9
Map from ServerRequest to HandlerFunction
Router Functions
@Controller
class PersonHandler {
PersonRepository repository;
ServerResponse getPerson(ServerRequest request) {
...
}
ServerResponse getPeople(ServerRequest request) {
...
}
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.path(“/people", builder -> builder
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople));
.build();
}
}
WebMvc.fn
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
10
Router Function Comparison
@Controller
class PersonHandler {
PersonRepository repository;
ServerResponse getPerson(ServerRequest request) {
...
}
ServerResponse getPeople(ServerRequest request) {
...
}
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.path(“/people", builder -> builder
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople));
.build();
}
}
@Controller
@RequestMapping(“/people")
class PersonController {
PersonRepository repository;
@RequestMapping(value = "/{id}", method = GET)
ResponseEntity<Person> getPerson(@PathVariable String id) {
...
}
@RequestMapping(method = GET)
ResponseEntity<List<Person>> getPeople() {
...
}
}
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
10
Router Function Comparison
@Controller
class PersonHandler {
PersonRepository repository;
ServerResponse getPerson(ServerRequest request) {
...
}
ServerResponse getPeople(ServerRequest request) {
...
}
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.path(“/people", builder -> builder
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople));
.build();
}
}
@Controller
@RequestMapping(“/people")
class PersonController {
PersonRepository repository;
@RequestMapping(value = "/{id}", method = GET)
ResponseEntity<Person> getPerson(@PathVariable String id) {
...
}
@RequestMapping(method = GET)
ResponseEntity<List<Person>> getPeople() {
...
}
}
Confidential │ ©2020 VMware, Inc. 11
Router Functions created using builder
• GET, POST, PUT, etc.
• resources
• nesting
• more powerful abstraction underneath:
RequestPredicate
Confidential │ ©2020 VMware, Inc.
Request Predicates
Evaluate on a ServerRequest
12
Confidential │ ©2020 VMware, Inc. 13
Evaluate on a ServerRequest
Request Predicates
RequestPredicate get = RequestPredicates.method(HttpMethod.GET);
RequestPredicate people = RequestPredicates.path("/people");
RequestPredicate getPeople = get.and(people); // or RequestPredicates.GET("/people")
RequestPredicate acceptJson = RequestPredicates.accept(APPLICATION_JSON);
RequestPredicate extensionJson = RequestPredicates.pathExtension("json");
RequestPredicate paramTypeJson = RequestPredicates.param("type", "json");
RequestPredicate json = acceptJson.or(extensionJson).or(paramTypeJson);
Confidential │ ©2020 VMware, Inc. 14
Evaluate on a ServerRequest
Request Predicates
@Controller
class PersonHandler {
PersonRepository repository;
...
ServerResponse createPerson(ServerRequest request) {
Person person = request.body(Person.class);
repository.savePerson(person);
return ServerResponse.ok()
.build();
}
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.path("/people", b -> b
.GET("/{id}", accept(APPLICATION_JSON), handler::getPerson)
.GET("/", accept(APPLICATION_JSON), handler::getPeople)
.POST("/", contentType(APPLICATION_JSON), handler::createPerson))
.build();
}
}
Confidential │ ©2020 VMware, Inc. 14
Evaluate on a ServerRequest
Request Predicates
@Controller
class PersonHandler {
PersonRepository repository;
...
ServerResponse createPerson(ServerRequest request) {
Person person = request.body(Person.class);
this.repository.savePerson(person);
return ServerResponse.ok()
.build();
}
@Bean
static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) {
return route()
.path(“/people", b -> b
.nest(accept(APPLICATION_JSON), b1 -> b1
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople)
)
.POST("/", contentType(APPLICATION_JSON), handler::createPerson))
.build();
}
}
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
15
Request Predicates Comparison
@Controller
@RequestMapping(“/people”)
class PersonController {
PersonRepository repository;
@RequestMapping(value = "/{id}",
method = GET,
produces = APPLICATION_JSON_VALUE)
ResponseEntity<Person> getPerson(@PathVariable String id) {
...
}
@RequestMapping(method = GET,
produces = APPLICATION_JSON_VALUE)
ResponseEntity<List<Person>> showPeople() {
...
}
@RequestMapping(method = POST,
consumes = APPLICATION_JSON_VALUE)
void createPerson(RequestEntity<Person> person) {
...
}
}
@Controller
class PersonHandler {
PersonRepository repository;
...
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.path(“/people", b -> b
.GET("/{id}", accept(APPLICATION_JSON), handler::getP
.GET("/", accept(APPLICATION_JSON), handler::getPeopl
.POST("/", contentType(APPLICATION_JSON), handler::cr
.build();
}
}
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
15
Request Predicates Comparison
@Controller
@RequestMapping(“/people”)
class PersonController {
PersonRepository repository;
@RequestMapping(value = "/{id}",
method = GET,
produces = APPLICATION_JSON_VALUE)
ResponseEntity<Person> getPerson(@PathVariable String id) {
...
}
@RequestMapping(method = GET,
produces = APPLICATION_JSON_VALUE)
ResponseEntity<List<Person>> showPeople() {
...
}
@RequestMapping(method = POST,
consumes = APPLICATION_JSON_VALUE)
void createPerson(RequestEntity<Person> person) {
...
}
}
@Controller
class PersonHandler {
PersonRepository repository;
...
@Bean
static RouterFunction router(PersonHandler handler) {
return route()
.path(“/people", b -> b
.GET("/{id}", accept(APPLICATION_JSON), handler::getP
.GET("/", accept(APPLICATION_JSON), handler::getPeopl
.POST("/", contentType(APPLICATION_JSON), handler::cr
.build();
}
}
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
16
Request Predicates Comparison
@Controller
class PersonHandler {
PersonRepository repository;
...
@Bean
static RouterFunction<ServerResponse> routerFunction(Person
return route()
.path("/person", b -> b
.nest(accept(APPLICATION_JSON), b1 -> b1
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople)
)
.POST("/", contentType(APPLICATION_JSON), handler::cr
.build();
}
}
?
Confidential │ ©2020 VMware, Inc.
Handler Filter Functions
Maps ServerRequest and HandlerFunction
to ServerResponse
17
Confidential │ ©2020 VMware, Inc. 18
Maps ServerRequest and HandlerFunction to ServerResponse
Handler Filter Functions
@Controller
@RequestMapping("/people")
class PersonController {
PersonRepository repository;
...
@ExceptionHandler(NotFoundException.class)
ResponseEntity notFound() {
return ResponseEntity.notFound().build()
}
}
Web MVC
Confidential │ ©2020 VMware, Inc. 18
Maps ServerRequest and HandlerFunction to ServerResponse
Handler Filter Functions
@Controller
class PersonHandler {
PersonRepository repository;
...
ServerResponse notFound(Throwable throwable, ServerRequest request) {
return ServerResponse.notFound().build();
}
@Bean
static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) {
return route()
.path(“/people", b -> b
.nest(accept(APPLICATION_JSON), b1 -> b1
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople)
)
.POST("/", contentType(APPLICATION_JSON), handler::createPerson))
.onError(NotFoundException.class, handler::notFound)
.build();
}
}
WebMvc.fn
Confidential │ ©2020 VMware, Inc. 18
Maps ServerRequest and HandlerFunction to ServerResponse
Handler Filter Functions
@Controller
class PersonHandler {
PersonRepository repository;
...
ServerResponse notFound(Throwable throwable, ServerRequest request) {
return ServerResponse.notFound().build();
}
@Bean
static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) {
return route()
.path(“/people", b -> b
.nest(accept(APPLICATION_JSON), b1 -> b1
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople)
.onError(NotFoundException.class, handler::notFound)
)
.POST("/", contentType(APPLICATION_JSON), handler::createPerson))
.build();
}
}
WebMvc.fn
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
19
Handler Filter Function Comparison
@Controller
@RequestMapping("/people")
class PersonController {
PersonRepository repository;
...
@ExceptionHandler(NotFoundException.class)
ResponseEntity notFound() {
return ResponseEntity.notFound().build()
}
}
@Controller
class PersonHandler {
PersonRepository repository;
...
ServerResponse notFound(Throwable throwable, ServerRequest request) {
return ServerResponse.notFound().build();
}
@Bean
static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) {
return route()
.path("/person", b -> b
.nest(accept(APPLICATION_JSON), b1 -> b1
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople)
)
.POST("/", contentType(APPLICATION_JSON), handler::createPerson))
.onError(NotFoundException.class, handler::notFound)
.build();
}
}
Confidential │ ©2020 VMware, Inc.
Web MVC WebMvc.fn
19
Handler Filter Function Comparison
@Controller
@RequestMapping("/people")
class PersonController {
PersonRepository repository;
...
@ExceptionHandler(NotFoundException.class)
ResponseEntity notFound() {
return ResponseEntity.notFound().build()
}
}
@Controller
class PersonHandler {
PersonRepository repository;
...
ServerResponse notFound(Throwable throwable, ServerRequest request) {
return ServerResponse.notFound().build();
}
@Bean
static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) {
return route()
.path("/person", b -> b
.nest(accept(APPLICATION_JSON), b1 -> b1
.GET("/{id}", handler::getPerson)
.GET("/", handler::getPeople)
)
.POST("/", contentType(APPLICATION_JSON), handler::createPerson))
.onError(NotFoundException.class, handler::notFound)
.build();
}
}
Confidential │ ©2020 VMware, Inc.
Final Comparison
20
Confidential │ ©2020 VMware, Inc.
• Functions
• Code
• Rigid handler methods
(ServerRequest→ServerResponse)
• Flexible routing
• Annotations
• Meta-data
• Flexible handler methods
(parameters & return type)
• Limited routing
Web MVC WebMvc.fn
21
Request Predicates Comparison
Confidential │ ©2020 VMware, Inc.
Thank You

More Related Content

PPTX
Cesiumマニアックス― Revenge ―
PDF
Re:dash Use Cases at iPROS
PDF
Marp入門
PPTX
【論文LT資料】 Gait Recognition via Disentangled Representation Learning (CVPR2019)
PDF
Data-Centric AIの紹介
PDF
Microsoft Graph APIを活用した社内アプリケーション開発
PDF
pythonでオフィス快適化計画
PDF
gRPC入門
Cesiumマニアックス― Revenge ―
Re:dash Use Cases at iPROS
Marp入門
【論文LT資料】 Gait Recognition via Disentangled Representation Learning (CVPR2019)
Data-Centric AIの紹介
Microsoft Graph APIを活用した社内アプリケーション開発
pythonでオフィス快適化計画
gRPC入門

What's hot (20)

PDF
オンプレML基盤on Kubernetes パネルディスカッション
PPTX
オレオレ言語実装に役立つプル型ASTウォーカーAPI
PDF
Docker道場オンライン#1 Docker基礎概念と用語の理解
PDF
Agile, the Pivotal way
PDF
Linked Open Data(LOD)の基本理念と基盤となる技術
PPTX
Jenkins使ってみた~Windows編~
PDF
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
PDF
グラフデータベースNeo4Jでアセットダウンロードの構成管理と最適化
PDF
Quarkus Technical Deep Dive - Japanese
PDF
20141008物体検出器
PDF
성장을 좋아하는 사람이, 성장하고 싶은 사람에게
PPTX
え!?データがオンプレにあるけどPower BI で BI したいの?
PDF
PostgreSQLレプリケーション(pgcon17j_t4)
PDF
DevOps Overview
 
PDF
PostgreSQLのトラブルシューティング@第5回中国地方DB勉強会
PDF
GitHub入門 手順編
PDF
i-Cart miniを対象としたつくばチャレンジ用ソフトウェアパッケージの開発
PDF
システムのモダナイズ 落ちても良いアプリの作り方
PPTX
Java 17直前!オレ流OpenJDK「の」開発環境(Open Source Conference 2021 Online/Kyoto 発表資料)
PDF
Unified JVM Logging
オンプレML基盤on Kubernetes パネルディスカッション
オレオレ言語実装に役立つプル型ASTウォーカーAPI
Docker道場オンライン#1 Docker基礎概念と用語の理解
Agile, the Pivotal way
Linked Open Data(LOD)の基本理念と基盤となる技術
Jenkins使ってみた~Windows編~
JDK 16 で導入された JEP 396 にご注意!! (JJUG CCC 2021 Spring)
グラフデータベースNeo4Jでアセットダウンロードの構成管理と最適化
Quarkus Technical Deep Dive - Japanese
20141008物体検出器
성장을 좋아하는 사람이, 성장하고 싶은 사람에게
え!?データがオンプレにあるけどPower BI で BI したいの?
PostgreSQLレプリケーション(pgcon17j_t4)
DevOps Overview
 
PostgreSQLのトラブルシューティング@第5回中国地方DB勉強会
GitHub入門 手順編
i-Cart miniを対象としたつくばチャレンジ用ソフトウェアパッケージの開発
システムのモダナイズ 落ちても良いアプリの作り方
Java 17直前!オレ流OpenJDK「の」開発環境(Open Source Conference 2021 Online/Kyoto 発表資料)
Unified JVM Logging
Ad

Similar to Introduction to WebMvc.fn (9)

PDF
Multi Client Development with Spring - Josh Long
PDF
Spring Framework - MVC
PPT
Spring-training-in-bangalore
PDF
Spring MVC to iOS and the REST
PPTX
PDF
REST based web applications with Spring 3
PDF
Spring MVC Annotations
KEY
Multi Client Development with Spring
PDF
RESTful Web Services with Spring MVC
Multi Client Development with Spring - Josh Long
Spring Framework - MVC
Spring-training-in-bangalore
Spring MVC to iOS and the REST
REST based web applications with Spring 3
Spring MVC Annotations
Multi Client Development with Spring
RESTful Web Services with Spring MVC
Ad

More from VMware Tanzu (20)

PDF
Spring into AI presented by Dan Vega 5/14
PDF
What AI Means For Your Product Strategy And What To Do About It
PDF
Make the Right Thing the Obvious Thing at Cardinal Health 2023
PPTX
Enhancing DevEx and Simplifying Operations at Scale
PDF
Spring Update | July 2023
PPTX
Platforms, Platform Engineering, & Platform as a Product
PPTX
Building Cloud Ready Apps
PDF
Spring Boot 3 And Beyond
PDF
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
PDF
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
PDF
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
PPTX
tanzu_developer_connect.pptx
PDF
Tanzu Virtual Developer Connect Workshop - French
PDF
Tanzu Developer Connect Workshop - English
PDF
Virtual Developer Connect Workshop - English
PDF
Tanzu Developer Connect - French
PDF
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
PDF
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
PDF
SpringOne Tour: The Influential Software Engineer
PDF
SpringOne Tour: Domain-Driven Design: Theory vs Practice
Spring into AI presented by Dan Vega 5/14
What AI Means For Your Product Strategy And What To Do About It
Make the Right Thing the Obvious Thing at Cardinal Health 2023
Enhancing DevEx and Simplifying Operations at Scale
Spring Update | July 2023
Platforms, Platform Engineering, & Platform as a Product
Building Cloud Ready Apps
Spring Boot 3 And Beyond
Spring Cloud Gateway - SpringOne Tour 2023 Charles Schwab.pdf
Simplify and Scale Enterprise Apps in the Cloud | Boston 2023
Simplify and Scale Enterprise Apps in the Cloud | Seattle 2023
tanzu_developer_connect.pptx
Tanzu Virtual Developer Connect Workshop - French
Tanzu Developer Connect Workshop - English
Virtual Developer Connect Workshop - English
Tanzu Developer Connect - French
Simplify and Scale Enterprise Apps in the Cloud | Dallas 2023
SpringOne Tour: Deliver 15-Factor Applications on Kubernetes with Spring Boot
SpringOne Tour: The Influential Software Engineer
SpringOne Tour: Domain-Driven Design: Theory vs Practice

Recently uploaded (20)

PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Introduction to Artificial Intelligence
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
System and Network Administration Chapter 2
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PPTX
Transform Your Business with a Software ERP System
PDF
top salesforce developer skills in 2025.pdf
PDF
Nekopoi APK 2025 free lastest update
PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
medical staffing services at VALiNTRY
PPTX
assetexplorer- product-overview - presentation
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
2025 Textile ERP Trends: SAP, Odoo & Oracle
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Embracing Complexity in Serverless! GOTO Serverless Bengaluru
L1 - Introduction to python Backend.pptx
Introduction to Artificial Intelligence
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Operating system designcfffgfgggggggvggggggggg
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
System and Network Administration Chapter 2
Which alternative to Crystal Reports is best for small or large businesses.pdf
Transform Your Business with a Software ERP System
top salesforce developer skills in 2025.pdf
Nekopoi APK 2025 free lastest update
CHAPTER 2 - PM Management and IT Context
Reimagine Home Health with the Power of Agentic AI​
How to Migrate SBCGlobal Email to Yahoo Easily
medical staffing services at VALiNTRY
assetexplorer- product-overview - presentation
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Internet Downloader Manager (IDM) Crack 6.42 Build 41

Introduction to WebMvc.fn

  • 1. Confidential │ ©2020 VMware, Inc. Introduction to WebMvc.fn Functional Servlet Endpoints Arjen Poutsma (@poutsma) Sr. Staff Engineer at VMware 3rd September 2020
  • 2. Confidential │ ©2020 VMware, Inc. Agenda 2 Handler Functions Router Functions Filter Functions Final Comparison
  • 3. Confidential │ ©2020 VMware, Inc. 3 WebMvc.fn was introduced in Spring 5.2 and is fully compatible with Spring Boot
  • 4. Confidential │ ©2020 VMware, Inc. Handler Functions Map from ServerRequest to ServerResponse 4
  • 5. Confidential │ ©2020 VMware, Inc. 5 Map from ServerRequest to ServerResponse Handler Functions @Controller class PersonController { PersonRepository repository; ResponseEntity<Person> getPerson(@PathVariable String id) { Person person = repository.findById(id); return ResponseEntity.ok() .contentType(APPLICATION_JSON) .body(person); } ResponseEntity<List<Person>> getPeople() { List<Person> people = repository.findAll(); return ResponseEntity.ok() .contentType(APPLICATION_JSON) .body(people); } } Web MVC
  • 6. Confidential │ ©2020 VMware, Inc. 5 Map from ServerRequest to ServerResponse Handler Functions @Controller class PersonHandler { PersonRepository repository; ServerResponse getPerson(ServerRequest request) { String id = request.pathVariable("id"); Person person = repository.findById(id); return ServerResponse.ok() .contentType(APPLICATION_JSON) .body(person); } ServerResponse getPeople(ServerRequest request) { List<Person> people = repository.findAll(); return ServerResponse.ok() .contentType(APPLICATION_JSON) .body(people); } } WebMvc.fn
  • 7. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 6 Handler Function Comparison @Controller class PersonController { PersonRepository repository; ResponseEntity<Person> getPerson(@PathVariable String id) { Person person = repository.findById(id); return ResponseEntity.ok() .contentType(APPLICATION_JSON) .body(person); } ResponseEntity<List<Person>> getPeople() { List<Person> people = repository.findAll(); return ResponseEntity.ok() .contentType(APPLICATION_JSON) .body(people); } } @Controller class PersonHandler { PersonRepository repository; ServerResponse getPerson(ServerRequest request) { String id = request.pathVariable("id"); Person person = repository.findById(id); return ServerResponse.ok() .contentType(APPLICATION_JSON) .body(person); } ServerResponse getPeople(ServerRequest request) { List<Person> people = repository.findAll(); return ServerResponse.ok() .contentType(APPLICATION_JSON) .body(people); } }
  • 8. Confidential │ ©2020 VMware, Inc. 7 Handler Functions map from ServerRequest to ServerResponse • both are immutable • create response with builder
  • 9. Confidential │ ©2020 VMware, Inc. Router Functions Map from ServerRequest to HandlerFunction 8
  • 10. Confidential │ ©2020 VMware, Inc. 9 Map from ServerRequest to HandlerFunction Router Functions @Controller @RequestMapping("/people") class PersonController { PersonRepository repository; @RequestMapping(value = "/{id}", method = GET) ResponseEntity<Person> getPerson(@PathVariable String id) { ... } @RequestMapping(method = GET) ResponseEntity<List<Person>> getPeople() { ... } } Web MVC
  • 11. Confidential │ ©2020 VMware, Inc. 9 Map from ServerRequest to HandlerFunction Router Functions @Controller class PersonHandler { PersonRepository repository; ServerResponse getPerson(ServerRequest request) { ... } ServerResponse getPeople(ServerRequest request) { ... } @Bean static RouterFunction router(PersonHandler handler) { return route() .GET("/people/{id}", handler::getPerson) .GET(“/people", handler::getPeople) .build(); } } WebMvc.fn
  • 12. Confidential │ ©2020 VMware, Inc. 9 Map from ServerRequest to HandlerFunction Router Functions @Controller class PersonHandler { PersonRepository repository; ServerResponse getPerson(ServerRequest request) { ... } ServerResponse getPeople(ServerRequest request) { ... } @Bean static RouterFunction router(PersonHandler handler) { return route() .path(“/people", builder -> builder .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople)); .build(); } } WebMvc.fn
  • 13. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 10 Router Function Comparison @Controller class PersonHandler { PersonRepository repository; ServerResponse getPerson(ServerRequest request) { ... } ServerResponse getPeople(ServerRequest request) { ... } @Bean static RouterFunction router(PersonHandler handler) { return route() .path(“/people", builder -> builder .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople)); .build(); } } @Controller @RequestMapping(“/people") class PersonController { PersonRepository repository; @RequestMapping(value = "/{id}", method = GET) ResponseEntity<Person> getPerson(@PathVariable String id) { ... } @RequestMapping(method = GET) ResponseEntity<List<Person>> getPeople() { ... } }
  • 14. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 10 Router Function Comparison @Controller class PersonHandler { PersonRepository repository; ServerResponse getPerson(ServerRequest request) { ... } ServerResponse getPeople(ServerRequest request) { ... } @Bean static RouterFunction router(PersonHandler handler) { return route() .path(“/people", builder -> builder .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople)); .build(); } } @Controller @RequestMapping(“/people") class PersonController { PersonRepository repository; @RequestMapping(value = "/{id}", method = GET) ResponseEntity<Person> getPerson(@PathVariable String id) { ... } @RequestMapping(method = GET) ResponseEntity<List<Person>> getPeople() { ... } }
  • 15. Confidential │ ©2020 VMware, Inc. 11 Router Functions created using builder • GET, POST, PUT, etc. • resources • nesting • more powerful abstraction underneath: RequestPredicate
  • 16. Confidential │ ©2020 VMware, Inc. Request Predicates Evaluate on a ServerRequest 12
  • 17. Confidential │ ©2020 VMware, Inc. 13 Evaluate on a ServerRequest Request Predicates RequestPredicate get = RequestPredicates.method(HttpMethod.GET); RequestPredicate people = RequestPredicates.path("/people"); RequestPredicate getPeople = get.and(people); // or RequestPredicates.GET("/people") RequestPredicate acceptJson = RequestPredicates.accept(APPLICATION_JSON); RequestPredicate extensionJson = RequestPredicates.pathExtension("json"); RequestPredicate paramTypeJson = RequestPredicates.param("type", "json"); RequestPredicate json = acceptJson.or(extensionJson).or(paramTypeJson);
  • 18. Confidential │ ©2020 VMware, Inc. 14 Evaluate on a ServerRequest Request Predicates @Controller class PersonHandler { PersonRepository repository; ... ServerResponse createPerson(ServerRequest request) { Person person = request.body(Person.class); repository.savePerson(person); return ServerResponse.ok() .build(); } @Bean static RouterFunction router(PersonHandler handler) { return route() .path("/people", b -> b .GET("/{id}", accept(APPLICATION_JSON), handler::getPerson) .GET("/", accept(APPLICATION_JSON), handler::getPeople) .POST("/", contentType(APPLICATION_JSON), handler::createPerson)) .build(); } }
  • 19. Confidential │ ©2020 VMware, Inc. 14 Evaluate on a ServerRequest Request Predicates @Controller class PersonHandler { PersonRepository repository; ... ServerResponse createPerson(ServerRequest request) { Person person = request.body(Person.class); this.repository.savePerson(person); return ServerResponse.ok() .build(); } @Bean static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) { return route() .path(“/people", b -> b .nest(accept(APPLICATION_JSON), b1 -> b1 .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople) ) .POST("/", contentType(APPLICATION_JSON), handler::createPerson)) .build(); } }
  • 20. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 15 Request Predicates Comparison @Controller @RequestMapping(“/people”) class PersonController { PersonRepository repository; @RequestMapping(value = "/{id}", method = GET, produces = APPLICATION_JSON_VALUE) ResponseEntity<Person> getPerson(@PathVariable String id) { ... } @RequestMapping(method = GET, produces = APPLICATION_JSON_VALUE) ResponseEntity<List<Person>> showPeople() { ... } @RequestMapping(method = POST, consumes = APPLICATION_JSON_VALUE) void createPerson(RequestEntity<Person> person) { ... } } @Controller class PersonHandler { PersonRepository repository; ... @Bean static RouterFunction router(PersonHandler handler) { return route() .path(“/people", b -> b .GET("/{id}", accept(APPLICATION_JSON), handler::getP .GET("/", accept(APPLICATION_JSON), handler::getPeopl .POST("/", contentType(APPLICATION_JSON), handler::cr .build(); } }
  • 21. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 15 Request Predicates Comparison @Controller @RequestMapping(“/people”) class PersonController { PersonRepository repository; @RequestMapping(value = "/{id}", method = GET, produces = APPLICATION_JSON_VALUE) ResponseEntity<Person> getPerson(@PathVariable String id) { ... } @RequestMapping(method = GET, produces = APPLICATION_JSON_VALUE) ResponseEntity<List<Person>> showPeople() { ... } @RequestMapping(method = POST, consumes = APPLICATION_JSON_VALUE) void createPerson(RequestEntity<Person> person) { ... } } @Controller class PersonHandler { PersonRepository repository; ... @Bean static RouterFunction router(PersonHandler handler) { return route() .path(“/people", b -> b .GET("/{id}", accept(APPLICATION_JSON), handler::getP .GET("/", accept(APPLICATION_JSON), handler::getPeopl .POST("/", contentType(APPLICATION_JSON), handler::cr .build(); } }
  • 22. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 16 Request Predicates Comparison @Controller class PersonHandler { PersonRepository repository; ... @Bean static RouterFunction<ServerResponse> routerFunction(Person return route() .path("/person", b -> b .nest(accept(APPLICATION_JSON), b1 -> b1 .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople) ) .POST("/", contentType(APPLICATION_JSON), handler::cr .build(); } } ?
  • 23. Confidential │ ©2020 VMware, Inc. Handler Filter Functions Maps ServerRequest and HandlerFunction to ServerResponse 17
  • 24. Confidential │ ©2020 VMware, Inc. 18 Maps ServerRequest and HandlerFunction to ServerResponse Handler Filter Functions @Controller @RequestMapping("/people") class PersonController { PersonRepository repository; ... @ExceptionHandler(NotFoundException.class) ResponseEntity notFound() { return ResponseEntity.notFound().build() } } Web MVC
  • 25. Confidential │ ©2020 VMware, Inc. 18 Maps ServerRequest and HandlerFunction to ServerResponse Handler Filter Functions @Controller class PersonHandler { PersonRepository repository; ... ServerResponse notFound(Throwable throwable, ServerRequest request) { return ServerResponse.notFound().build(); } @Bean static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) { return route() .path(“/people", b -> b .nest(accept(APPLICATION_JSON), b1 -> b1 .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople) ) .POST("/", contentType(APPLICATION_JSON), handler::createPerson)) .onError(NotFoundException.class, handler::notFound) .build(); } } WebMvc.fn
  • 26. Confidential │ ©2020 VMware, Inc. 18 Maps ServerRequest and HandlerFunction to ServerResponse Handler Filter Functions @Controller class PersonHandler { PersonRepository repository; ... ServerResponse notFound(Throwable throwable, ServerRequest request) { return ServerResponse.notFound().build(); } @Bean static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) { return route() .path(“/people", b -> b .nest(accept(APPLICATION_JSON), b1 -> b1 .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople) .onError(NotFoundException.class, handler::notFound) ) .POST("/", contentType(APPLICATION_JSON), handler::createPerson)) .build(); } } WebMvc.fn
  • 27. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 19 Handler Filter Function Comparison @Controller @RequestMapping("/people") class PersonController { PersonRepository repository; ... @ExceptionHandler(NotFoundException.class) ResponseEntity notFound() { return ResponseEntity.notFound().build() } } @Controller class PersonHandler { PersonRepository repository; ... ServerResponse notFound(Throwable throwable, ServerRequest request) { return ServerResponse.notFound().build(); } @Bean static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) { return route() .path("/person", b -> b .nest(accept(APPLICATION_JSON), b1 -> b1 .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople) ) .POST("/", contentType(APPLICATION_JSON), handler::createPerson)) .onError(NotFoundException.class, handler::notFound) .build(); } }
  • 28. Confidential │ ©2020 VMware, Inc. Web MVC WebMvc.fn 19 Handler Filter Function Comparison @Controller @RequestMapping("/people") class PersonController { PersonRepository repository; ... @ExceptionHandler(NotFoundException.class) ResponseEntity notFound() { return ResponseEntity.notFound().build() } } @Controller class PersonHandler { PersonRepository repository; ... ServerResponse notFound(Throwable throwable, ServerRequest request) { return ServerResponse.notFound().build(); } @Bean static RouterFunction<ServerResponse> routerFunction(PersonHandler handler) { return route() .path("/person", b -> b .nest(accept(APPLICATION_JSON), b1 -> b1 .GET("/{id}", handler::getPerson) .GET("/", handler::getPeople) ) .POST("/", contentType(APPLICATION_JSON), handler::createPerson)) .onError(NotFoundException.class, handler::notFound) .build(); } }
  • 29. Confidential │ ©2020 VMware, Inc. Final Comparison 20
  • 30. Confidential │ ©2020 VMware, Inc. • Functions • Code • Rigid handler methods (ServerRequest→ServerResponse) • Flexible routing • Annotations • Meta-data • Flexible handler methods (parameters & return type) • Limited routing Web MVC WebMvc.fn 21 Request Predicates Comparison
  • 31. Confidential │ ©2020 VMware, Inc. Thank You