Reactor & Spring Boot Webflux series: EP 1 — Getting Started with Reactive Programming

fResult
10 min readNov 13, 2023

--

Photo by Markus Spiske on Unsplash

Journey Map.

EP 0 — A Series of Reactive Programming with Reactor & Spring Boot Webflux (The Road to Backend Developer Edition)

Key Topics.

These repositories are my final code for this episode.
Feel free to check one of them out.

On GitHub

On Gitlab

Checkout ep01_getting-started-with-reactive-programming branch.

git checkout --force --detach ep01_getting-started-with-reactive-programming
# OR
git switch ep01_getting-started-with-reactive-programming

Introduction to Reactive Programming Concepts.

Our journey into Reactive Programming deepens as we explore the foundational concepts that define this paradigm.
This segment delves into the core principles, offering a more comprehensive understanding of the building blocks introduced in the initial episode.

Asynchronous Programming:

So, imagine we’re at a busy bus stop.
Buses (our data) just keep coming, and we don’t want to wait for one to leave before the next one arrives.
That’s what we mean by asynchronous programming, dealing with data that doesn’t wait for one task to finish before moving on to the next.

Functional Programming and Reactive Programming:

Think of functional programming as our secret sauce.
It’s like having rules to play the game better.
We talk about immutability, pure functions, and higher-order functions.
What do these fancy terms mean?
Well, they’re like having a magic wand that helps us create super reliable and scalable reactive systems.
Functional programming and reactive programming make a power duo.

Reactive Streams:

Think about data flowing in a river, and we can grab it at any point.
Reactive streams are continuous flows of data, allowing us to handle information at different stages within the stream.
This flexibility is crucial for building responsive and scalable applications.

Handling Asynchronous Operations:

Now, let’s talk about Mono and Flux.
Mono is like a stream that expects either zero or one element.

Good for situations where we’re waiting for just one result.
Flux is for scenarios where we might get zero to many elements in our stream.

Understanding these concepts sets us up for the hands-on part in the next section.
We’re going to set up a simple Spring Boot WebFlux project using Kotlin.
It’s time to turn these ideas into action!

Setting up a basic Spring Boot WebFlux project in Kotlin.

Now, let’s get our hands dirty and set up our playground for some reactive action.

Step 1: Getting Our Tools Ready

Just like gearing up for a journey, the first thing we need is our toolkit.
In our case, it’s setting up a basic Spring Boot WebFlux project in Kotlin.
Don’t worry; it’s easier than it sounds.

Make sure you have the necessary tools installed:

  • Java Development Kit (JDK): Install a recent version 17 or more of JDK (I preferred version 21.)
  • IntelliJ IDEA (or any preferred IDE): Download and install IntelliJ IDEA.
  • Kotlin Plugin: (for IntelliJ IDEA’s user)
    1. Open it and go to Preferences (or Settings on Windows/Linux).
    2. Navigate to Plugins and search for "Kotlin."
    3. Install the Kotlin plugin and restart IntelliJ IDEA.
  • Gradle: Install Gradle 8 on your machine. You can do this manually or use a package manager like SDKMAN or HOMEBREW.
  • Spring Initializr: Visit Spring Initializr to initialize your project. Choose Kotlin as the language and include the “Spring Reactive Web” dependency.

Step 2: Creating Our Project

Think of creating our project by marking our starting point on the map.
We’ll be using Kotlin to write our code, and Spring Boot WebFlux to make things reactive.
It’s like choosing the right vehicle for our adventure.

1. Go to Spring Initializr

2. Configure Your Project:

  • Choose “Gradle Project” and “Kotlin” as the language.
  • Set “Jar” as the packaging type.
  • Pick the latest “3.x.x” (without RC or SNAPSHOT) as the Spring Boot version.
  • Choose “21” as the JVM version.
  • Fill in the group, artifact, and name fields as needed.
  • Add “Spring Reactive Web” in the dependencies section.
Spring Initializr configuration

3. Download the project:
Download as a ZIP file or use the link I’m sharing with you to get the setup I’ve configured.

Step 3: Running Our Project

Once everything is set, it’s time to hit the road! We’ll run our project and see our first taste of reactive programming in action. Get ready. It’s going to be a fun ride!

1. Open the main application file located at /src/dev/fresult/reactiveweb/ReactiveWebApplication.kt file (or similar). This is the heart of our application.

2. Look for content that resembles the image shown below

3. Run it:
Click the play button (it’s shown in the image above) to run the project.
We’ll see a screen like this.

4. Test it:
Enter http://localhost:8080 into our web browser.
We should see something like this.

Our build.gradle.kts file.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "3.2.1"
id("io.spring.dependency-management") version "1.1.4"
kotlin("jvm") version "1.9.21"
kotlin("plugin.spring") version "1.9.21"
}

group = "dev.fresult"
version = "0.0.1"

java {
sourceCompatibility = JavaVersion.VERSION_21
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
}

tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "21"
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

If it doesn’t work, please check the Project Structure.
(FileProject Structure)

Make sure that your JDK version is 21.

Creating and subscribing to reactive streams.

Now that we’ve got our Spring Boot WebFlux project ready to roll, it’s time to dive into the exciting world of reactive streams.

Think of reactive streams as the lanes on our adventure highway, where data flows smoothly, and we’re all set to interact with it.

Step 1: Understanding Reactive Streams

Think of Mono as our superhero for single results, like waiting for a bus that may come or may not come.

Image from ProjectReactor — Reactor Core documentation

Flux, on the other hand, is the champion of multiple results, perfect for handling a bunch of tasks at once.

Image from ProjectReactor — Reactor Core documentation

Step 2: Writing Our First Reactive Endpoint

