I want to log the responsebody of the webclient.

My exchangeFilter

            next.exchange()
                .map { response ->
                    response.mutate()
                        .body { dataBuffer ->
                            dataBuffer.map {
                                Channels.newChannel(responseBodyBaos).write(it.asByteBuffer().asReadOnlyBuffer())
                                it
                            }.doOnComplete {
                                traceLog()
                        }.build()

My webclient. it works.

              webClient()
                    .get()
                    .uri(uri)
                    .exchange()
                    .flatMap {
                        when {
                            it.statusCode().value() == 500 ->
                                it.bodyToMono(Void::class.java).then(Mono.error(RuntimeException("api status: ${it.statusCode()}")))
                            else ->
                                it.bodyToMono(String::class.java)
                        }

However, while upgrading the spring boot version to 2.2.6 -> 2.4.0, I found that the exchange method was deprecated.

              webClient()
                    .get()
                    .uri(uri)
                    .exchangeToMono {
                        when {
                            it.statusCode().value() == 500 ->
                                it.bodyToMono(Void::class.java).then(Mono.error(RuntimeException("api status: ${it.statusCode()}")))
                            else ->
                                it.bodyToMono(String::class.java)
                        }

So, when I change the exchange method to the exchangeToMono method, an error occurs when the http status is 500.

java.lang.IllegalStateException: Only one connection receive subscriber allowed.

Any idea how to solve this problem?

Comment From: rstoyanchev

I can't tell from the snippets. For a start, please try on a more recent, and supported version, like Boot 2.7. For what you're trying to do, simple decoding to String, you can use retrieve with a status handler:

val result = webClient.get().uri("...")
        .retrieve()
        .onStatus(HttpStatus::is5xxServerError) { ... }
        .awaitBody<String>()

If you still run into the issue, it's best if you can provide a small sample, and we'll have a look.