HelloKoding

Practical coding guides

WebFlux Reactive Web API Example in Spring Boot

Spring WebFlux is a reactive-stack web framework, part of Spring 5, fully non-blocking and runs on such servers as Netty, Undertow, and Servlet 3.1+ containers

This guide will give you the steps to build a non-blocking web API with Spring WebFlux in a Spring Boot project

What you’ll need

  • Your favorite IDE
  • JDK 8+ or OpenJDK 8+
  • Maven 3+

Init project structure

You can create and init a new Spring Boot project by using Spring CLI or Spring Initializr. Learn more about using these tools at here

The final project structure as below

├── src
│   └── main
│       ├── java
│       │   └── com
│       │       └── hellokoding
│       │           └── spring
│       │               ├── HelloApplication.java
│       │               ├── HelloHandler.java
│       │               └── HelloRouter.java
│       └── resources
│           ├── static
│           ├── templates
│           └── application.properties
└── pom.xml

Project dependencies

Add spring-boot-starter-webflux into your project as a dependency on pom.xml or build.gradle file. The library versions can be omitted as it is resolved by the parent pom provided by Spring Boot

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
</dependencies>

You can find the full pom.xml file as below

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.3.RELEASE</version>
	</parent>

	<groupId>com.hellokoding.spring</groupId>
	<artifactId>spring-webflux</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-webflux</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Define a reactive API handler

HelloHandler.java

package com.hellokoding.spring;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

@Component
public class HelloHandler {
    public Mono<ServerResponse> hello(ServerRequest request) {
        String name = request
            .queryParam("name")
            .orElse("Spring WebFlux");

        return ServerResponse.ok()
            .contentType(MediaType.TEXT_PLAIN)
            .bodyValue(String.format("Hello, %s!", name));
    }
}

The handler method declaration is defined by HandlerFunction, a functional interface in Spring, as below

package org.springframework.web.reactive.function.server;
import reactor.core.publisher.Mono;

@FunctionalInterface
public interface HandlerFunction<T extends ServerResponse> {
	Mono<T> handle(ServerRequest request);
}

Define a reactive API router

HelloRouter.java

package com.hellokoding.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;

@Configuration
public class HelloRouter {
    @Bean
    public RouterFunction<ServerResponse> route(HelloHandler helloHandler) {
        return RouterFunctions
            .route(GET("/hello").and(accept(MediaType.TEXT_PLAIN)), helloHandler::hello);
    }
}

Here we route GET requests for “/hello” to the hello method in helloHandler object

Define application bootstrap

HelloApplication.java

package com.hellokoding.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloApplication {
	public static void main(String[] args) {
		SpringApplication.run(HelloApplication.class, args);
	}
}

Run and Test

You can run the application by typing the following command on the terminal console at the project root directory

$ mvn clean spring-boot:run

You would see this text in the console

o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080

Access to http://localhost:8080/hello on your web browser, the following response is expected

Hello, Spring WebFlux!

Conclusion

In this tutorial, we learned to build a reactive web API by using Spring WebFlux in a Spring Boot project. You can find the full source code on GitHub

Follow HelloKoding