Backend Development 9 min read

Using Spring's ResponseBodyEmitter for Real-Time Streaming Responses

This article explains how Spring's ResponseBodyEmitter, introduced in Spring 4.2, enables lightweight asynchronous HTTP streaming for use cases like real-time logs, progress updates, chat, and AI responses, and provides a complete code example with best-practice guidelines.

Architecture Digest
Architecture Digest
Architecture Digest
Using Spring's ResponseBodyEmitter for Real-Time Streaming Responses

Introduction

ChatGPT's popularity has brought streaming output techniques to the forefront, and many developers started exploring SSE asynchronous handling. This article introduces a simpler way to achieve streaming output using Spring's ResponseBodyEmitter.

What is ResponseBodyEmitter

ResponseBodyEmitter, introduced in Spring Framework 4.2, is an interface that enables asynchronous HTTP responses by allowing data to be sent to the client incrementally rather than all at once. It is especially useful for long-running or streaming scenarios.

Typical Use Cases

Long polling

Server‑Sent Events (SSE)

Streaming large data (file download, real‑time feeds)

Asynchronous processing where partial results are returned progressively.

Practical Example – Real‑Time Log Streaming

The following Spring Boot controller demonstrates how to create a real‑time log stream using ResponseBodyEmitter.

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

@RestController
@RequestMapping("/api/log")
public class LogController {
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseBodyEmitter streamLogs() {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        new Thread(() -> {
            try {
                while (true) {
                    String logEntry = getLatestLogEntry();
                    if (logEntry != null) {
                        emitter.send(logEntry);
                    }
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }).start();
        return emitter;
    }

    private String getLatestLogEntry() {
        // Simulated log entry
        return "2025-02-12 12:00:00 - INFO: User logged in successfully.";
    }
}

Core Methods

send(Object data) : Sends a piece of data to the client; can be called multiple times.

complete() : Marks the response as finished.

onTimeout(Runnable callback) : Sets a timeout callback.

onCompletion(Runnable callback) : Sets a completion callback.

How It Works

ResponseBodyEmitter uses HTTP chunked transfer encoding, allowing the server to push data blocks as soon as they are ready without specifying a Content‑Length. The client can process each chunk immediately, reducing latency.

Connection lifecycle is managed by calling complete() when all data is sent or completeWithError() on failure, preventing resource leaks.

Comparison with Other Streaming Techniques

Streaming (OutputStream) : Gives full control but requires manual stream management.

Server‑Sent Events (SSE) : Uses the text/event‑stream protocol and needs client support.

ResponseBodyEmitter : Works with any HTTP client, integrates easily with Spring, and is suitable for AI‑style incremental responses.

Best Practices and Caveats

Ensure client compatibility with chunked responses.

Configure a timeout to avoid indefinitely open connections, e.g., emitter.onTimeout(() -> emitter.complete()); .

Although send() is thread‑safe, manage thread lifecycles to avoid leaks.

Always close the connection with complete() or completeWithError() after processing.

Conclusion

ResponseBodyEmitter provides a lightweight, Spring‑native solution for real‑time, high‑concurrency data delivery, enabling features such as progress bars, live chat, stock tickers, and log streaming.

backendJavaStreamingSpringHTTPResponseBodyEmitter
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.