[Spring Boot] Making a chat application with WebFlux and MongoDB — Part 1

Jay Kim
4 min readDec 17, 2021

--

Introduction

In this article, we are going to implement a chat application using Spring WebFlux. By going with the Reactive Stack, we are going to use MongoDB since it offers reactive database capabilities like tailable cursors.

Background

MongoDB Tailable Cursors

Normally when we query from a database, we end up with a finite data stream because the database driver opens a cursor to provide matching results then close the cursor when the client reads all results.

Maybe this will be understood better if we understand what a database cursor is. A database cursor in simple words can be thought of as “a pointer to the result set” and clients can iterate through a cursor to retrieve results.

But what is tailable cursor? According to the MongoDB documentation,

“However, for capped collections you may use a Tailable Cursor that remains open after the client exhausts the results in the initial cursor.”

Capped collection means a fixed-size collection based on the max number of records or max size of collection. It works in a way similar to circular buffers, which automatically removes the oldest documents to make room for new documents.

After clients insert new additional documents into a capped collection, the tailable cursor will continue to retrieve documents.

So with tailable cursor, we can get an infinite data stream over fixed-size collections because cursor remains open to notify us when a new record is inserted into a collection.

Server-Sent Event

Another important concept in this article is Server-Sent Event (SSE). SSE is HTTP based API dedicated to push stream from server to client. Of course Websockets can be used instead but in this article I decided to use SSE. I plan on making the same chat app using Websockets sometime in the future. Let’s see how SSE and Websockets are different at a high level.

However, there might be a question on “How can you implement this using uni-directional push? Clearly, user is typing and sending new messages”. Well, let us look at the flow of this application:

1. The web page we will implement using React will start by getting stored data (old chat messages) through SSE endpoint and render. Server and client stay connected for future data streaming.

2. A user enters and sends new chat messages on the web. These new messages will be sent to the server and they will be saved to DB.

3. As a new message gets saved, such message will be pushed from server to client through the SSE endpoint.

4. Lastly, the web will re-render as it receives pushed data.

Setup

MongoDB

I installed mongodb-community on my local machine. Let us look at some commands to start MongoDB and to create a capped collection.

Spring Boot

To get started, we need the following dependencies.

pom.xml

Define MongoDB configurations in application.yml

application.yml

Server Implementation

Data Model

Reactive Repository

Make sure to annotate the query method with @Tailable. This will enable infinite data stream using tailable cursors explained earlier.

Controller

Two endpoints will be implemented.

  • getMessages endpoint reads from the database and provides SSE. Notice how the Content-Type is set to text/event-stream.
  • setMessage endpoint saves a new chat message to the database.

Result

At this point, start the app and open a browser and go to localhost:8080/chat/id/{id}. Use your favorite REST client tool to post some data to /chat endpoint or use mongo CLI to add new chat messages to the database. As a new message is saved, such message will show up on the browser like below:

Output of SSE endpoint

It is observed that SSE endpoint will continue to stay alive until the client is exited.

Conclusion

We looked into how to implement the server side of chat application using the Reactive Stack. In the Part 2, we will discover the client side using React.

--

--

Responses (1)