Building the Backend of Chat applications with spring WebFlux and reactive MongoDB
By: Khalid Abdul Wahab
Tags: Java, Spring Boot, Reactor, Backend Development, Mongodb

These past few weeks, I was trying to build a real-time chat application with spring boot. The first thing I thought of was WebSockets, However, I wanted to know if there were other ways to do this and I found SSE’s.

Note that this article is not meant to compare Websockets to SSE’s. Both methods are awesome and have their pros and cons. You are free to use any method you find suitable for your case.

What are SSE’s?

SSE is an acronym for server-sent events. It is a unidirectional technology that allows the server to send events to the client. This means that we can create an endpoint to receive data from a client and the server or backend will react to the new data inserted into it. The cool thing about SSE’s is that even if you do not have knowledge of WebSockets, you can still implement them easily.

This article will be using reactive spring to build the chat app server since it supports reactive databases out of the box.

What is Spring Webflux??

Spring WebFlux is an asynchronous framework. It can run on Servlet Containers using the Servlet 3.1 non-blocking IO API as well as other async runtime environments such as netty or undertow. It makes use of a library called reactor for its reactive support and reactor is an implementation of the Reactive Stream specification. Reactor has 2 major types:

Flux: This is used to represent 0 to N elements. Mono: This is used to represent a 0 to 1 element or a single element.

Alright, Let’s get our hands dirty!!

In order to make use of reactive MongoDB in our project, we will have to first install MongoDB in our computer systems and make sure mongo is running on port 27017. If you do not have MongoDB installed, you can check here for details on how to do that.

I wouldn’t go through all the details of creating a project in spring. If you are new to spring boot and MongoDB I recommend this article. One thing you should note however is that you will need to add the dependencies for reactive web and reactive MongoDB when you are creating your project.

Also, make sure you add your database URL in your application.properties file.

In order to be able to stream data using SSE, we will need to create a capped collection in MongoDB. We will need to specify a size in bytes for this capped collection. Use the script below to create a capped collection.

Do not rely on spring data to create this capped collection for you. Make sure you run this script to create a capped collection. I did not find a way of creating a capped collection with spring data. If you have a way of doing this automatically with spring data, please mention it in the comment section.

Up next, we create a message Model.

The above model shows that we created a collection called messages with an Id, sender, the person we are sending the message to and a channel Id. The point of this article is to show you how to send and receive messages, so we can ignore the other values and focus on just the sending messages.

We can now create a repository interface that will expose the CRUD methods to us.

We can notice a few things here:

We extend ReactiveMongoRepository instead of the usual MongoRepository We are using a tailable cursor to query the database by channelId . This is what will enable us to fetch data automatically as they are inserted. We use @Tailable to indicate that this method may need to react to changes in the database.

Now let’s write the controller.

From the controller, you will notice the following:

We have a post method to save a chat message that returns a Mono since we are returns a message Object. Also, make sure you call subscribe() on the post method. We are using the tailable cursor query to stream the messages and we specify the Media Type to be MediaType.TEXT_EVENT_STREAM_VALUE and this method are returning a Flux since it will be returning more than one message and we specify the channel.

That’s it!! You just built the backend for a real-time chat app!!

You can now send your requests in postman or swagger and you will notice that the get endpoint for streaming messages will be updated automatically without you having to perform any action.

data streaming via the GET request

We will notice from the screenshot above that each message is wrapped around a data object which shows that the messages are being sent in the form of server-sent events.

Code samples can be found on my Github repository.

Thanks for reading!

Happy coding!!