I am trying to build a notification system where-in my back-end, upon receiving a webhook from a third party, will notify the front-end of a particular status, and have decided to go ahead with the Server Sent Events implementation in Spring Boot. Having gone through 10s of implementations of the same, I found that the common way of doing it is:
- having your client hit a subscription API on your back-end
- Create an object of SseEmitter class and store it in an in-memory HashMap or ArrayList
- Fetch the events stored in your memory, to send notification when the desired event occurs
However, my issue is that I can't store these SseEmitter Objects in-memory, in a production grade code. I have tried serializing the object, but upon deserialization a new object of SseEmitter is created and the connection to client is lost. How do I do this gracefully?
@RestController
public class EventController {
Map<String, SseEmitter> sseEmitters = new ConcurrentHashMap<>();
@Autowired
SerializerUtils serializerUtils;
String sseEmitterSerialized = null;
@CrossOrigin
@GetMapping(value="/subscribe", consumes = MediaType.ALL_VALUE)
public SseEmitter subscribe(@RequestParam(value = "tokenId") String tokenId) throws IOException {
DefaultSseEmitter sseEmitter = new DefaultSseEmitter(Long.MAX_VALUE);
sseEmitter.send(SseEmitter.event().name("latestEvent").data("INITIALIZED"));
sseEmitter.onCompletion(() -> sseEmitters.remove(sseEmitter));
sseEmitters.put(tokenId, sseEmitter);
return sseEmitter;
}
@CrossOrigin
@PostMapping(value="/dispatchEvent", produces = MediaType.ALL_VALUE)
public void dispatchToClients(@RequestParam (value = "freshEvent") String freshEvent, @RequestParam(value = "tokenId") String tokenId)
throws IOException, ClassNotFoundException {
sseEmitters.get(tokenId).send(SseEmitter.event().name("latestEvent").data(freshEvent));
}
I have tried serializing and conversion to JSON. None of that stuff works.