Backend Development 9 min read

Real‑Time Streaming with Spring’s ResponseBodyEmitter: Concepts, Use Cases, and Code Example

This article explains the purpose, core methods, and practical scenarios of Spring Framework’s ResponseBodyEmitter, compares it with SSE and raw streaming, and provides a complete Spring Boot controller example that demonstrates how to implement real‑time log streaming and other asynchronous HTTP responses.

Architecture Digest
Architecture Digest
Architecture Digest
Real‑Time Streaming with Spring’s ResponseBodyEmitter: Concepts, Use Cases, and Code Example

With the popularity of ChatGPT, streaming output techniques have attracted many developers, and the Spring Framework’s ResponseBodyEmitter offers a simple way to achieve asynchronous HTTP responses.

What is ResponseBodyEmitter? It is an interface introduced in Spring 4.2 that allows data to be sent to the client incrementally rather than waiting for the entire response, making it ideal for long‑running or real‑time scenarios.

Typical use cases include long polling, Server‑Sent Events (SSE), generic streaming, and asynchronous processing such as progress‑bar updates, real‑time chat, stock price feeds, system log streaming, and AI response streaming.

Real‑time Log Streaming Example

The following Spring Boot controller creates an endpoint /api/log/stream that returns a ResponseBodyEmitter and starts a background thread to push a new log entry every second.

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() {
        return "2025-02-12 12:00:00 - INFO: User logged in successfully.";
    }
}

When the application runs and the endpoint is accessed, the client receives a continuously updating log stream.

Core Methods of ResponseBodyEmitter

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

complete() : Marks the response as finished and closes the connection.

onTimeout(Runnable callback) : Registers a timeout callback.

onCompletion(Runnable callback) : Registers a completion callback.

How It Works

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

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

Comparison with Other Streaming Techniques

Streaming via OutputStream : Gives low‑level control but requires manual stream management.

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

ResponseBodyEmitter : Works with any HTTP client, integrates seamlessly with Spring, and is easier to use for generic streaming.

For AI‑driven real‑time responses, ResponseBodyEmitter often provides better HTTP compatibility than SSE.

Key Considerations

Ensure client compatibility; older browsers may have issues with chunked transfer.

Set appropriate timeouts, e.g., emitter.onTimeout(() -> emitter.complete()); .

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

Always call complete() or completeWithError() to close the connection.

In summary, ResponseBodyEmitter is a lightweight Spring solution for real‑time, high‑concurrency data push, enabling developers to build dynamic applications such as progress bars, chat, stock tickers, and log streaming with minimal effort.

backendJavareal-timeStreamingSpringSSEResponseBodyEmitter
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.