Implementation of Server-Sent Events Using Spring Boot
Below is the step-by-step implementation of Server-Sent Events in Spring.
Step 1: Setting up a Spring Boot Project in Spring Initializer
Go to this link and create a Spring Boot project by pre-filling some information such as:
- Specify the project metadata:
- Group: Project group ID
- Artifact: Project’s artifact ID
- Name: Name of your project
- Choosing the appropriate version of Spring Boot.
- Select the language (Java)
- Adding necessary dependencies:
- Spring Reactive Web (for building reactive, non-blocking web applications).
- Spring boot actuator (for monitoring and managing web applications).
- Spring web (for building web applications).
- At last, click on GENERATE button.
- Download your Spring Boot project in zip format.
- Now extract the folder into your local machine.
Step 2: Adding Dependencies in pom.xml
All dependencies are specified in pom.xml file.
XML
<? xml version = "1.0" encoding = "UTF-8" ?> < project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion >4.0.0</ modelVersion > < parent > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-parent</ artifactId > < version >3.2.3</ version > < relativePath /> <!-- lookup parent from repository --> </ parent > < groupId >com.article</ groupId > < artifactId >server-sent-events-example</ artifactId > < version >0.0.1-SNAPSHOT</ version > < name >server-sent-events-example</ name > < description >Demo project for server sent events</ description > < properties > < java.version >17</ java.version > </ properties > < dependencies > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-actuator</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-web</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-webflux</ artifactId > </ dependency > < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > < dependency > < groupId >io.projectreactor</ groupId > < artifactId >reactor-test</ artifactId > < scope >test</ scope > </ dependency > </ dependencies > < build > < plugins > < plugin > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-maven-plugin</ artifactId > </ plugin > </ plugins > </ build > </ project > |
Step 3: Creating a Server-Sent Events Controller
Here is the ServerEventsController class.
Java
package com.article.spring; import org.springframework.http.MediaType; import org.springframework.http.codec.ServerSentEvent; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; @RestController @RequestMapping ( "/server-events" ) public class ServerEventsController { @GetMapping (produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<ServerSentEvent<String>>getEvents() throws IOException { // Read lines from a file Stream<String> lines=Files.lines(Path.of( "C:\\Users\\prade\\Downloads\\server-sent-events-example\\server-sent-events-example\\pom.xml" )); // Counter for event IDs AtomicInteger counter= new AtomicInteger( 1 ); // Convert lines to Server-Sent Events return Flux.fromStream(lines) // Filter out blank lines .filter(line -> !line.isBlank()) // Map each line to a Server-Sent Event .map(line -> ServerSentEvent.<String>builder() // Assign an ID to the event .id(String.valueOf(counter.getAndIncrement())) // Set the data of the event to the line content .data(line) // Set the event type .event( "lineEvent" ) // Set the retry duration .retry(Duration.ofMillis( 1000 )) // Build the Server-Sent Event .build()) // Introduce a delay between sending each event .delayElements(Duration.ofMillis( 300 )); } } |
The ServerEventsController is responsible for handling HTTP requests related to Server-Sent Events (SSE). It reads lines from a file and converts them into SSEs.
- Endpoint Mapping: The controller is mapped to “/server-events” endpoint which will handle requests made to this URL.
- Reading from file: It reads lines from a file specified by the file path.
- Event Creation: Each line from the file is converted into a Server-Sent Events (SSE) using a builder method. The ID is assigned sequentially using an “AtomicInteger” and the line content becomes the data of the event.
- Retry Duration: The Server-Sent Events are given a retry duration of 1 second.
- Streaming and Delay: The Server-Sent Events are streamed to clients with a delay of 300 milliseconds between each event.
Step 4: Run the Application.
To run the Spring Boot application, simply run this ServerSentEventsExampleApplication class .
Java
package com.article.spring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ServerSentEventsExampleApplication { public static void main(String[] args) { SpringApplication.run(ServerSentEventsExampleApplication. class , args); } } |
Output Using CURL:
In the terminal execute the following command,
curl http://localhost:8080/server-events -v
After executing the above command, we will see the below output in terminal.
Output Using Browser:
To see the Server-Sent Events in action, open browser and go to the following URL:
http://localhost:8080/server-events
After hitting the above link in browser, we will get the below output.
Server – Sent Events in Spring
When we design web applications, we generally have a client and a server model, where the client is always the initiator of the transaction or a request to the server. The server responds to these requests. However, in certain scenarios, there arises a need for the server to respond much more frequently or give additional information to the client. This requirement leads us to techniques such as long polling, WebSockets, and Server-Sent Events (SSE).
In this article, we are going to look at Server-Sent Events (SSE) using Spring Boot and how we can implement them.