WebFlux SSE (Server Send Event) — Real-Time Progress Tracking with WebFlux SSE and Quartz Jobs

Gayan Sanjeewa
4 min readJan 5, 2025

--

Live Example

Hi Folks! I’m Back Again !

After diving into Java 21 Virtual Threads vs Reactive Streams in my last article, I’m back with another fascinating subject that’s bound to pique your interest. This time, we’re going to explore something truly dynamic and interactive — Real-Time Progress Updates with WebFlux SSE and Quartz Jobs.

If you’ve ever worked on long-running tasks like file uploads, data processing, or report generation in web applications, you know the struggle of providing real-time feedback to users. Typically, users are left guessing about the progress of these tasks, resorting to refreshing the page or waiting indefinitely for updates. But what if there was a better way?

In this article, we’ll learn how to integrate Spring WebFlux’s Server-Sent Events (SSE) with Quartz Dynamic job scheduling to stream real-time progress updates directly to the client. Imagine sending dynamic progress bars, live status updates, and much more — all without the need for polling or manual page refreshes.

Understanding WebFlux SSE

WebFlux SSE is a reactive extension for sending server-sent events to the client over HTTP. It is built on top of the reactive framework in Spring WebFlux and allows the server to push updates to the client in a non-blocking and asynchronous manner. SSE is a great choice for applications where real-time updates are essential, such as live dashboards, progress bars, and notification systems.

Why Quartz Jobs?

Quartz is a powerful job scheduling library that provides advanced scheduling capabilities for Java applications. It can be used for running tasks periodically or executing them in the background. In our case, we want to track the progress of a Quartz job and send updates to a client as the job progresses.

The Problem

Suppose we have a long-running Quartz job, like a file processing task or a complex computation. The client, however, does not know the progress of this task until it is completed. WebFlux SSE can solve this problem by allowing the server to stream progress updates to the client.

To demonstrate this, I created a simple application with two endpoints:

  1. Start Job Endpoint: This endpoint dynamically starts a Quartz job.
  2. Progress Endpoint: This endpoint streams real-time progress updates of the Quartz job to the client using WebFlux SSE.

This endpoint creates and starts a Quartz job, returning the job ID in the response:

/api/v1/job/create
{
"id": 36,
"jobName": "my-job-36",
"jobProgress": 0,
"jobStatus": "IN-PROGRESS"
}

This endpoint streams the real-time progress of the job:

/api/v1/job/{jobId}/progress
id:45
event:progress-update
data:{"id":45,"jobName":null,"jobGroup":null,"jobDescription":null,"jobProgress":1.0,"jobStatus":"IN-PROGRESS"}
Live Example

Sample code is available in my GitHub
https://github.com/its-me-gayan/WebfluxSSEQuartzExample.git

Alternative Approaches: SSE, Flux, and WebSocket

While this article focuses on using WebFlux SSE with Quartz Jobs to provide real-time progress updates, it’s worth noting that there are multiple approaches to achieving similar functionality. Let’s explore how SSE, Flux, and WebSocket compare:

1. Server-Sent Events (SSE)

SSE is a natural choice for one-way, server-to-client updates. It works well for scenarios like real-time dashboards, progress tracking, and notifications. Its simplicity and built-in support in browsers make it a preferred option when two-way communication is not required.

2. Reactive Streams with Flux

If you’re already using Spring WebFlux, leveraging Flux for reactive streams is another powerful option. With Flux, you can stream updates directly to the client in a non-blocking and asynchronous manner. It integrates seamlessly with WebFlux SSE and allows you to emit data at regular intervals or based on Quartz job progress.

Example Flux Integration:

@GetMapping(value = "/progress", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<JobProgress> getJobProgress() {
return jobService.getProgressUpdates();
}

3. WebSocket

For more complex scenarios requiring two-way communication (e.g., real-time chat, gaming, or collaborative applications), WebSocket is the better option. WebSocket establishes a persistent, full-duplex connection between the server and the client, allowing both parties to send and receive data in real time.

Example WebSocket Use Case:

  • A client can send requests for specific updates, and the server can respond dynamically.
  • Users can receive progress updates while simultaneously sending cancellation or pause requests.

Which Approach to Choose?

By understanding the strengths of each technology, you can decide which approach best fits your specific requirements. For one-way updates like progress tracking, SSE and Flux are efficient solutions, while for interactive, two-way communication, WebSocket is the way to go.

Conclusion

With WebFlux SSE and Quartz, you can provide users with seamless, real-time feedback for long-running tasks. This approach enhances the user experience and eliminates the need for constant page refreshes or polling.

I hope this article helps you implement dynamic real-time progress tracking in your applications. Let me know your thoughts, and feel free to share your use cases!

--

--

Gayan Sanjeewa
Gayan Sanjeewa

Written by Gayan Sanjeewa

Senior Software Engineer | Java | SpringBoot | MicroServices | Cloud | AWS | OpenShift | Kubernetes | Docker

No responses yet