Kafka + WebSockets + Angular: event-driven microservices all the way to the frontend
Tags: websockets, kafka, angular, eventdriven
Published: 2019-11-10 13:25:30

In the the initial post of the _**Event-driven microservices with Kafka**_ series (see [here](https://dev.to/victorgil/using-apache-kafka-to-implement-event-driven-microservices-af2)), I talked about the advantages of using event-driven communication and Kafka to implement stateful microservices instead of the standard stateless RESTful ones. 
I also presented the architecture and the source code of a related proof of concept application.  
In this post, I would like to show how to extend the asynchronous event-driven communication all the way from Kafka to the Web frontend passing through the Java backend.
Hence, in the first post of this series, we got rid of HTTP as the communication protocol among microservices in the backend, and now we are also replacing it (with WebSockets) as the communication protocol between the frontend and the backend.

####Ok, but why would you do that?
Because it provides a better experience to the end user!.
Using WebSockets you can build _legit_ real-time user interfaces, the updates are pushed immediately from the server to the client, no need for the user to click any button nor to refresh the browser.

####Wait, but we can do the same using good old HTTP, can't we?
Well... HTTP was not designed to provide real-time communication, but since people really wanted it, a number of workaround techniques and technologies have been create on top of it, such as:
* Long polling
* Short polling
* Server-Sent Events

Those are little more than hacks, IMHO.
WebSockets, on the other hand, provide **full-duplex bidirectional** communication, which means that information can flow from the client to the server and also in the opposite direction simultaneously, it cannot get more real-time than that (that's what I meant when I said '_legit_ real-time applications' before).
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/m0yedkwm7xh4e680c5fj.png" 
   alt="Image depicting the differences between HTTP and WebSockets"/>
  <figcaption>HTTP vs WebSockets (source: https://blogs.windows.com/windowsdeveloper/2016/03/14/when-to-use-a-http-call-instead-of-a-websocket-or-http-2-0)</figcaption>
</figure>

###The example
I added a new service to the same PoC application which I used in the previous post and also an Angular web frontend.

####Ok, but what does this new service do?
It allows the frontend user to receive information about the current balance of any account of her/his choice as well as live updates when the balance changes.
Also, information about any transactions related to that currently selected account (i.e., any amount of money credited or debited) past or live, is displayed to the users.

####Architecture
The new [_**Transfers WebSockets**_](https://github.com/VictorGil/transfers_websockets_service) service main components are: 
* Two Kafka [consumers](https://github.com/VictorGil/transfers_websockets_service/blob/1.0.0/src/main/java/net/devaction/kafka/consumer/TopicConsumerImpl.java) (one for each topic) to retrieve messages from the Kafka cluster
* Two Kafka Streams [local stores](https://github.com/VictorGil/transfers_websockets_service/blob/1.0.0/src/main/java/net/devaction/kafka/transferswebsocketsservice/localstores/LocalStoresManagerImpl.java) to retrieve the latest data associated with a given key (id)
* A [custom local store](https://github.com/VictorGil/transfers_websockets_service/blob/1.0.0/src/main/java/net/devaction/kafka/transferswebsocketsservice/transferscustomstore/TransfersStoreImpl.java) implemented using a simple Map to store the list of transactions for a given account.
* Two dispatchers which keep track of what WebSockets sessions (i.e., frontend clients) are registered to receive live [balance updates](https://github.com/VictorGil/transfers_websockets_service/blob/1.0.0/src/main/java/net/devaction/kafka/transferswebsocketsservice/processor/dispatcher/BalanceUpdatesDispatcherImpl.java) or live new [transfers data](https://github.com/VictorGil/transfers_websockets_service/blob/1.0.0/src/main/java/net/devaction/kafka/transferswebsocketsservice/processor/dispatcher/TransferDataDispatcherImpl.java) related to which account, and then dispatch the updates accordingly.

And these are the main components of the [**Angular frontend**](https://github.com/VictorGil/transfers_frontend):
* A [WebSockets service](https://github.com/VictorGil/transfers_frontend/blob/1.0.0/src/app/websockets.service.ts) which handles the connection lifecycle and dispatches the received messages to the corresponding `RxJS Subject`. Please note that different types of JSON messages (requests, responses and updates) flow through the only WebSockets connection.
* A [form](https://github.com/VictorGil/transfers_frontend/blob/1.0.0/src/app/account-balance-form/account-balance-form.component.ts) which passes the user input (i.e., the id of the chosen account) to the WebSockets service so it can be sent to the remote server.
* An Angular [component](https://github.com/VictorGil/transfers_frontend/blob/1.0.0/src/app/display-transfers/display-transfers.component.ts) to display the account balance which gets asynchronously notified of balance changes (updates) through an `RxJS Observer` which is subscribed to the corresponding `RxJS Subject` in the previously mentioned WebSockets service, and then re-renders the value accordingly.
* Another Angular [component](https://github.com/VictorGil/transfers_frontend/blob/1.0.0/src/app/display-transfers/display-transfers.component.ts) which similarly as the previous one, gets asynchronously notified of any new transaction related to the selected account and adds it to the list of displayed transaction data.

<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/cdoxdf5u9w1zoaypt36v.png" 
   alt="Image depicting the PoC application components"/>
  <figcaption>PoC application components</figcaption>
</figure>

####See it in action
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/133n4rnrkr2jph72tgy7.gif" 
   alt="GIF depicting the Web UI in action"/>
  <figcaption>Web UI in action</figcaption>
</figure>
Check out this [Youtube video](https://youtu.be/6b07L7floKE) for a demo, where a [test process](https://github.com/VictorGil/transfers_recording_service/blob/1.1.0/src/test/java/net/devaction/kafka/transfersrecordingservice/randomtransfersproducer/RandomTransferProducer.java) which continuously generates Kafka messages representing random money transfers is used to feed the application.
And on the Web UI the user can see how the transfers pop up as they happen and the balance of the related account changes accordingly, all in real time.
{% youtube 6b07L7floKE %}

###Final Thoughts
HTTP protocol has had a huge success, it made possible the WWW as we know it today.
It has been so successful that it has spread to the backend (RESTful services and open APIs) where it has been the king for more than a decade already.
However, technology evolves, paradigms come and go and for some use cases other tools and designs may be a better choice.
I do not know how software applications will look like in the future, all I can do is guess.
_Event-driven microservices_ look very powerful and implementing them with Kafka and adding WebSockets to the mix seems promising.
In fact, some companies are able to see beyond REST APIs and are starting to offer WebSockets APIs to their clients for faster streaming access to data ([example](https://blog.kraken.com/post/2892/kraken-launches-websockets-private-api)).
And there are other alternative ways to implement event-driven microservices, for example, recently I learnt about [Uber Cadence](https://github.com/uber/cadence) but that's for a future post :relaxed: