Prior discussion in #34481 (comment).
There is a class which identifies when client breaks connection: org.springframework.web.util.DisconnectedClientHelper
Unfortunately, when JSON is being written to output stream, org.springframework.http.converter.AbstractJacksonHttpMessageConverter#writeInternal identifies it as HttpMessageNotWritableException
Both identification collides and finally application produces output like:
WARN .w.s.m.s.DefaultHandlerExceptionResolver : Ignoring exception, response committed already: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: ServletOutputStream failed to write: java.io.IOException: Broken pipe
Expected behavior: no warning at all.
Affects: spring-framework 7.0.8
Steps to reproduce:
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>broken-pipe-demo</groupId>
<artifactId>broken-pipe-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>25</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>eu.rekawek.toxiproxy</groupId>
<artifactId>toxiproxy-java</artifactId>
<version>2.1.7</version>
</dependency>
</dependencies>
</project>
- compose.yaml (prepared for Windows, may need adjustment for Linux)
services:
toxiproxy:
image: ghcr.io/shopify/toxiproxy:2.12.0
container_name: toxiproxy
ports:
- "8474:8474" # Toxiproxy API (for managing proxies and toxics)
- "8081:8081" # proxy
labels:
org.springframework.boot.ignore: true
- application
package brokenpipedemo.brokenpipedemo;
import eu.rekawek.toxiproxy.ToxiproxyClient;
import eu.rekawek.toxiproxy.model.ToxicDirection;
import jakarta.annotation.PostConstruct;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.stream.IntStream;
@SpringBootApplication
@RestController
public class BrokenPipeDemoApplication {
static void main(String[] args) {
SpringApplication.run(BrokenPipeDemoApplication.class, args);
}
@PostConstruct
void toxiProxySetup() throws IOException {
new ToxiproxyClient("localhost", 8474)
.createProxy("broken-pipe", "0.0.0.0:8081", "host.docker.internal:8080")
.toxics()
.resetPeer("immediate", ToxicDirection.DOWNSTREAM, 0);
}
@GetMapping
int[] get() {
return IntStream.range(0, 100_000).toArray();
}
}
curl localhost:8080 is ok
curl localhost:8081 triggers warning in application log
Prior discussion in #34481 (comment).
There is a class which identifies when client breaks connection: org.springframework.web.util.DisconnectedClientHelper
Unfortunately, when JSON is being written to output stream, org.springframework.http.converter.AbstractJacksonHttpMessageConverter#writeInternal identifies it as HttpMessageNotWritableException
Both identification collides and finally application produces output like:
Expected behavior: no warning at all.
Affects: spring-framework 7.0.8
Steps to reproduce:
curl localhost:8080is okcurl localhost:8081triggers warning in application log