Realtime web notification Using Apache Kafka, Spring WebSocket, and Angular

In this post, I’ll explain to you how to send notifications to the web client without refreshing the web browser.

We are going to create a simple real-time web application that demonstrates how to use Kafka as a message broker with Spring Boot as the backend and Angular 9 on the front end.

Setup Kafka instance

Many installation methods are recommended in official documents. Here we are using docker compose to easily setup a kafka instance.

version: '3.7'
services:
zoo1:
image: zookeeper:3.4.9
hostname: zoo1
ports:
- "2181:2181"
environment:
ZOO_MY_ID: 1
ZOO_PORT: 2181
ZOO_SERVERS: server.1=zoo1:2888:3888
kafka1:
image: confluentinc/cp-kafka:5.5.1
hostname: kafka1
ports:
- "9092:9092"
- "29092:29092"
environment:
KAFKA_ADVERTISED_LISTENERS: LISTENER_DOCKER_INTERNAL://127.0.0.1:29092,LISTENER_DOCKER_EXTERNAL://127.0.0.1:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: LISTENER_DOCKER_INTERNAL:PLAINTEXT,LISTENER_DOCKER_EXTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: LISTENER_DOCKER_INTERNAL
KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181"
KAFKA_CREATE_TOPICS: notification:1:1:compact
KAFKA_BROKER_ID: 1
KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
depends_on:
- zoo1

Start the zookeeper and Kafka instance with docker-compose up -d

Backend side code

Create 2 Spring Boot projects (producer Kafka and consumer Kafka). You need to import the Kafka dependencies into your pom.xml file.

<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
KafkaProducerConfiguration.java

The next step is to create an endpoint and a class of service to send the messages to the Kafka topic.

BrokerProducerService.java

Similar to KafkaProducerConfiguration.java we need to have a Consumer Config to enable the consumer to find the broker. For the consumer project, we have two important configuration files (KafkaConsumerConfiguration.java and WebSocketConfig.java).

Step 1: First, we need to add the WebSocket dependency.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

Step 2. Then, we can configure Spring to enable WebSocket and STOMP messaging

WebSocketConfig.java

WebSocketConfig is annotated with @Configuration to indicate that it is a Spring configuration class. It is also annotated with @EnableWebSocketMessageBroker. As its name suggests, @EnableWebSocketMessageBroker enables WebSocket message handling, backed by a message broker.

The configureMessageBroker() method implements the default method in WebSocketMessageBrokerConfigurer to configure the message broker. It starts by calling enableSimpleBroker() to enable a simple memory-based message broker to carry the greeting messages back to the client on destinations prefixed with /topic.

It also designates the /app prefix for messages that are bound for methods annotated with @MessageMapping. This prefix will be used to define all the message mappings.

The registerStompEndpoints() method registers the /ws-notification endpoint, enabling SockJS fallback options so that alternate transports can be used if WebSocket is unavailable. The SockJS client will attempt to connect to /ws-notification and use the best available transport (websocket, xhr-streaming, xhr-polling, and so on).

We have handled the CORS issue with the following code:

...setAllowedOrigins("http://localhost:4200").withSockJS();
In production you can replace http://localhost:4200 with .setAllowedOrigins(*) or your domain name.

Now we need to create the Front-End part of the application to start the socket communication.

Frontend Development side with Angular

ng new web-notification
cd web-notification

Install dependencies

  • npm install — save ng-push
  • npm install stompjs
  • npm install sockjs-client

Let’s create the websocket.service.ts service file

websocket.service.ts

Launch the front-end application and backend services

ng serve

When the application is launched, the browser asks the user to allow confirmation of push notifications.

Final Result

http://localhost:8082/swagger-ui.html

Producer swagger ui
Frontend view

That’s it.

Thank you for taking the time to read this. The source code can be found here

Related Posts