SERVER-SIDE PUSH IN SPRING BOOT AND ANGULAR

Mohit Kaushal
3 min readOct 21, 2022

In this tutorial, we’ll see how we can implement Server-side push-based API in spring boot.

This could be implemented using SSE (Server-sent Event), HTTP standards allow a web application to handle a unidirectional events stream and receive every event pushed by the server.

How to Implement it in Spring boot?

Step 1: We have to register subscriptions for users through which we can send events to their particular subscriptions.

List<Map<String, Object>> sseEmitterList = new CopyOnWriteArrayList<>();

We can create a list sseEmitterList to store subscriptions of multiple users.

Step 2: Now, we have to create a subscription API.

@GetMapping(value = "subscribe")
public SseEmitter subscribe(@RequestParam String userIP) {
// Create Object of SseEmitter which lives till 48 * 60 * 60000 milliseconds
SseEmitter sseEmitter = new SseEmitter((long) (48 * 60 * 60000));
try {
//send init event sseEmitter.send(SseEmitter.event().name("INIT"));
} catch (IOException e) {
e.printStackTrace();
}
Map<String, Object> userEmitter = new HashMap<>();
userEmitter.put("ip_address", userIP);
userEmitter.put("emitter", sseEmitter);
sseEmitter.onCompletion(() -> this.sseEmitterList.remove(userEmitter));
sseEmitter.onTimeout(() -> this.sseEmitterList.remove(userEmitter));
//Add emitter object to Emitter list
this.sseEmitterList.add(userEmitter);
return sseEmitter;
}

We can customize the duration till the subscription is valid by passing milliseconds like(48 * 60 * 60000).

Step 3: Create Post API to publish events to subscriptions.

@PostMapping("dispatch-event")
public void dispatchEventToClients(@RequestParam String ipAddress, @RequestParam String event, @RequestBody Map<String, Object> reqbody) {
//iterate emitterList here
for (Map<String, Object> sseEmitter : this.sseEmitterList) {
try {
if (sseEmitter.get("ip_address").equals(ipAddress)) {
//Get required emitter according to IP Address SseEmitter emitter = (SseEmitter) sseEmitter.get("emitter");
if(emitter != null){
//Dispatch Event to subscription emitter.send(SseEmitter.event().name(event).data(reqbody));
}
}
} catch (IOException e) {
//Remove emitter
this.sseEmitterList.remove(sseEmitter);
}
}
}

Step 4: Now to push the event to subscriptions we need to call our POST API with the required parameters.

ipAddress: The IP Address same as we use to create subscriptions for users in subscription API.

event: This is a title for the event which is pushing to subscription.

reqbody: Data which is pushed to subscription.

That’s all for the Spring boot side.

Complete Code…

public class UserSubscriptionController {

List<Map<String, Object>> sseEmitterList = new CopyOnWriteArrayList<>();

@GetMapping(value = "subscribe")
public SseEmitter subscribe(@RequestParam String userIP) {
SseEmitter sseEmitter = new SseEmitter((long) (48 * 60 * 60000));
try {
sseEmitter.send(SseEmitter.event().name("INIT"));
} catch (IOException e) {
e.printStackTrace();
}
Map<String, Object> userEmitter = new HashMap<>();
userEmitter.put("ip_address", userIP);
userEmitter.put("emitter", sseEmitter);
sseEmitter.onCompletion(() -> this.sseEmitterList.remove(userEmitter));
sseEmitter.onTimeout(() -> this.sseEmitterList.remove(userEmitter));
this.sseEmitterList.add(userEmitter);
return sseEmitter;
}

@PostMapping("dispatch-event")
public void dispatchEventToClients(@RequestParam String ipAddress, @RequestParam String event, @RequestBody Map<String, Object> reqbody) {
for (Map<String, Object> sseEmitter : this.sseEmitterList) {
try {
if (sseEmitter.get("ip_address").equals(userId)) {
SseEmitter emitter = (SseEmitter) sseEmitter.get("emitter");
if(emitter != null){
emitter.send(SseEmitter.event().name(event).data(reqbody));
}
}
} catch (IOException e) {
this.sseEmitterList.remove(sseEmitter);
}
}
}
}

How to use a subscription in Angular?

Step 1: Create a new subscription using IP Address and Subscription API.

this.eventSource = new EventSource(
environment.apiUrl +
'/subscribe?&userIP=' + this.ipAddress
);

Step 2: Use this.eventSource Object to catch all pushed events.

this.eventSource.addEventListener(event_title_to_listen,(e) => {
console.log(e);
});

Now, you will get all server-side pushed events in your console.

Complete Code…

import { Component } from '@angular/core';@Component({
selector: 'app-main-container',
templateUrl: './main-container.component.html',
styleUrls: ['./main-container.component.scss'],
})
export class MainContainerComponent {
eventSource: EventSource;

constructor(
) {
this.createSubscription()
}

createSubscription(){
this.eventSource = new EventSource(
environment.apiUrl +
'/subscribe?&userIP=' + this.ipAddress
);
this.subscribeEvents();
}

subscribeEvents(){
this.eventSource.addEventListener(event_title_to_listen, (e)=>
{
console.log(e);
});
}
}

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Mohit Kaushal
Mohit Kaushal

Written by Mohit Kaushal

Hi, I’m Mohit Kaushal currently working as a software engineer and willing to make some changes by sharing knowledge with persons having the same interests.

No responses yet

Write a response