สร้าง Reactive RESTful Web Service ด้วย Spring WebFlux

Phayao Boonon
3 min readJan 20, 2019

--

ใน Spring 5.0 เป็นต้นมาได้นำเสนอการพัฒนา Web Service ด้วย Reactive Web Stack ด้วย Spring WebFlux ที่ทำให้นักพัฒนาสมารถพัฒนา application ที่เป็นแบบ non-blocking I/O ได้ โดยที่ Spring Framework ได้ใช้ Reactive Stream ที่เป็นมาตรฐานสำหรับ asynchronous stream processing ซึ่งน่าสนใจมาก ในบทความนี้จึงจะนำเสนอการใช้งาน Spring WebFlux ร่วมกับ MongoDB

Spring WebFlux

เมื่อก่อน Web Framework ที่อยู่ใน Spring Framework, Spring Web MVC ทำเพื่อ Servlet API และ Servlet containers แต่ Reactive-Stack web framework อย่างเช่น Spring WebFlux เพิ่มเข้ามาใน Spring version 5.0 เป็น non-blocking I/O ที่รองรับ Reactive Streams และทำงานบน server รุ่นใหม่ อย่างเช่น Netty, Undertow และ Servlet 3.1+ container

Non-blocking web stack จะจัดการกับ concurrency ด้วย thread จำนวนน้อย และ scale ได้โดยใช้ทรัพยากร hardware ไม่มาก ตั้งแต่ Servlet 3.1 มี API สำหรับ Non-blocking I/O แต่อย่างไรก็ตามท้ายที่สุดก็ใช้ Servlet API แบบเดิมที่ synchronous (Filter, Servlet) หรือ blocking (getParameter, getPart) ทำให้เกิด common API ใหม่ขึ้นมาเพื่อรองรับ non-blocking ที่แท้จริง ในขณะ runtime อย่างเช่น Netty ทำให้เกิด async และ non-blocking ขึ้นมา และใช้งาน functional programming

Spring MVC vs Spring WebFlux

Programming Models

ใน Spring WebFlux มีตัวเลือกให้เราสามารถเขียนโปรแรมได้ 2 แบบ

  • Annotated Controllers: สอดคล้องกับ Spring MVC และรูปแบบ annotation เหมือนกัน ทั้ง Spring MVC และ WebFlux controller รองรับ reactive (Reactor และ RxJava) return type แต่ WebFlux รองรับ reactive @RequestBody ด้วย
  • Functional Endpoint: ใช้รูปแบบ Lamda-based, lightweight และ functional programming เราสามารถงาน utility ที่ application สามารถใช้ route และ handle request สิ่งที่แตกต่างมากกับ annotated controller ก็คือ application เป็นส่วนที่รับผิดชอบจัดการ request จากเริ่มต้นจนจบ เที่ยบกับการประกาศสิ่งที่ต้องการผ่าน annotation และเริ่มใช้งานที่ called back

Create Spring project

สร้าง Spring project ด้วย Spring Initializr ซึ่งในบทความนี้จะใช้ MongoDB มาเป็นส่วน Persistence Layer ดังนั้นเลือก dependency ดังนี้

  • Reactive Web — สำหรับ Spring WebFlux และ Netty เพื่อใช้งาน Web Reactive
  • Reactive MongoDB — สำหรับใช้งาน MongoDB แบบ reactive Spring Data
  • Embedded MongoDb — สำหรับใช้งาน MongoDB ใน app โดยที่ไม่ต้องติดตั้ง
  • Lombok — เป็นผู้ช่วยเราสร้าง boilerplate code ทำให้เราเขียนโปรแกรมได้เร็วขึ้น

และในบทความนี้จะทำเป็น Gradle project ด้วย Java และ Spring Boot 2.1.2

Spring Initializr

แต่เราจะต้องเปลี่ยน Embedded Mongo จาก testImplementation ที่ใช้ตอน Unit Test มาเป็น implementation เพื่อมาใช้ตอนรันโปรแกรม

Create Model (POJO)

สร้าง model (คลาส Customer) เพื่อเป็นข้อมูลของสำหรับ application โดยใช้ @Data สำหรับให้สร้าง getter/setter และ @Document เพื่อกำหนดให้เป็น persist data สำหรับ MongoDB และ @Id เพื่อกำหนดค่าของ field id อัตโนมัติ

Create Persistence

สร้าง คลาส CustomerRepository เพื่อเป็น Persistence Layer สำหรับติดต่อกับ MongoDB โดย extend ReactiveCrudRepository ซึ่งเป็น Repository ที่รองรับ Reactive ใช้งาน CRUD operation และเพิ่ม method findByFirstName เพื่อ query ด้วย field FirstName

Create Service

สร้าง คลาส CustomerService เพื่อเป็น Service Layer สำหรับบริการให้ Controller โดยที่ใช้งาน CustomerRepository ในการเชื่อมต่อกับ MongoDB

ซึ่งจะเห็นได้ว่า method จะ return เป็น Flux หรือ Mono ซึ่งเป็น Reactive Stream Publisher

  • Flux — เก็บลำดับข้อมูล 0..N (N element) ใช้กับ getCustomers ซึ่ง return ข้อมูลมากว่า 1 element
  • Mono — เก็บลำดับข้อมูล 0..1 (1 element) ใช้กับ method อื่นๆ ที่ return ข้อมูลเพียง element เดียว

Create Controller

สร้างคลาส CustomerController ซึ่งเป็นส่วนของ Presentation Layer ที่รับข้อมูลจาก User และเรียกใช้บริการจาก CustomerService

จะเห็นได้ว่า method ของ RestController จะ return เป็น Flux หรือ Mono เช่นเดียวกับ Service ที่เป็น Reactive และใน postCustomer และ updateCustomer รับข้อมูล POST/PUT @RequestBody เป็นแบบ Reactive ด้วย Mono และเรียกใช้งาน CustomerService ในแบบ functional programming

Test <UnitTest>

ทดสอบ Reactive RESTful Web Service ที่สร้างขึ้นด้วย Unit Test เพื่อทดสอบในแต่ล่ะ endpoint ของ Controller ด้วย WebTestClient ซึ่งเป็น reactive client ที่เหมาะสำหรับทดสอบ Reactive Web Service ภายในเป็น WebClient

สามารถดู completed implementation ได้ที่นี่ครับ

สรุป

จากการที่สร้าง Reactive RESTful Web Service ด้วย Spring WebFlux ขึ้นมานี้ จะเห็นได้ว่าแนวคิดการสร้าง Service นั้นแตกต่างจากการใช้ Spring MVC เป็นอย่างมากเพราะว่า method response เป็นแบบ Reactive ใช้ functional programming ในการดำเนินการกับตัวแปรทั้งหมด เพราะว่า return ของ Reactive Spring Data ก็เป็น Reactive ทั้งหมด ดังนั้นจะต้องเรียนรู้ Reactive Java มาก่อนถึงจะใช้งาน Spring WebFlux ด้วย Reactive อย่างราบรื่น

--

--

Phayao Boonon
Phayao Boonon

Written by Phayao Boonon

Software Engineer 👨🏻‍💻 Stay Hungry Stay Foolish

Responses (1)