{"id":26197,"date":"2024-01-15T05:00:00","date_gmt":"2024-01-15T04:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=26197"},"modified":"2024-07-22T14:18:03","modified_gmt":"2024-07-22T12:18:03","slug":"server-side-events-implementation-and-highlights","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/server-side-events-implementation-and-highlights\/","title":{"rendered":"Server Side Events \u2013 implementation and highlights"},"content":{"rendered":"\n<p>I want to present the Server Side Events technology implemented using Spring Boot and Angular 16. The article goes with:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>brief introduction to SSE,<\/li>\n\n\n\n<li>implementation of SSE with a Spring Boot (SSE Emitter),<\/li>\n\n\n\n<li>implementation of SSE with Angular 16,<\/li>\n\n\n\n<li>description of what is going on under the hood,<\/li>\n\n\n\n<li>compared with other similar technologies,<\/li>\n\n\n\n<li>use cases where SSE can be used.<\/li>\n<\/ul>\n\n\n\n<p>Enjoy!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>A brief introduction to SSE<\/strong><\/h2>\n\n\n\n<p>Server Side Events is a web technology that enables a unidirectional, real-time communication channel between a web server and a client, typically a web browser. In a nutshell \u2013 you create a long-lived HTTP connection between a server and a browser, and then the server can send asynchronous messages to the browser without user involvement. This is useful for applications like stock market updates, social media feeds, and collaborative tools where real-time updates are crucial.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Why should I use SSE?<\/strong><\/h2>\n\n\n\n<p>SSE has gained popularity for several compelling reasons:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Efficiency<\/strong> \u2013 SSE operates over a single HTTP connection without requiring multiple requests (as in short or long polling). This efficiency reduces server load and network overhead.<\/li>\n\n\n\n<li><strong>Simplicity <\/strong>\u2013 implementing SSE on both the server and client sides is straightforward, as it leverages familiar web technologies like HTML, JavaScript, and standard HTTP protocols. There is no need for third-party libraries or complex configurations! All major web browsers, including Chrome, Firefox, Safari, Edge, and Opera, support SSE. IE is the only major browser that doesn\u2019t support SSE.<\/li>\n\n\n\n<li><strong>Real-Time Updates <\/strong>\u2013 SSE enables real-time updates from the server to the client, allowing instant notifications of events or changes in state.<\/li>\n\n\n\n<li><strong>Fallback Mechanism<\/strong> \u2013 SSE gracefully handles scenarios where a client&#8217;s browser lacks support for SSE. It automatically falls back to other techniques like long polling, ensuring that your application remains functional across various environments.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Advantages and limitations of SSE<\/strong><\/h2>\n\n\n\n<p>Among the advantages of the solution are:<a><\/a><strong><\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Ease of Implementation <\/strong>\u2013<strong> <\/strong>Implementing SSE Events for the first time took me around 3-4 hours. It doesn&#8217;t require complex libraries or additional technologies, simplifying the creation of streaming applications.<\/li>\n\n\n\n<li><strong>Low Network Overhead <\/strong>\u2013<strong> <\/strong>SSE relies on a single, persistent connection to the server, enabling real-time data transmission with a minimal network overhead. You don&#8217;t need to open and close multiple connections, positively impacting application performance.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>No need to constantly request the server <\/strong>\u2013<strong> <\/strong>once a connection is established as a server-client, you don\u2019t need to constantly request the server if some business status has been changed. When the server changes its status, it can directly send you the event with details of what has changed.<\/li>\n\n\n\n<li><strong>Error Handling <\/strong>\u2013<strong> <\/strong>backend SSE implementation and frontend EventSource provide an API that helps us handle unforeseen situations easily.<strong><\/strong><\/li>\n<\/ul>\n\n\n\n<p>Disadvantages of the solution include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Limit of maximum open connections <\/strong>\u2013<strong> <\/strong>when not used over HTTP\/2, SSE suffers from a limitation to the maximum number of open connections, which can be especially painful when opening multiple tabs, as the limit is per browser and is set to a very low number (6).<br>When used over HTTP\/2 protocol, the maximum number of simultaneous HTTP streams depends on the server and client configuration but, by default, is set to 100.<\/li>\n\n\n\n<li><strong>Unidirectional Communication <\/strong>\u2013<strong> <\/strong>SSE technology enables communication only from the server to the client. It creates limitations, so it may not be the best choice for more complex, interactive applications where bidirectional communication or frequent client-server interactions are needed. On the other hand, unidirectional communication is safer, as the stream of events goes from the server to the user.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Implementing the Spring Boot Server<\/strong><\/h2>\n\n\n\n<p>To present the capabilities of Server Side Events technology, I\u2019ve created a simple app that monitors business processes. <\/p>\n\n\n\n<p>The business logic of the backend system is simple. We have defined 3 three paths:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Happy path,<\/li>\n\n\n\n<li>Warning path,<\/li>\n\n\n\n<li>Error path.<\/li>\n<\/ul>\n\n\n\n<p>Whenever a monitoring request is made, the system randomly picks and follows one of the paths. Simulates a sample business process that sends status events whenever its state changes. <\/p>\n\n\n\n<p>The working system is below:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"800\" height=\"425\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/image1.gif\" alt=\"Business Process Monitoring\" class=\"wp-image-26265\"\/><figcaption class=\"wp-element-caption\">Fig. 1 Business Pocess Monitoring<\/figcaption><\/figure>\n\n\n\n<p>Application structure:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz2-1.png\"><img decoding=\"async\" width=\"474\" height=\"532\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz2-1.png\" alt=\"Application structure:\" class=\"wp-image-26202\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz2-1.png 474w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz2-1-267x300.png 267w\" sizes=\"(max-width: 474px) 100vw, 474px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 2 Application structure<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Controller handling SSE<\/strong><\/h3>\n\n\n\n<p>Plain RestController exposes SseEmitter on GET request. SseEmitter is a class of Spring MVC. It will be exposed over HTTP with a content type as text\/event stream. Thus, a browser can request and handle it as an EventSource.<\/p>\n\n\n\n<p>When a request reaches this method, the SSE Event Processor service creates a new SSEEmitter and starts an asynchronous monitoring process.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz3-1.png\"><img decoding=\"async\" width=\"602\" height=\"341\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz3-1.png\" alt=\"code\" class=\"wp-image-26205\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz3-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz3-1-300x170.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Processor handling Server Side Events<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz4-1.png\"><img decoding=\"async\" width=\"602\" height=\"243\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz4-1.png\" alt=\"code\" class=\"wp-image-26207\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz4-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz4-1-300x121.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>This service keeps all created emitters. During the creation process, a new SseEmitter object is created and then stored in a Map.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz5-1.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz5-1.png\" alt=\"code\" class=\"wp-image-26209\" width=\"606\" height=\"275\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz5-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz5-1-300x136.png 300w\" sizes=\"(max-width: 606px) 100vw, 606px\" \/><\/a><\/figure>\n\n\n\n<p>During sending an event, the SseEmitter object is retrieved from the map, and the send method is invoked with an event message. Object SseEventModel is a custom model created for this application.<br><br>If the client aborts the connection and the server wants to send a new event \u2013 ClientAbortException is called.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz6-1.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz6-1.png\" alt=\"code\" class=\"wp-image-26211\" width=\"602\" height=\"421\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz6-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz6-1-300x210.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>The process ends when the termination event is sent, and the connection is completed.<\/p>\n\n\n\n<p>For that, I\u2019ve used a message with the flag <em>finished<\/em> set to true \u2013 the client then can handle the connection appropriately.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Business Process Monitoring<\/strong><\/h3>\n\n\n\n<p>This service simulates an ongoing process that is monitored, and the events are sent.<\/p>\n\n\n\n<p>We have defined 3 constant paths:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Happy path,<\/li>\n\n\n\n<li>No data,<\/li>\n\n\n\n<li>Error Path.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz7-1.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz7-1.png\" alt=\"code\" class=\"wp-image-26214\" width=\"602\" height=\"324\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz7-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz7-1-300x161.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>Simulation of the monitoring process is just picking randomly a path defined above and waiting after every notification.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz8-1.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz8-1.png\" alt=\"code\" class=\"wp-image-26217\" width=\"608\" height=\"400\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz8-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz8-1-300x197.png 300w\" sizes=\"(max-width: 608px) 100vw, 608px\" \/><\/a><\/figure>\n\n\n\n<p>Sending an event is done by calling SseEventProcessor.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz9-1.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz9-1.png\" alt=\"code\" class=\"wp-image-26220\" width=\"602\" height=\"177\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz9-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz9-1-300x88.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Implementing the Angular Client<\/strong><\/h2>\n\n\n\n<p>We can obtain an EventSource exposed by the server by simply calling the constructor of the EventSource class. Every modern browser supports this class.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie-1.jpg\"><img decoding=\"async\" width=\"1024\" height=\"366\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie-1-1024x366.jpg\" alt=\"Server-sent events\" class=\"wp-image-26269\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie-1-1024x366.jpg 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie-1-300x107.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie-1-768x275.jpg 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie-1.jpg 1277w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 3 Server-sent events<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz11-1.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz11-1.png\" alt=\"code\" class=\"wp-image-26224\" width=\"594\" height=\"390\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz11-1.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz11-1-300x197.png 300w\" sizes=\"(max-width: 594px) 100vw, 594px\" \/><\/a><\/figure>\n\n\n\n<p>We can define three types of handlers for an event source:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><em>onmessage <\/em><\/strong>\u2013 function will be invoked upon the message&#8217;s arrival,<\/li>\n\n\n\n<li><strong><em>onerror <\/em><\/strong>\u2013 will be invoked when the error occurs,<\/li>\n\n\n\n<li><strong><em>onopen <\/em><\/strong>\u2013 will be invoked when the connection will be opened.<\/li>\n<\/ul>\n\n\n\n<p>Let&#8217;s break down the piece of code responsible for receiving the message:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz12.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz12.png\" alt=\"code\" class=\"wp-image-26227\" width=\"602\" height=\"249\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz12.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz12-300x124.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>When the event comes, we extract its data, only text in JSON format. We\u2019re closing the connection when the finished event is sent. If not, we\u2019re using messageSubject$ to push the received message. <\/p>\n\n\n\n<p>MessageSubject$ is an Angular\u2019s Subject, which can then be subscribed to display elements on the screen. <\/p>\n\n\n\n<p>ProcessMonitoringService exposes 3 public methods:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>startMonitoring,<\/li>\n\n\n\n<li>getMessageObservable \u2013 responsible to return messageSubject$ as an observable,<\/li>\n\n\n\n<li>stopMonitoring.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz13.png\"><img decoding=\"async\" width=\"602\" height=\"421\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz13.png\" alt=\"code\" class=\"wp-image-26229\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz13.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz13-300x210.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>I\u2019ve assumed that the connection will be open for different users. For demo purposes, I\u2019ve generated a random user ID to pass as a parameter in creating a Server Side Event Connection request. Then, we can subscribe to the messages in the component and display them to the user. <\/p>\n\n\n\n<p>The component handling the view simply keeps processes as an array, which is updated every time a message is received.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz14.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz14.png\" alt=\"code\" class=\"wp-image-26232\" width=\"602\" height=\"505\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz14.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz14-300x252.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>We employ the NgZone service to automatically update the component view on the arrival of a message. Without this, we would have to rely on user interaction to display the message correctly. Full code for the frontend and the backend application <a href=\"https:\/\/github.com\/IncogVito\/Articles\/tree\/main\/Server%20Side%20Events\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >is available on GitHub<\/a>. &nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Under the hood<\/strong><\/h2>\n\n\n\n<p>But how does it work under the hood?<\/p>\n\n\n\n<p>At the beginning, the browser is opening the connection:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie1.jpg\"><img decoding=\"async\" width=\"1024\" height=\"606\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie1-1024x606.jpg\" alt=\"The connection\" class=\"wp-image-26274\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie1-1024x606.jpg 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie1-300x177.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie1-768x454.jpg 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie1.jpg 1214w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 4 The connection<\/figcaption><\/figure>\n\n\n\n<p>The diagram below illustrates the life cycle of&nbsp;an event source:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz16.png\"><img decoding=\"async\" width=\"491\" height=\"341\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz16.png\" alt=\"The life cycle of an event source\" class=\"wp-image-26236\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz16.png 491w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz16-300x208.png 300w\" sizes=\"(max-width: 491px) 100vw, 491px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 5 The life cycle of an event source<\/figcaption><\/figure>\n\n\n\n<p>The connection is kept open until the proper event completes the connection. <\/p>\n\n\n\n<p>In the browser, we\u2019re able to see incoming events:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie3.jpg\"><img decoding=\"async\" width=\"1024\" height=\"209\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie3-1024x209.jpg\" alt=\"Incoming events\" class=\"wp-image-26276\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie3-1024x209.jpg 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie3-300x61.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie3-768x157.jpg 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie3.jpg 1218w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 6 Incoming events<\/figcaption><\/figure>\n\n\n\n<p>We see that the last message has a finished flag set to true. This way, in the code, we\u2019re able to handle closing connections on the client side more gracefully:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz18.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz18.png\" alt=\"code\" class=\"wp-image-26241\" width=\"602\" height=\"443\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz18.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz18-300x221.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>But what happens if we lose the connection? Simulating that the server is down after successfully obtaining the connection, we can see that the browser, by default, automatically tries to reconnect to the source:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie4.jpg\"><img decoding=\"async\" width=\"1024\" height=\"147\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie4-1024x147.jpg\" alt=\"Automatically reconnection\" class=\"wp-image-26282\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie4-1024x147.jpg 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie4-300x43.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie4-768x111.jpg 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie4.jpg 1208w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 7 Automatically reconnection<\/figcaption><\/figure>\n\n\n\n<p>Disclaimer \u2013 this situation happens if we don\u2019t handle closing the connection in case of failure.<br>In my example of process monitoring, I\u2019ve handled this case by closing the connection in case of failure:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz20.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz20.png\" alt=\"code\" class=\"wp-image-26247\" width=\"602\" height=\"144\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz20.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz20-300x72.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>Nevertheless, the behavior of automatically reconnecting can be different among different types of browsers; thus, I recommend handling reconnecting with EventSource manually.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Security with EventSource<\/strong><\/h2>\n\n\n\n<p>EventSource mechanism enables us to provide a withCredentials flag into the constructor.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz21.png\"><img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz21.png\" alt=\"code\" class=\"wp-image-26250\" width=\"602\" height=\"43\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz21.png 602w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Obraz21-300x21.png 300w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/figure>\n\n\n\n<p>When withCredentials is true, the browser will include cookies and HTTP headers in SSE requests, such as the Authorization header. This enables user authentication and authorization on the server, similar to standard HTTP requests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Comparing SSE with other technologies<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Short Polling<\/strong><\/h3>\n\n\n\n<p>It involves clients making frequent, regular requests to the server for updates. These requests are usually quick and lightweight, making Short Polling a simple solution. However, it can lead to higher network and server resource consumption, as clients consistently ask for updates, even when no new data is available. This constant &#8220;polling&#8221; can be inefficient and strain the client and server unnecessarily.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Protocol<\/strong>: HTTP,<\/li>\n\n\n\n<li><strong>Connection type<\/strong>: frequent queries for updates,<\/li>\n\n\n\n<li><strong>Performance<\/strong>: excessive network traffic because the client needs to ask the server for updates.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Long Polling<\/strong><\/h3>\n\n\n\n<p>Long Polling is a variation of the polling method designed to mitigate some inefficiencies associated with Short Polling. With Long Polling, clients request the server, and the server holds the request open until new data is available or a timeout occurs. The server responds to the client&#8217;s request once data becomes available or the timeout is reached. This approach reduces the constant back-and-forth polling of Short Polling, but it might not be as efficient as more modern solutions like WebSockets or SSE.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Protocol<\/strong>: HTTP<strong>,<\/strong><\/li>\n\n\n\n<li><strong>Connection type:<\/strong> persistent client-server connection, the server delays response,<\/li>\n\n\n\n<li><strong>Performance<\/strong>: high resource usage on the server as well as on the client side due to frequently opening new connections.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>WebSockets<\/strong><\/h3>\n\n\n\n<p>WebSockets provide a more sophisticated and efficient means of real-time communication. They offer full-duplex, bidirectional communication, enabling both the client and server to send messages to each other at any time without the need for repeated requests. WebSockets are highly efficient, reducing network overhead and allowing for near-instant data transmission.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Protocol<\/strong>: WebSocket protocol,<\/li>\n\n\n\n<li><strong>Connection type:<\/strong> full-duplex connection,<\/li>\n\n\n\n<li><strong>Performance<\/strong>: highly efficient and fast without excessive delay or continuous server polling.<\/li>\n<\/ul>\n\n\n\n<p>Comparison of diagram:<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie5.jpg\"><img decoding=\"async\" width=\"1007\" height=\"334\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie5.jpg\" alt=\"Comparision SSE with other technologies\" class=\"wp-image-26286\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie5.jpg 1007w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie5-300x100.jpg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Przechwytywanie5-768x255.jpg 768w\" sizes=\"(max-width: 1007px) 100vw, 1007px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 8 Comparision SSE with other technologies<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Business scenarios where SSE can be used<\/strong><\/h2>\n\n\n\n<p>There&#8217;s a huge area where unidirectional communication between servers and clients can be used.<br>Here are some examples of how Server Side Events can be used.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Social Media Feeds \u2013 instantly deliver posts, comments, and notifications to users,<\/li>\n\n\n\n<li>Sports Updates and Scores \u2013 live notifications, up-to-date scores,<\/li>\n\n\n\n<li>Live updates for financial markets \u2013 providing real-time updates on stock prices and currency exchange rates,<\/li>\n\n\n\n<li>monitor system processes and provide the user with the actual state of the process.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>As you have seen, server-side events <strong>can be effectively used in vast business scenarios<\/strong>.<\/p>\n\n\n\n<p>I hope this article has shown you how to use SSE technology and introduced you to this type of communication. I hope this helps you handle use cases in your system more effectively!<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/IncogVito\/Articles\/tree\/main\/Server%20Side%20Events\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Full code is available on GitHub<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Sources<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Server-sent_events\/Using_server-sent_events\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Using server-sent events<\/a><\/li>\n<\/ul>\n\n\n\n<p>***<\/p>\n\n\n\n<p>You can also find another article by the author on our blog: <a href=\"https:\/\/sii.pl\/blog\/en\/ngxs-vs-ngrx-comprehensive-comparison-of-angular-redux-libraries\/\" target=\"_blank\" aria-label=\"NGXS vs NgRx \u2013 comprehensive comparison of Angular Redux libraries (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">NGXS vs NgRx \u2013 comprehensive comparison of Angular Redux libraries<\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;26197&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;7&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 7)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Server Side Events \u2013 implementation and highlights&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 7)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>I want to present the Server Side Events technology implemented using Spring Boot and Angular 16. The article goes with: &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/server-side-events-implementation-and-highlights\/\">Continued<\/a><\/p>\n","protected":false},"author":557,"featured_media":26260,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[2622,2127,1604,1590,1482],"class_list":["post-26197","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-digital-en","tag-server-side-events","tag-pros-and-cons","tag-tools","tag-solutions-en"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/12\/Server-Side-Events-\u2013-implementation-and-highlights.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/26197"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/557"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=26197"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/26197\/revisions"}],"predecessor-version":[{"id":26297,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/26197\/revisions\/26297"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/26260"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=26197"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=26197"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=26197"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}