Reactive API - I

How to create reactive apis using spring web-flux

Reactive API - I

In this article , I am going to write about reactive apis and how they could be developed easily using spring web flux. If you are interested going through the code first, Please visit the repo for this project - Reactive-API

What are Reactive APIs ?

Reactive Programming is a programming paradigm where we strive to write non-blocking, asynchronous, event-driven and functional style of code which is easier to read, understand and reason about.

Why Reactive APIs ?

Below are the advantages of using Reactive APIs instead of traditional Imperative APIs.

  • Asynchronous and non-blocking : Reactive APIs enables us to write asynchronous and non-blocking APIs

  • Event/Message driven : The system will generate events or messages for an activity. For example when a data comes from a database, it comes as a stream of events.

  • Better utilisation of system resource : In reactive APIs threads are non-blocking asynchronous and hence won't be blocked waiting for I/O operations to complete. Hence more number of user requests could be served using fewer number of threads.

  • Support for back pressure - If producer is producing data at a rate which the consumer system is unable to handle, there is mechanism for the consumer to provide feedback to the producer asking it to slow down.

  • Move away from thread per request model : Unlike the traditional restful apis where one thread is used and blocked for each request, In reactive apis once a request is made, an event is created in the server side and the request thread is released to handle other requests.

Below is image depicting how data will be fetched from database in a reactive api.

reactive_data_flow.png

N.B : Notice that the request thread is returned immediately and then the server emits onNext event for each item and once all the items are returned, onComplete event is emitted.

How Spring helps in writing Reactive APIs ?

Spring 5 includes Spring WebFlux which provides reactive programming support for web applications. It internally uses Project Reactor and its publisher implementation, Flux and Mono.

Reactive REST application

Now we'll build a simple reactive REST application ProductService using Spring WebFlux.

Dependencies

We are going to use dependencies as mentioned below :

  • Spring WebFlux Starter dependency
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
  • Reactive Spring Data starter dependency
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-r2dbc</artifactId>
        </dependency>
  • Reactive MySql
      <dependency>
            <groupId>dev.miku</groupId>
            <artifactId>r2dbc-mysql</artifactId>
            <scope>runtime</scope>
        </dependency>
  • MySql Connector dependency
    <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

Note - One crucial thing to note when developing a reactive api is to make sure that whole development stack is reactive. If the persistence layer of our application is imperative then the whole application turns out to be effectively non reactive (imperative).

Reactive Rest Controller

We can still use the good old annotated style Controllers inside Reactive API

@RestController
public class ProductController {

    private final ProductService service;

    @Autowired
    public ProductController(ProductService service)
        {
            this.service = service;

        }

    @GetMapping(path =   "/product" , produces = MediaType.TEXT_EVENT_STREAM_VALUE )
    public Flux<Product> getAllProducts()
        {
            return service.getProducts();
        }

}

Retrieving products from Database

We are going to use ReactiveCrudRepository to fetch products from the database

public interface ProductRepository extends ReactiveCrudRepository<Product, Integer>{

}

ProductService Class

I have added a dummy delay to help visualise how events are emitted at regular intervals , rather than blocking and waiting for db fetch to complete and than return the response.

@Service
public class ProductService {

    ProductRepository repository;

    @Autowired
    public ProductService (final ProductRepository repository)
    {
        this.repository = repository;
    }

    public Flux<Product> getProducts() {
        // whole method takes 10 second 
        //but the client will get each product at interval of 5 seconds.
        return repository.findAll().delayElements(Duration.ofSeconds(5));   

    }




}

Conclusion

Reactive APIs or Reactive programming in general is not applicable to all use cases. It is difficult and inherently complex to implement. If the application is not highly concurrent and IO operation heavy, we should not use reactive programming. It has been demonstrated that reactive api in the wrong context and implementation is actually deterrent to application performance. But having said that, Reactive APIs are being adopted at a good rate in the enterprise level and it definitely optimises performance, throughput and resource utilisation if implemented correctly for the correct use-case.