SERVER-SIDE PUSH IN SPRING BOOT AND ANGULAR
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);
});
}
}