Spring Boot + OkHttp3 for SSE-Based API Response Handling

Spring Boot + OkHttp3 for SSE-Based API Response Handling

In real-world applications, integrating Spring Boot with external APIs is a common scenario. Particularly, when working with chatbot APIs or real-time services, streaming responses to clients efficiently is essential.
This post explains how to use OkHttp3 to call an external API and stream its response using Server-Sent Events (SSE).


1. What is SSE (Server-Sent Events)?

Server-Sent Events (SSE) is a technology that enables servers to push real-time updates to clients over HTTP. Unlike WebSockets, SSE is a unidirectional communication channel where the server continuously sends data to the client. SSE is widely used for real-time data streaming applications, such as stock prices, chat messages, and notifications.


2. Implementing SSE in Spring Boot

Spring Boot allows easy implementation of SSE using Flux<String>. To enable SSE support, we need to add the WebFlux dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

3. Using OkHttp3 for API Calls and SSE Streaming

In a real-world scenario, we often need to call an external API using OkHttp3 and transform its response into an SSE stream. Below is a sample implementation that processes an already available okhttp3.Response object and streams it to the client using SSE.

@RestController
public class ChatController {

    @GetMapping(value = "/chat-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> streamChatResponse(@RequestParam String message) {
        Sinks.Many<String> sink = Sinks.many().unicast().onBackpressureBuffer();

        Response response = callChatApi(message); // API call logic
        processResponse(response, sink);

        return sink.asFlux();
    }

    private Response callChatApi(String message) {
        return ChatApiClient.callApi(message); // Pre-implemented API call method
    }

    private void processResponse(Response response, Sinks.Many<String> sink) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body().byteStream()))) {
            String line;
            while ((line = reader.readLine()) != null) {
                sink.tryEmitNext("data: " + line + "\n");
            }
        } catch (Exception e) {
            sink.tryEmitNext("Error reading response: " + e.getMessage());
        } finally {
            sink.tryEmitComplete();
        }
    }
}

4. Receiving SSE Data on the Client Side

Clients can receive SSE data using the EventSource API.

const eventSource = new EventSource("http://localhost:8080/chat-stream?message=Hello");

eventSource.onmessage = (event) => {
    console.log("Received:", event.data);
};

eventSource.onerror = (error) => {
    console.error("SSE Error:", error);
    eventSource.close();
};

5. Summary

- SSE is an efficient way to push real-time data from the server to clients.
- OkHttp3 can be used to call external APIs and stream responses as SSE.
- Spring Boot allows easy SSE implementation using Flux<String>.
- Clients can use EventSource to receive streamed data.


6. Additional Considerations

- If streaming is unnecessary, consider returning a JSON response instead.
- Network issues may cause SSE connections to drop, so implementing a reconnection mechanism on the client side is advisable.
- WebFlux provides more efficient non-blocking processing than traditional Spring MVC.

Comments