Expected behavior

Only hit reactor.netty.channel.FluxReceive#startReceiver once

Actual behavior

Hits twice, where second time throws silently the "Only one connection receive subscriber allowed."

In production, sometimes this exception is reported from reactor.core.publisher.Operators : Operator called default onErrorDropped .... Locally I could only see this exception at the point of throwing inside FluxReceive#startReceiver with a debugger. Later in reactor.core.publisher.MonoFlatMap.FlatMapMain#onError it was done = false, so the exception was never shown anywhere.

Steps to reproduce

My calling code is the following:

webClient.get()
      .uri("myUri")
      .retrieve()
      .onStatus(HttpStatus::isError, response ->
                          response.bodyToMono(ErrorResponse.class)
                                  .log("response.bodyToMono")
                                  .flatMap(error -> Mono.error(
                                          new MyException(
                                                  MyErrorType.ofCode(error.getCode()).orElse(null),
                                                  error.getDescription()
                                          )
                                  ))
        )
      .bodyToMono(MyDto.class)

the logs:

client.bodyToMono                        : | onSubscribe([Fuseable] MonoFlatMap.FlatMapMain)
client.bodyToMono                        : | request(unbounded)
response.bodyToMono                      : | onSubscribe([Fuseable] MonoSingle.SingleSubscriber)
response.bodyToMono                      : | request(unbounded)
response.bodyToMono                      : | onNext(ErrorResponse(code=500, description=message))
response.bodyToMono                      : | cancel()
client.bodyToMono                        : | onError(com.bla.MyException: message)
client.bodyToMono                        :  the exception stacktrace

Reactor Core version

org.springframework:spring-webflux:5.1.6.RELEASE

JVM version (e.g. java -version)

openjdk version "11.0.1" 2018-10-16

========

The workaround for me is using an ExchangeFilterFunction https://stackoverflow.com/a/48984852/6166627 instead of onStatus. With this approach, I only hit the start receiver once with a debugger. Hopefully, it's gonna fix itself.

Anyway, this ERROR log seems to not affect anything actually, the code still throws MyException


originally posted in reactor but it's off-topic there https://github.com/reactor/reactor-core/issues/1747 Similar: #22096 #22284

Comment From: poutsma

I wrote a test to reproduce this problem (see https://github.com/spring-projects/spring-framework/commit/9f7dd9f35260368cafbc405b52f90ef72a9d0686), but it seems to work fine. Closing this for now, but let us now how we can improve the test to reproduce this issue.

Comment From: gmuth

I'd like to confirm the behaviour reported by Sam (my used version is 5.1.7.RELEASE). To be more precise: the logging message appears twice. This happens within the IDE (IntelliJ). There might be an issue with annotation processing - it's just a guess. We use a Lombok injected Logger via @Slf4j. As long as the onStatus-lambda (called twice) does not change state this is not an issue (like in my case).

Comment From: rstoyanchev

@gmuth please provide a sample if you'd like us to look further. As you can see above we did try the above snippet, a test was written, but could not reproduce it.

Comment From: DurgeshAlex

I am also facing the same issue with spring-webflux 5.2.9.RELEASE and using on spring boot version 2.1.11 and it seems to call the the endpoint twice. Below is the dependencies i am using org.springframework spring-webflux 5.2.9.RELEASE io.projectreactor reactor-core 3.3.10.RELEASE io.projectreactor.netty reactor-netty 0.9.12.RELEASE

Comment From: gmuth

good point I haven't checked. Maybe the onStatus() lambda calls are handled correct triggered by according endpoint calls. 1. someone should confirm that indeed the endpoint is called twice (e.g. by checking the server side). 2. we should find out why the "call-endpoint" operation is called multiple times.

Comment From: DurgeshAlex

Yeahh i created dummy endpoint in local server itself which is being called by webclient and kept the log and debug point in the endpoint i created. And as result debug point got invoked twice and log printed twice . That concluded that endpoint is being called twice. And also i added a filter while creating the the WebClient instance. Some thing like this Spring WebClient subscribing twice

And it seems that filter got invoked only once. This is the log i am seeing

Spring WebClient subscribing twice

In the log above you can see that two 200 Ok response i got. with two different threads. Hope it helps you.

Comment From: DurgeshAlex

Twice calling got fixed by removing the subscribe() i think issue is their with subscribe function.

Comment From: ShimelesT

I am having similar issue. I have list of Mono waiting response from multiple servers. And collectively block them after I subscribed to each of them individually. And I have to subscribe.

  1. For each server create client make a get request subscribe to the mono
  2. block all mono
  3. generate status summary from each server

Comment From: bclozel

You should (almost) never subscribe() to a publisher in a Spring application.

  1. if you're writing a non-reactive application, you can call block() on publisher instances and get the value directly
  2. if you're writing a reactive application, subscribe and block should never be called and you should use reactor operators instead to compose publishers if necessary

If you're reading this issue and you're still confused, I'd suggest writing a new question on StackOverflow showing a code snippet and explaining what you're trying to achieve.

Comment From: jesus9508

I have the same problem, but is a little hard to reply the error in dev environment, but in prod is sending a request twice at same

this is my implementation, Can someone tellme if I have some wrong whit this. Spring WebClient subscribing twice

Spring WebClient subscribing twice

the problem happend when it tryed to send information to other app, the provider noticed that there are same request sent twice at same hour, minute and sec.