Affects: both 5.3.25, 6.0.6 but differently
I have almost the same process like described in #29038:
Service returns Flux<SomeObject>
which is then returned by controller as ResponseEntity.ok(payloadFlux)
. If any error occurs it triggers either ResponseStatusException or some custom Exception.
I noticed different behaviour between versions 5 and 6 in the case if flux contains error after some element. There are three options for non empty flux:
* flux completes successfully after some elements
* works as expected in both versions, server returns 200
* flux has error without any elements
* works as expected in both versions, server returns status from exception
* flux has error after some elements
* works differently
* version 5: server returns status from exception
* version 6: server starts to stream response with status 200 and first element and can not change the status afterwards: Error [org.springframework.web.server.ResponseStatusException] for HTTP GET "/path", but ServerHttpResponse already committed (200 OK) Error finishing response. Closing connection
* it only affects JSON payload, if payload is Flux<String>
both versions behave like with JSON payload in version 6: unable to set correct error status because response is already commited with status 200
Example project: * run with mvn clean verify: * two failed tests * change parent version to spring boot 2.7.9, which depends on spring-webflux 5.3.25 and run again: * only test with string payload fails
webflux-flux-response-with-error.zip
Comment From: alex-arana
I've refreshed @denvir 's test harness for the latest releases of Spring Boot / WebFlux and can confirm the issue is very much still there. You can find my test repository here:
https://github.com/alex-arana/webflux-flux-response-with-error
Comment From: rstoyanchev
This is a side effect of #28398 where Flux
is written as a stream vs collecting items to a List first. The idea is that as a framework we don't know how many items will be written, and it's better to stream the output rather than aggregating into a potentially very large list. You can still achieve the same effect by returning Mono<List<T>>
with flux.collectList()
.