Getting Started with Spring WebFlux — Bootstrapping a Reactive Web Application with Spring Initializr
Introduction
In this article, we will walk through the process of creating a reactive web application using Spring WebFlux and Spring Boot. Spring WebFlux is a reactive framework that provides support for non-blocking, asynchronous web applications, making it perfect for modern, scalable applications. We will use Spring Initializr, an online service, to create a boilerplate project to get started quickly.
Prerequisites: Before diving into the tutorial, make sure you have the following tools installed:
- JDK 11 or later
- Maven or Gradle (we will use Maven in this example)
- A suitable IDE, such as IntelliJ IDEA or Eclipse
Step 1: Generate the project using Spring Initializr
Head over to the Spring Initializr website. Configure the following options for your project:
- Project type: Maven Project
- Language: Java
- Packaging: Jar
- Java version: 11
- Group: com.example
- Artifact: reactive-webapp
- Name: reactive-webapp
- Description: A simple reactive web application using Spring WebFlux
- Package name: com.example.reactive-webapp
In the “Dependencies” section, search for “WebFlux” and select “Reactive Web” to include Spring WebFlux in your project. Click on “Generate” to download the zipped project files.
Step 2: Import and explore the project
Extract the downloaded project files and import them into your favorite IDE. You should see a basic structure similar to the following:
reactive-webapp/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com.example.reactive-webapp/
│ │ │ └── ReactiveWebappApplication.java
│ │ └── resources/
│ │ ├── static/
│ │ ├── templates/
│ │ └── application.properties
│ └── test/
│ └── java/
│ └── com.example.reactive-webapp/
│ └── ReactiveWebappApplicationTests.java
├── .gitignore
├── pom.xml
└── README.md
Step 3: Implement a simple reactive endpoint
In ReactiveWebappApplication.java
, add a new RouterFunction
bean to define a simple reactive endpoint:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
@SpringBootApplication
public class ReactiveWebappApplication {
public static void main(String[] args) {
SpringApplication.run(ReactiveWebappApplication.class, args);
}
@Bean
public RouterFunction<ServerResponse> routeHelloWorld() {
return route(GET("/hello"),
request -> ServerResponse.ok()
.contentType(MediaType.TEXT_PLAIN)
.body(Mono.just("Hello, Reactive World!"), String.class));
}
}
Step 4: Run the application
Run the ReactiveWebappApplication
class from your IDE or use Maven to start the application:
$ cd reactive-webapp
$ mvn spring-boot:run
After the application starts, navigate to http://localhost:8080/hello in your browser or use a tool like curl
to test the endpoint:
$ curl http://localhost:8080/hello
You should see the response “Hello, Reactive World!”.
Step 5: Create a simple reactive RESTful API
Now, let’s create a simple reactive RESTful API to demonstrate the power of Spring WebFlux. We’ll create a Person
class and a PersonHandler
class to handle the API requests.
First, create a new Person
class in the com.example.reactive-webapp
package:
package com.example.reactive-webapp;
public class Person {
private final String id;
private final String name;
public Person(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
Next, create a new PersonHandler
class in the same package:
package com.example.reactive-webapp;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
public class PersonHandler {
private final Map<String, Person> personMap = new HashMap<>();
public Mono<ServerResponse> getAllPeople(ServerRequest request) {
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(Flux.fromIterable(personMap.values()), Person.class);
}
public Mono<ServerResponse> getPerson(ServerRequest request) {
String personId = request.pathVariable("id");
Person person = personMap.get(personId);
if (person != null) {
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(person), Person.class);
} else {
return ServerResponse.notFound().build();
}
}
public Mono<ServerResponse> createPerson(ServerRequest request) {
Mono<Person> personMono = request.bodyToMono(Person.class);
return personMono.flatMap(person -> {
personMap.put(person.getId(), person);
return ServerResponse.created(request.uriBuilder().pathSegment(person.getId()).build().toUri())
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(person), Person.class);
});
}
}
Finally, update the ReactiveWebappApplication
class to include the new API endpoints:
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
// ... other imports and class definition ...
@Bean
public RouterFunction<ServerResponse> personRoutes(PersonHandler handler) {
return route(GET("/people"), handler::getAllPeople)
.andRoute(GET("/people/{id}"), handler::getPerson)
.andRoute(POST("/people"), handler::createPerson);
}
@Bean
public PersonHandler personHandler() {
return new PersonHandler();
}
Step 6: Test the RESTful API
Run the application again and use a tool like curl
or Postman to test the new RESTful API endpoints. For example:
- To create a new person:
$ curl -X POST -H "Content-Type: application/json" -d '{"id": "1", "name": "John Doe"}' http://localhost:8080/people
- To retrieve all people:
$ curl http://localhost:8080/people
- To retrieve a specific person by ID:
$ curl http://localhost:8080/people/1
Conclusion
We have demonstrated how to create a simple reactive web application using Spring WebFlux and Spring Boot. We used Spring Initializr to generate the project structure and implemented a simple reactive endpoint and a reactive RESTful API. This is just the beginning of what you can achieve with Spring WebFlux. As you build more complex applications, you can take advantage of the full power of reactive programming, allowing you to create highly scalable and responsive web applications.