Enable Javascript

Please enable Javascript to view website properly

Toll Free 1800 889 7020

Looking for an Expert Development Team? Take two weeks Trial! Try Now

How to Enable CORS in Spring WebFlux and Returning flux with Backend Implementations?

How to develop the reactive web server?

I used Spring WebFlux, which has been available since Spring 5 and is included in the Spring Boot 2.5 version. We'll use Spring Data and Spring Boot to connect to a Mongo database via its reactive driver.

Within the same backend application, I used two different web approaches: A reactive design that makes use of WebFlux and a MongoDB ReactiveCrudRepository. A blocking REST controller and a blocking MongoDB query are used in the traditional Spring boot Web stack.

In addition, we will employ: Docker will make MongoDB deployment easier.

Backend Application Design

Spring Boot integrates WebFlux capabilities, so let's harness their power to build our backend. The Spring Boot Initializr has made the first change in our dependency management. We don't include the traditional web starter.

But we do include the WebFlux one (spring-boot-starter-webflux in pom.xml). This starter includes the Reactor Netty server library dependencies, so Spring Boot knows which one to start at runtime. During development, we'll also have access to the Reactor API.

reactor-api

You'll build a standard three-layer backend application. Controllers will use the repositories directly because there is no business logic involved.

In addition, I created reactive methods from two coexisting stacks:

We plan to expose a list of quotes via a reactive web API, namely the ExampleReactiveController and ExampleMongoReactiveRepository, and compare it to the traditional blocking REST API, namely the ExampleBlockingController and ExampleMongoBlockingRepository.

The CorsFilter configuration class allows cross-origin requests to simplify the frontend connection, and we create the data loader (ExampleDataLoader) to insert the quotes into the Mongo database if they aren't already there.

A script to preload data into MongoDB. We'll use Spring Boot's CommandLineRunner implementation for this.

I have mentioned here the following topics:

We want to connect to the backend from a client app that is deployed at a different origin and uses a different port. That means the frontend will make a cross-origin request. That connection will be rejected unless we explicitly allow CORS (Cross-Origin Resource Sharing) in our configuration.

Bean CorsWebFilter

One option for enabling CORS with WebFlux globally is to inject a CorsWebFilter bean in the context with custom configuration of the allowed origins, methods, headers, and so on. I've set it up to accept any method and header from the origin, localhost:4200, where our frontend will be hosted.

CorsWebFilter

WebFlux:Standard controllers and router functions

WebFlux also includes a reactive web client, WebClient. You can use it to send requests to controllers that use reactive streams while also benefiting from backpressure. It is a reactive and fluent implementation of the well-known RestTemplate. This component is being popularly used across all the E-commerce application.

As stated in the first section, we will not be using WebClient. That is only useful for backend-to-backend communication and it is simple to use. Instead, you can use Angular to build a real frontend that consumes the reactive API.

Behind the scenes of returning a Flux from a controller

Controller’s code

Let us now concentrate on the most critical component of our backend application: the reactive controller.

import com.mano.reactiveweb.domain.ExampleQuote; import com.mano.reactiveweb.repository.ExampleMongoReactiveRepository; import org.springframework.data.domain.PageRequest; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.time.Duration; @RestController public class ExampleReactiveController { private static final int DELAY_IN_MS = 100; private final QuoteMongoReactiveRepository quoteMongoReactiveRepository; public QuoteReactiveController(final QuoteMongoReactiveRepository quoteMongoReactiveRepository) { this.quoteMongoReactiveRepository = quoteMongoReactiveRepository; } @GetMapping("/example-reactive") public Flux<Quote> getQuoteFlux() { return quoteMongoReactiveRepository.findAll().delayElements(Duration.ofMillis(DELAY_IN_MS)); } @GetMapping("/example-reactive-paged") public Flux<ExampleQuote> getQuoteFlux(final @RequestParam(name = "pg") int pge, final @RequestParam(name = "sze") int quote_size) { return quoteMongoReactiveRepository.findAllByIdNotNullOrderByIdAsc(PageRequest.of(pge, quote_size)) .delayElements(Duration.ofMillis(DELAY_IN_MS)); } }

Simulating poor performance:

Pagination:

By calling PageRequest.of, we created a Pageable object from the query parameters.

Reactive: Spring 5 and Spring data reactive repository

spring data

Saving the Entities in reactive Way:

Now imagine: Let's say we want to save a Quote. We're so sure of the outcome that we ignore the possibility that it won't save and use:

Blocking Controller and Mongo Repository:

mongo repository

Loading Data Into MongoDB With an ApplicationRunner:

Data loader:

We now have all of the code necessary to run our Spring Boot application. However, the quotes are not yet stored in the database. We'll fix this by reading them from the book's text version and storing them in MongoDB the first time the application runs.

data loader

Blocking logic and self-subscription:

Running MongoDB with Docker#

Remember that the full source code (Spring Boot, Angular, and Docker) can be found on GitHub: Full-Reactive Stack repository. Please read through this entire step-by-step process for detailed implementations:

Local setup:

docker container

$ docker-compose -f docker-compose-mongo-only.yml up

Recent Blogs

Categories

NSS Note
Some of our clients
team