I'm using server-side events (SSE) in Java Spring. Whenever a new client subscribes to the events service I execute the following code at the REST controller:
SseEmitter emitter = new SseEmitter(-1L);
emitter.onCompletion(() -> {
logger.debug(TAG + "Emitter completed.");
emitters.remove(emitter);
});
return emitter;
Then, whenever an event needs to be notified to the clients I execute:
for (ResponseBodyEmitter emitter: emitters) {
emitter.send("Message #1");
}
The problem is that when one of the clients reloads the browser, the emitter does not get completed (as I expected), and I get a broken pipe exception when calling the code above. Only after this exception is triggered I see the emitter being completed.
Is there a way to solve this problem?
When the browser reloads, it will establish a new EventSource to your server, right? Your problem is with the old one, which has no client endpoint anymore.
I suggest you try to detect that it is the same client connecting, and then explicitly call complete on the old emitter.
In my case I can detect this based on a token which the EventSource passes in as a URL parameter. When I hook the newly created emitter to a "user object", I make sure to complete the previous emitter before assigning the new to the user field variable.
From your code, it seems you have a list or set of emitters. Can you maybe make it a map instead, where you have some client identity as the key, and the emitter as the value?
I can't tell you exactly what piece of information to use as a client identity, since it all depends on your application. In my case it is a JWT token, but you could perhaps simply create a client numbering scheme...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With