- What you’ll learn
- Additional prerequisites
- Getting started
- Setting up SSE in the bff service
- Configuring the Kafka connector for the bff service
- Configuring the frontend service to subscribe to and consume events
- Building and running the application
- Tearing down the environment
- Great work! You’re done!
- Related Links
- Guide Attribution
Streaming updates to a client using Server-Sent Events
Learn how to stream updates from a MicroProfile Reactive Messaging service to a front-end client by using Server-Sent Events (SSE).
What you’ll learn
You will learn how to stream messages from a MicroProfile Reactive Messaging service to a front-end client by using Server-Sent Events (SSE).
MicroProfile Reactive Messaging provides an easy way for Java services to send requests to other Java services, and asynchronously receive and process the responses as a stream of events. SSE provides a framework to stream the data in these events to a browser client.
What is SSE?
Server-Sent Events is an API that allows clients to subscribe to a stream of events that is pushed from a server. First, the client makes a connection with the server over HTTP. The server continuously pushes events to the client as long as the connection persists. SSE differs from traditional HTTP requests, which use one request for one response. SSE also differs from Web Sockets in that SSE is unidirectional from the server to the client, and Web Sockets allow for bidirectional communication.
For example, an application that provides real-time stock quotes might use SSE to push price updates from the server to the browser as soon as the server receives them. Such an application wouldn’t need Web Sockets because the data travels in only one direction, and polling the server by using HTTP requests wouldn’t provide real-time updates.
The application that you will build in this guide consists of a
frontend service, a
bff (backend for frontend) service, and three instances of a
system service. The
system services periodically publish messages that contain their hostname and current system load. The
bff service receives the messages from the
frontend service. This client uses the events to update a table in the UI that displays each system’s hostname and its periodically updating load. The following diagram depicts the application that is used in this guide:
In this guide, you will set up the
bff service by creating an endpoint that clients can use to subscribe to events. You will also enable the service to read from the reactive messaging channel and push the contents to subscribers via SSE. After that, you will configure the Kafka connectors to allow the
bff service to receive messages from the
system services. Finally, you will configure the client in the
frontend service to subscribe to these events, consume them, and display them in the UI.
To learn more about the reactive Java services that are used in this guide, check out the Creating reactive Java microservices guide.
The fastest way to work through this guide is to clone the Git repository and use the projects that are provided inside:
git clone https://github.com/openliberty/guide-reactive-messaging-sse.git cd guide-reactive-messaging-sse
start directory contains the starting project that you will build upon.
finish directory contains the finished project that you will build.
Setting up SSE in the bff service
In this section, you will create a REST API for SSE in the
bff service. When a client makes a request to this endpoint, the initial connection between the client and server is established and the client is subscribed to receive events that are pushed from the server. Later in this guide, the client in the
frontend service uses this endpoint to subscribe to the events that are pushed from the
Additionally, you will enable the
bff service to read messages from the incoming stream and push the contents as events to subscribers via SSE.
Navigate to the
start directory to begin.
Create the BFFResource class.
Creating the SSE API endpoint
subscribeToSystem() method allows clients to subscribe to events via an HTTP
GET request to the
/bff/sse/ endpoint. The
@Produces(MediaType.SERVER_SENT_EVENTS) annotation sets the
Content-Type in the response header to
text/event-stream. This content type indicates that client requests that are made to this endpoint are to receive Server-Sent Events. Additionally, the method parameters take in an instance of the
SseEventSink class and the
Sse class, both of which are injected using the
@Context annotation. First, the method checks if the
broadcaster instance variables are assigned. If these variables aren’t assigned, the
sse variable is obtained from the
@Context injection and the
broadcaster variable is obtained by using the
Sse.newBroadcaster() method. Then, the
register() method is called to register the
SseEventSink instance to the
SseBroadcaster instance to subscribe to events.
Reading from the reactive messaging channel
getSystemLoadMessage() method receives the message that contains the hostname and the average system load. The
@Incoming("systemLoad") annotation indicates that the method retrieves the message by connecting to the
systemLoad channel in Kafka, which you configure in the next section.
Each time a message is received, the
getSystemLoadMessage() method is called, and the hostname and system load contained in that message are broadcasted in an event to all subscribers.
Broadcasting events is handled in the
broadcastData() method. First, it checks whether the
broadcaster value is
null. There must be at least one subscriber or there’s no client to send the event to. If the
broadcaster value is specified, the
OutboundSseEvent interface is created by using the
Sse.newEventBuilder() method, where the
name of the event, the
data it contains, and the
mediaType are set. The
OutboundSseEvent interface is then broadcasted, or sent to all registered sinks, by invoking the
You just set up an endpoint in the
bff service that the client in the
frontend service can use to subscribe to events. You also enabled the service to read from the reactive messaging channel and broadcast the information as events to subscribers via SSE.
Configuring the Kafka connector for the bff service
system service is provided for you in the
start/system directory. The
system service is the producer of the messages that are published to the Kafka messaging system. The periodically published messages contain the system’s hostname and a calculation of the average system load (its CPU usage) for the last minute.
Configure the Kafka connector in the
bff service to receive the messages from the
Create the microprofile-config.properties file.
bff service uses an incoming connector to receive messages through the
systemLoad channel. The messages are then published by the
system service to the
system.load topic in the Kafka message broker. The
value.deserializer properties define how to deserialize the messages. The
group.id property defines a unique name for the consumer group. All of these properties are required by the Apache Kafka Consumer Configs documentation.
Configuring the frontend service to subscribe to and consume events
In this section, you will configure the client in the
frontend service to subscribe to events and display their contents in a table in the UI.
The front-end UI is a table where each row contains the hostname and load of one of the three
system services. The HTML and styling for the UI is provided for you but you must populate the table with information that is received from the Server-Sent Events.
Create the index.js file.
Subscribing to SSE
initSSE() method is called when the page first loads. This method subscribes the client to the SSE by creating a new instance of the
EventSource interface and specifying the
http://localhost:9084/bff/sse URL in the parameters. The
EventSource interface makes a
GET request to this endpoint with a request header of
Accept: text/event-stream to connect to the server.
Because this request comes from
localhost:9080 and is made to
localhost:9084, it must follow the Cross-Origin Resource Sharing (CORS) specification to avoid being blocked by the browser. To enable CORS for the client, set the
withCredentials configuration element to true in the parameters of the
EventSource interface. CORS is already enabled for you in the
bff service. To learn more about CORS, check out the CORS guide.
Consuming the SSE
EventSource.addEventListener() method is called to add an event listener. This event listener listens for events with the name of
systemLoadHandler() function is set as the handler function, and each time an event is received, this function is called. The
Building and running the application
To build the application, navigate to the
start directory and run the following Maven
package goals from the command line:
mvn -pl models install mvn package
Run the following command to download or update to the latest Open Liberty Docker image:
docker pull openliberty/open-liberty:kernel-java8-openj9-ubi
Run the following commands to containerize the
docker build -t frontend:1.0-SNAPSHOT frontend/. docker build -t bff:1.0-SNAPSHOT bff/. docker build -t system:1.0-SNAPSHOT system/.
Next, use the following
startContainers.sh script to start the application in Docker containers:
This script creates a network for the containers to communicate with each other. It also creates containers for Kafka, Zookeeper, the
frontend service, the
bff service , and three instances of the
Once your application is up and running, open your browser and check out your service by visiting http://localhost:9080. The application might take some time to get ready. The latest version of most modern web browsers supports Server-Sent Events. The exception is Internet Explorer, which does not support SSE.
When you visit the URL, look for a table similar to the following example:
The table contains three rows, one for each of the running
system containers. If you can see the loads updating, you know that your
bff service is successfully receiving messages and broadcasting them as SSE to the client in the
Tearing down the environment
Run the following script to stop the application:
Great work! You’re done!
You developed an application that subscribes to Server-Sent Events by using MicroProfile Reactive Messaging, Open Liberty, and Kafka.
Streaming updates to a client using Server-Sent Events by Open Liberty is licensed under CC BY-ND 4.0
Nice work! Where to next?
What did you think of this guide?
Thank you for your feedback!
Thank you for your feedback!
Would you like to open an issue in GitHub?Yes
What could make this guide better?
Raise an issue to share feedback
Create a pull request to contribute to this guide