Skip to content

When connection to client is lost while writing JSON, it should not be logged as warning #37151

Description

@michaldo

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:

  1. 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>
  1. 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
  1. 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();
    }
}
  1. curl localhost:8080 is ok
  2. curl localhost:8081 triggers warning in application log

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions