dash1e
dash1e

Reputation: 7807

SocketException Broken Pipe not raised when curl is terminated

I have a Spring Rest Controller that returns millions of rows in a SpringBoot application.

@GetMapping(value = "/getStreamOfJson")
public void getStreamOfJson(HttpServletResponse resp) throws IOException, InterruptedException {
    resp.setContentType("text/plain");
    resp.setBufferSize(1024);

    try (PrintWriter pw = resp.getWriter()) {
        for (int i = 0; i < 100_000_000; ++i) {
            GenericDto dto = GenericDto.builder()
                                       .id(i)
                                       .desc("DTO#%d".formatted(i))
                                       .build();
            String str = objectMapper.writeValueAsString(dto);
            logger.debug("getStreamOfJson: {}", str);
            pw.println(str);
            pw.flush(); // added just with the hope to receive the exception earlier
        }
    }
}

Then I try to consume it with curl or a Spring WebClient.

BUT when I terminate the client in the middle of the reading, the server continues to write data till the end and does not receive the SocketException: Borken Pipe or any other exception.

The ApplicationServer used by Spring in my example is Tomcat.

Why I'm not receiving any Exception when the client is terminated? How can I receive it?

Upvotes: 0

Views: 38

Answers (1)

dash1e
dash1e

Reputation: 7807

A silly question on my part. I forgot that, as also mentioned in the documentation (https://docs.oracle.com/javase/8/docs/api/java/io/PrintWriter.html), the PrintWriter class, unlike the Writer class from which it inherits, behaves differently:

Methods in this class never throw I/O exceptions, although some of its constructors may. The client may inquire as to whether any errors have occurred by invoking checkError().

So I added that check in my loop

for (int i = 0; i < N; ++i) {
    if (pw.checkError()) {
        logger.warn("Response is closed");
        return;
    }
    ...

And now everything works fine.

Upvotes: 1

Related Questions