1. Open the main application file (e.g., ReactiveWebApplication.kt).
2. Look for content that resembles the image shown in the setup.
3. Add a new endpoint to create a reactive stream. For example:


// Add imports
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux

// Add /reactive
@RestController
@RequestMapping("/reactive")
class ReactiveController {

@GetMapping("/hello")
fun getReactiveHello(): Flux<String> {
return Flux.just("Hello", "Reactive", "World!")
}
}

This simple endpoint returns a reactive stream of strings.

Step 3: Testing Our Reactive Endpoint

  1. Run your project (hit the play icon).
  2. Open your browser or a tool like Postman.
  3. Visit http://localhost:8080/reactive/hello

4. You’ll see the result: HelloReactiveWorld in your browser.

In Step 2: Writing Our First Reactive Endpoint above.
We’ve created a reactive endpoint that returns a Flux or Mono.
But hold on, you might wonder, where’s the subscribe() we talked about in EP 0?

A Quick Recap — Publisher, Subscriber, and Operators
In our reactive world, when we return Flux or Mono, we’re essentially creating a Publisher. Think of it as a source of data flowing like a stream. Now, here's the interesting part.

  1. Publisher (Flux or Mono): Our reactive endpoint returns a Flux or Mono, acting as a Publisher. It’s like a stream of data ready to flow.
  2. Subscriber (Client): When a client (like a web browser or another service) sends a request to our endpoint, it becomes the Subscriber. The client is ready to receive and handle the data.
  3. No Need for Manual Subscribe:
    Spring Boot, being smart, takes care of the subscription for us.
    When the client makes a request, Spring Boot automatically subscribes to our Publisher (Flux or Mono) and sends the data to the client.
    Therefore, no manual subscribe() needed.

What Happens Behind the Scenes?
When we return Flux or Mono, we’re saying, “Hey, here’s a stream of data, be ready to handle it!”
Spring Boot handles the subscription part, making our life easier.

So, even though we don’t explicitly write subscribe(), the magic happens behind the scenes, ensuring our reactive streams flow seamlessly from the Publisher to the Subscriber.

Try with the operator, collect.

@RestController
@RequestMapping("/reactive")
class ReactiveController {
@GetMapping("/hello")
fun getReactiveHello(): Mono<String> {
return Flux.just("Hello", "Reactive", "World").collect(Collectors.joining(" "));
}
}

Flux.just("Hello", "Reactive", "World"): Creates a Flux (reactive stream) with 3 elements: "Hello", "Reactive", and "World".

.collect(Collectors.joining(" ")): Uses the collect operator to concatenate the elements of the Flux (list of String) into a Mono (single String), joined by a space.

Handling asynchronous operations with Mono and Flux.

Now that we’ve dipped our toes into the world of reactive streams, let’s take it up
Think of we’re not just dealing with strings but handling various tasks asynchronously.
That’s where Mono and Flux, our trusty sidekicks, come into play.

Step 1: Understanding Mono and Flux

Think of Mono as our superhero for single results, like waiting for a bus that may or may not show up.
Flux, on the other hand, is the champion of multiple results, perfect for handling a bunch of tasks at once.

Step 2: Adding Some Async Magic

  1. Open your main application file (e.g., ReactiveWebApplication.kt).
  2. Below the existing code, let’s add an asynchronous endpoint using Mono and Flux. For example:
@RestController
@RequestMapping("/async")
class AsyncController {
@GetMapping("/task")
fun getAsyncTask(): Mono<String> = Mono.just("Async Task Completed!")
.delayElement(Duration.ofSeconds(3))

@GetMapping("/tasks")
fun getAsyncTasks(): Flux<String> = Flux.just("Task 1", "Task 2", "Task 3")
.delayElements(Duration.ofSeconds(1))
}

Step 3: Testing Our Async Endpoints

1. Run your project (click the play button).
2. Open your browser or Postman.
3. Go to http://localhost:8080/async/task

You’ll notice it takes around 3 seconds or more due to the .delayElement(Duration.ofSeconds(3)) setting.

4. Go to http://localhost:8080/async/tasks

See how it handles many tasks at once. Watch the magic happen as it shows Task 1, then Task 1Task 2, and finally Task 1Task 2Task 3 respectively.

And there we have it!
We’ve mastered handling asynchronous operations with Mono and Flux.
In our next adventure, we’ll explore building Functional Endpoints without the usual @RestController approach.

Get ready for more coding fun! 🚌 🚌

Conclusion

Alright, let’s wrap it up.

  1. We Started a Journey: Today, we kicked off our journey into reactive programming with Spring Boot WebFlux and Kotlin.
  2. Reactive Streams: We learned how to handle data smoothly, like lanes on a highway, using reactive streams.
  3. Mono and Flux: Met our helpers, Mono and Flux, who handle tasks — one at a time or a bunch together.
  4. Async Magic: We explored the magic of doing things asynchronously, like waiting for a bus or handling multiple tasks at once.
  5. What’s Next: In the next episode, we’ll build functional endpoints without the usual @RestController style.
    Exciting, right? Buckle up! We’re just getting started.
Photo by averie woodard on Unsplash

Thanks for reading until the final line.
If you’re confused or have any questions, don’t hesitate to leave the comments.

Feel free to connect with me and stay updated on the latest insights and discussions.
👉 https://linkedin.com/in/fResult 👈

--

--

fResult

ชื่อเล่นว่ากร เขามี background มาจากอาชีพเด็กวิ่งเอกสารในอาคารของธนาคาร โดยเรียนไปด้วยจนจบจากมหาลัยเปิดแห่งหนึ่ง และปัจจุบันทำงานเป็น Web Developer ครับทั่นน