Spring WebFlux the Spring Reactive Programming

Spring WebFlux, introduced in Spring 5, is a fresh module that marks the initial move towards incorporating a reactive programming model into the spring framework.

Reactive Programming during the Spring-time

If you are unfamiliar with the reactive programming model, I strongly recommend reading the following articles to gain understanding of it.

  • Reactive Manifesto
  • Reactive Streams
  • Java 9 Reactive Streams
  • RxJava

If you are not familiar with Spring 5, it is recommended that you review the Spring 5 Features.

Spring WebFlux is a reactive web framework provided by Spring.

spring webflux and spring mvc
    1. Mono implements the Publisher interface and returns either 0 or 1 element.

 

    Flux implements the Publisher interface and returns multiple (N) elements.

Example of a Hello World application using Spring WebFlux

spring webflux example

Dependencies for Spring WebFlux in Maven.

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.scdev.spring</groupId>
  <artifactId>SpringWebflux</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Spring WebFlux</name>
  <description>Spring WebFlux Example</description>
  
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <jdk.version>1.9</jdk.version>
    </properties>
    
  <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<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>
		</dependency>

		<dependency>
			<groupId>io.projectreactor</groupId>
			<artifactId>reactor-test</artifactId>
			<scope>test</scope>
		</dependency>
    </dependencies>
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</pluginRepository>
		<pluginRepository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</pluginRepository>
	</pluginRepositories>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.7.0</version>
                    <configuration>
                        <source>${jdk.version}</source>
                        <target>${jdk.version}</target>
                    </configuration>
                </plugin>
            </plugins>
    </pluginManagement>
    </build>
    
</project>

The pivotal dependencies are spring-boot-starter-webflux and spring-boot-starter-parent, while other dependencies serve for the creation of JUnit test scenarios.

Spring WebFlux Handler can be rephrased as “Handler for Spring WebFlux.”

The Handler method of Spring WebFlux manages the request and provides a Mono or Flux as the response.

package com.scdev.spring.component;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

import reactor.core.publisher.Mono;

@Component
public class HelloWorldHandler {

	public Mono<ServerResponse> helloWorld(ServerRequest request) {
		return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
			.body(BodyInserters.fromObject("Hello World!"));
	}
}

Take note that the Mono reactive component contains the body of the ServerResponse. Additionally, observe the sequence of functions used to establish the content type, response code, and body of the returned response.

The Spring WebFlux Router is to be rephrased natively.

One possible option:
Router for Spring WebFlux in Spring’s framework for reactive web applications.

Router methods are employed to establish routes for the application. These methods generate a RouterFunction object which also encapsulates the ServerResponse body.

package com.scdev.spring.component;

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

@Configuration
public class HelloWorldRouter {

	@Bean
	public RouterFunction<ServerResponse> routeHelloWorld(HelloWorldHandler helloWorldHandler) {

		return RouterFunctions.route(RequestPredicates.GET("/helloWorld")
                .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), helloWorldHandler::helloWorld);
	}
}

We have set up a GET endpoint at /helloWorld which will provide a plain text response when called by the client.

A Spring Boot Application

We need to set up our basic WebFlux application using Spring Boot.

package com.scdev.spring;

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

@SpringBootApplication
public class Application {

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

By examining the code above, it is apparent that there is no reference to Spring WebFlux. However, Spring Boot will automatically set up our application as Spring WebFlux because we have included the dependency of the spring-boot-starter-webflux module.

Support for Java 9 Modules

If you are using Java 8, our application is prepared to run. However, if you are using Java 9, we will also need to incorporate the module-info.java class.

module com.scdev.spring {
    requires reactor.core;
    requires spring.web;
    requires spring.beans;
    requires spring.context;
    requires spring.webflux;
    requires spring.boot;
    requires spring.boot.autoconfigure;
    exports com.scdev.spring;
}

Starting the Spring WebFlux Spring Boot Application.

Eclipse run as spring boot app
2018-05-07 15:01:47.893  INFO 25158 --- [           main] o.s.w.r.f.s.s.RouterFunctionMapping      : Mapped ((GET && /helloWorld) && Accept: [text/plain]) -> com.scdev.spring.component.HelloWorldRouter$$Lambda$501/704766954@6eeb5d56
2018-05-07 15:01:48.495  INFO 25158 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext     : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-05-07 15:01:48.495  INFO 25158 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2018-05-07 15:01:48.501  INFO 25158 --- [           main] com.scdev.spring.Application        : Started Application in 1.86 seconds (JVM running for 5.542)

Based on the logs, it’s evident that our application is operational on the Netty server, specifically on port 8080. Now, we can proceed with testing the app.

Test for a Spring WebFlux application.

We have the ability to test our app using different techniques.

    1. Using the CURL command, you can send a request to the specified URL and receive the response “Hello World!”.

Alternatively, you can launch the URL in a browser.

To test a Rest web service using WebTestClient from Spring 5 reactive web, you can use the provided JUnit test program. This program sends a GET request to the specified URI and checks if the response status is OK and the response body is “Hello World!”.

Another option is to use WebClient from Spring Web Reactive to call the REST web service. This program sends a GET request to the specified URI and retrieves the response body as a string.

Running these programs will give you the expected output and any relevant debug messages.

Please provide the text that you want me to paraphrase.

This article discussed Spring WebFlux and how to create a basic reactive Restful web service. It’s great to see that well-known frameworks like Spring are embracing the reactive programming model. However, there is still much to explore because if your dependencies are not reactive and non-blocking, your application cannot be truly reactive. For instance, relational database vendors do not provide reactive drivers as they rely on JDBC, which is not reactive. Thus, Hibernate API is also non-reactive. Consequently, if you are using relational databases, you cannot currently develop a fully reactive application. Nonetheless, I am optimistic that this situation will change in the near future.

The project code is available for download on my GitHub Repository.

Source: Official documentation

Paraphrased: Documentation endorsed by the official source.

 

 

more tutorials

Spring Boot CLI(Opens in a new browser tab)

The Spring Framework(Opens in a new browser tab)

Spring MVC HandlerInterceptorAdapter and HandlerInterceptor.(Opens in a new browser tab)

React Application Component Testing Integrate with Playwright(Opens in a new browser tab)

Spring Component annotation(Opens in a new browser tab)

 

 

Leave a Reply 0

Your email address will not be published. Required fields are marked *