In spring-web 6.0.15, this code works as expected, in spring 6.1.2 (propably because of this commit - https://github.com/spring-projects/spring-framework/commit/033bebf8cd4a2933788e1ea3540404aefdac2cf7 ) it doesn't work.

Any suggestions? is it bug in spring-web, or in my code? It seems @Deprecated annotations have been added in 6.1 together with removal of some code without maintaining the backward compatibility in 6.1... But I am not sure if I just havent missed some release notes :(

Wierd thing is, it only happens for some requests, most of requests pass correctly, I suspect there are 2 possible reasons: 1. failed request json has length 597 bytes, passed requests has only up to 355 bytes (request content length header field) 2. new implementation is looking into Content-Length request header (old did not) and since body length is different (due to modifySomeJsonValues()), it fails with the exception

exception is low level IOException:

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://127.0.0.1:8765/bff/services/target-service/orders/": insufficient data written
    at org.springframework.web.client.RestTemplate.createResourceAccessException(RestTemplate.java:905) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:885) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:821) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:682) ~[spring-web-6.1.2.jar:6.1.2]
    at org.example.MyService.processRequest(MyService.java:143) ~[classes/:na]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:859) ~[undertow-core-2.3.10.Final.jar:2.3.10.Final]
Caused by: java.io.IOException: insufficient data written
    at java.base/sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.close(HttpURLConnection.java:3848) ~[na:na]
    at org.springframework.http.client.SimpleClientHttpRequest.executeInternal(SimpleClientHttpRequest.java:84) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.http.client.BufferingClientHttpRequestWrapper.executeInternal(BufferingClientHttpRequestWrapper.java:75) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-6.1.2.jar:6.1.2]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:879) ~[spring-web-6.1.2.jar:6.1.2]
    ... 121 common frames omitted
/* from controller input 
HttpMethod method;
URI uri;
@RequestBody(required = false) String body;
HttpServletRequest request;
HttpServletResponse response;
*/

        final HttpHeaders headers = new HttpHeaders();
        final Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.set(headerName, request.getHeader(headerName));
        }

        HttpEntity<byte[]> httpEntity = new HttpEntity<>(modifySomeJsonValues(body.getBytes(StandardCharsets.UTF_8)), headers);

        ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
        RestTemplate restTemplate = new RestTemplate(factory);
        try {
            ResponseEntity<byte[]> serverResponse = restTemplate.exchange(uri, method, httpEntity, byte[].class);
            .......
        } catch (...) {...}

Comment From: snicoll

I believe there is a note for that in the upgrade guide:

To reduce memory usage in RestClient and RestTemplate, most ClientHttpRequestFactory implementations no longer buffer request bodies before sending them to the server. As a result, for certain content types such as JSON, the contents size is no longer known, and a Content-Length header is no longer set. If you would like to buffer request bodies like before, simply wrap the ClientHttpRequestFactory you are using in a BufferingClientHttpRequestFactory.

Can you give that a try and report back if that doesn't help? If that's the case, we'd need you to move that code in text into a small sample we can run ourselves. You can attach a zip to this issue or push the code to a GitHub repository.

Comment From: tomaskodaj

thanks, problem solved by the hint - sorry for overlooking the release notes.

problem was original request had "content-length" and after modifyingit in modifySomeJsonValues() it has changed... and since spring stopped using buffers and recalculating content-length, it contained wrong value... I have just removed original content-length from request and everything works again :)