Boot

Spring Boot Functional Endpoints

Welcome, in this tutorial, we will see how to create functional endpoints in a spring boot reactive application.

1. Introduction

Before going further in this tutorial, let us understanding web flux and reactive programming.

1.1 Webflux

  • Webflux is the reactive-web framework in spring and was added as a part of the 5.0 release
  • It offers asynchronous, non-blocking, and event-driven approach for the data processing
  • It also offers reactive streams back-pressure and runs on servers like Netty, Undertow, or the Servlet 3.1 containers

1.2 Reactive programming

  • Reactive programming is a functional, event-based, asynchronous, non-blocking data processing technique
  • The programming technique refers to reacting to the changes such as mouse clicks or the I/O events
  • The reactive programming application works better and more efficiently when working with the stream of data. The client application consumes it and streams it back to the users
  • The streaming api provides 4 different interfaces –
    • Publisher – Emits a sequence of events to subscribers according to the subscriber demands
    • Subscriber – Receives and processes the events emitted by the publisher interface. Multiple subscribers can be linked to a single publisher and can respond differently to the same event
    • Subscription – Defines a 1-1 relationship between the publisher and subscriber interfaces. Each subscriber can only be linked to a single publisher
    • Processor – Shows a processing stage consisting of both subscriber and publisher interface. It also obeys the contract of both the interfaces

1.3 Spring Webflux

  • Spring Webflux is similar to spring MVC and supports non-blocking reactive streams. It also supports the back-pressure concept and uses Netty as the preferred server to run reactive applications
  • Uses the project reactor as the reactive library
  • It uses 2 publishers –
    • Mono returns 0 or 1 element
    • Flux returns 0 to N elements. It is endless and can emit events forever. It also sends a complete notification when the last event is sent
  • Spring webflux allows scalability and immunity to latency problems in a microservice architecture. It also offers excellent stream processing capabilities

1.4 Lombok

  • Lombok is nothing but a small library that reduces the amount of boilerplate Java code from the project
  • Automatically generates the getters and setters for the object by using the Lombok annotations
  • Hooks in via the Annotation processor API
  • Raw source code is passed to Lombok for code generation before the Java Compiler continues. Thus, produces properly compiled Java code in conjunction with the Java Compiler
  • Under the target/classes folder you can view the compiled class files
  • Can be used with Maven, Gradle IDE, etc.

1.4.1 Lombok features

FeatureDetails
valLocal variables are declared as final
varMutable local variables
@Slf4JCreates an SLF4J logger
@CleanupWill call close() on the resource in the finally block
@GetterCreates getter methods for all properties
@SetterCreates setter for all non-final properties
@EqualsAndHashCode
  • Generates implementations of equals(Object other) and hashCode()
  • By default will use all non-static, non-transient properties
  • Can optionally exclude specific properties
@ToString
  • Generates String of class name, and each field separated by commas
  • Optional parameter to include field names
  • Optional parameter to include a call to the super toString method
@NoArgsConstructor
  • Generates no-args constructor
  • Will cause compiler error if there are final fields
  • Can optionally force, which will initialize final fields with 0/false/null var – mutable local variables
@RequiredArgsContructor
  • Generates a constructor for all fields that are final or marked @NonNull
  • The constructor will throw a NullPointerException if any @NonNull fields are null val – local variables are declared final
@AllArgsConstructor
  • Generates a constructor for all properties of the class
  • Any @NotNull properties will have null checks
@Data
  • Generates typical boilerplate code for POJOs
  • Combines – @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor
  • No constructor is generated if constructors have been explicitly declared
@Builder
  • Implements the Builder pattern for object creation
@Value
  • The immutable variant of @Data
  • All fields are made private and final by default

2. Spring Boot Functional Endpoints

Let us go ahead with the tutorial implementation but before going any further I’m assuming that you’re aware of the Spring boot basics.

2.1 Tools Used for Spring boot application and Project Structure

We are using Eclipse Kepler SR2, JDK 8, and Maven. In case you’re confused about where you should create the corresponding files or folder, let us review the project structure of the spring boot application.

Spring boot Endpoints - project structure
Fig. 1: Project structure

Let us start building the application!

3. Creating a Spring Boot application

Below are the steps involved in developing the application.

3.1 Maven Dependency

Here, we specify the dependency for the Spring boot (Webflux) and Lombok. The updated file will have the following code.

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.4.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	
	<groupId>com.springboot</groupId>
	<artifactId>SpringbootFunctionalrouting</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>
		</dependency>
		<dependency>
			<groupId>io.projectreactor</groupId>
			<artifactId>reactor-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

