Architecture of a Reactive Spring Boot Application

Janani Subbiah
Javarevisited
Published in
4 min readOct 20, 2022

--

Components in a typical spring boot reactive application.

Photo by Jason Briscoe on Unsplash

Spring boot supports building reactive applications using project reactor under the hood and this means a slight shift in the architecture of reactive spring boot applications as compared to a traditional non-reactive Spring Boot application. In this post I would like to touch on the different components of a reactive Spring Boot application, the terminologies and different options at every layer.

Router Function

The router function defines the entry point into the application. It defines the routes (aka APIs) exposed by the application which in turn serve as individual entry points. In addition to the API (which consists of the path and the HTTP verb), it also specifies handling of the request i.e. what happens when a request matching a certain API is received. More often than not the handling of an API request is done by the next component in the chain, a Handler.

Handler

Handler methods process ServerRequest objects and returns a ServerResponse object (in case of a reactive application a Handler method will return a Mono<ServerResponse>). The Handler does not need to perform all steps to convert an incoming ServerRequest to Mono<ServerResponse> but it is the component that uses other components and services for that processing.

Other components

Below the Handlers are all other components in the application i.e. other beans in the application that can be reused across the app. The components in this layer usually use each other interchangebly. Most of the All other components, more often than not fall under one of the following categories:

Service

If the processing of an API request requires talking to multiple components and is reusable across the codebase, I like to create a service class that becomes a single place in the code where all these multiple components can be combined and used to generate an output. Service classes help in testing certain processing steps in isolation and help with code reuse and maintanence. Service classes may use other classes in this section including clients, computational units, other services, repositories and computation classes.

Client

When a component is responsible for making API calls to other services/ 3rd party APIs, I like to call such classes clients (because they are clients of those services they make API calls to). In case of reactive Spring, chances are you will be using Spring’s WebClient to make API calls. There is no need per se to create a component dedicated to communicating with other APIs. I like to break them up this way because:

  • It becomes easy to test this component thoroughly for error as well happy path scenarios.
  • All error handling for a specific API can occur in this component in an isolated way.
  • Any future changes that might be made to third party APIs, will only mean that the client that interacts with that API will be the only component that will need to be changed.

It helps to have a client class for every 3rd party API the application interacts with and if modeled that way, a client class may use utility classes, computational classes and repositories (rarely other service/client classes)

Utility/Helper classes

No matter what application you are building, chances are you are going to have at least one component that takes care of all validations (as an example). Sometimes, there could be multiple validators to validate different data sets processed by the application. While validators are one kind of utility classes, there are other types that fall into this category (this is not an exclusive list):

  • Transformers (E.g.: DTOs/SVOs — > Entities and vice versa)
  • Formatters (E.g.: run on data before it is sent to a presentation layer)
  • Error handlers

If utility classes could be broken up the piece of data that needs validation (and this can be done in most cases), a utility class may not need to depend on any other class in the application (except other utility classes).

Repository

Repositories are spring interfaces/classes that define the contract (and sometimes implementation) for interacting with a datastore (could be relational DB, document store etc). These are not the same as any of the components previously described because spring-data-jpa provides an option to define functions/methods in interfaces marked as repositories and the implementation of those methods is taken care of by Spring (aka query methods). The simplest option to define a repository component is to extend from spring-data’s CrudRepository.

Repository classes are like clients where there is usually a one on one mapping to an entity (or table in the DB). Repositories usually do not depend on any other spring components.

The components mentioned this in blog post are just to provide an overall example and do not cover all possible scenarios. Spring Boot’s reactive stack is different from the non-reactive stack not just in terms of operators available to handle requests but also in terms of how requests are handled and processed. I hope this article provides a good starting place for your reactive application backed by Spring Boot!

--

--

Janani Subbiah
Javarevisited

Product Architect | Ice cream lover | Newbie gardener