3.2 Application properties file

Create a new YML file at the location: SpringbootFunctionalrouting/src/main/resources/ and add the following code. You’re free to change the application details as per your wish.

application.properties

server.port=9091
spring.application.name=springboot-functional-routing

3.3 Java Classes

Let us write the important java class(es) involved in this application.

3.3.1 Implementation/Main class

Add the following code to the main class to bootstrap the application from the main method. Always remember, the entry point of the spring boot application is the class containing @SpringBootApplication annotation and the static main method.

SpringbootFunctionalroutingApplication.java

package com.springboot.flux;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//lombok annotation
@Slf4j
//spring annotation
@SpringBootApplication
public class SpringbootFunctionalroutingApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootFunctionalroutingApplication.class, args);
        log.info("Spring boot and functional routing application started successfully");
    }
}

3.3.2 Handler class

Add the following code to the handler class. The handler methods will map to the endpoints defined in the router class.

MyHandler.java

package com.springboot.flux.handler;

import lombok.extern.slf4j.Slf4j;
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.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;

//lombok annotation
@Slf4j
//spring annotation
@Component
public class MyHandler {

    //serves a plain text
    public Mono<ServerResponse> returnMonoResponse() {
        log.info("Returning a plain text");
        return ServerResponse.ok()
                .contentType(MediaType.TEXT_PLAIN)
                .body(Mono.just("Welcome to javacodegeeks.com"), String.class);
    }

    //serves a json stream
    public Mono<ServerResponse> returnFluxResponse() {
        log.info("Returning a json stream");
        return ServerResponse.ok()
                .contentType(MediaType.TEXT_EVENT_STREAM)
                .body(Flux.just("Welcome", "to", "javacodegeeks.com")
                        .delayElements(Duration.ofSeconds(2))
                        .log(), String.class);
    }

    //serves a json stream
    public Mono<ServerResponse> returnUserFluxResponse(final ServerRequest request) {
        final String name = request.pathVariable("name");
        log.info("Returning a username stream for = {}", name);
        return ServerResponse.ok()
                .contentType(MediaType.TEXT_EVENT_STREAM)
                .body(Flux.just("Welcome", name, "to", "javacodegeeks.com")
                        .delayElements(Duration.ofSeconds(2))
                        .log(), String.class);
    }
}

3.3.3 Router class

Add the following code to the router class. In this class, we will define the router function that maps to the respective handler functions.

MyRoutes.java

package com.springboot.flux.routes;

import com.springboot.flux.handler.MyHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

//spring annotation
@Configuration
public class MyRoutes {

    //spring annotation
    @Bean
    public RouterFunction<ServerResponse> functionalRoutes(final MyHandler handler) {
        return RouterFunctions.route()
                .GET("/api/mono", request -> handler.returnMonoResponse())      // http://localhost:9091/api/mono
                .GET("/api/flux", request -> handler.returnFluxResponse())              // http://localhost:9091/api/flux
                .GET("/user/flux/{name}", handler::returnUserFluxResponse)          // http://localhost:9091/user/flux/daniel
                .build();
    }
}

4. Run the Application

To execute the application, right-click on the SpringbootFunctionalroutingApplication.java class, Run As -> Java Application.

Spring boot Endpoints - run the app
Fig. 2: Run the Application

5. Project Demo

When the application is started we can test the mono and flux endpoints. To test the mono endpoint, open the below URL in the browser.
Mono endpoint

http://localhost:9091/api/mono

You will get a message – Welcome to javacodegeeks.com on the browser. Similarly, test the flux endpoint, open the below URL in the browser.

Flux endpoint

http://localhost:9091/api/flux

You will get the message – Welcome to javacodegeeks.com printed on the browser in parts. The message is received in parts as a JSON stream after 2 seconds with the help of a flux stream. Similarly, you can hit the name endpoint to receive the welcome message as a flux stream. That is all for this tutorial and I hope the article served you whatever you were looking for. Happy Learning and do not forget to share!

6. Summary

In this section, you learned:

  • Introduction to Webflux, Reactive programming, Spring Webflux, and Lombok
  • Steps to implement functional routing in a spring boot reactive application

You can download the sample application as an Eclipse project in the Downloads section.

7. Download the Project

This was an example of how to create functional endpoints in a spring boot reactive application.

Download
You can download the full source code of this example here: Spring Boot Functional Endpoints

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button