Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebClient throws "Only one connection receive subscriber allowed" when response has content but no Content-Type header [SPR-17482] #22014

Closed
spring-issuemaster opened this Issue Nov 9, 2018 · 1 comment

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

spring-issuemaster commented Nov 9, 2018

Nischit Shetty opened SPR-17482 and commented

I stumbled upon this issue while executing a uncommon outbound API.

Refer the test case at which simulates the issue. https://github.com/nischit7/my-exp-webflux-stream/blob/master/src/test/java/com/example/spring/stream/controller/MoreThanOnSubscriberTest.java

In essence, I am bringing up a mock server which is supposed to return NO media type header. I know for an API, NO response header doesnt seem right. For the moment, pls assume its a negative test case.

On running that test, I get an error -

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


at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:277)
at reactor.netty.channel.FluxReceive.subscribe(FluxReceive.java:127)at
 reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62)
at reactor.netty.ByteBufFlux.subscribe(ByteBufFlux.java:290)
at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62)
at reactor.core.publisher.FluxMap.subscribe(FluxMap.java:62)
at reactor.core.publisher.Flux.subscribe(Flux.java:7734)
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:207)
at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:81)
at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:81)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:1713)
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136)
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136)
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136)at
 reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:378)
at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:202)
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:343)
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:325)
at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:372)
at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:522)
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:141)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:310)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:284)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:628)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:563)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:480)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
at java.lang.Thread.run(Thread.java:748)Suppressed: java.lang.Exception: #block terminated with an error
 
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:93) 
at reactor.core.publisher.Mono.block(Mono.java:1475) 
at com.example.spring.stream.controller.MoreThanOnSubscriberTest.moreThanOneSubscriberError(MoreThanOnSubscriberTest.java:83) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Note the line number 69 in that test class. I have intentionally commented it. Now uncomment the line and re-rerun the test case. This time, it should be successful. Comment that line again.

Now another interesting thing to note. When you change the version of spring-webflux to 5.0.10.RELEASE, you should see it successful. Change the version of spring-webflix to 5.1.1.RELEASE, it will fail. So obviously something has changed. I do see spring finds no content-type response header and defaults it to octet stream. After which I have not digged further, why it fails.

 


Affects: 5.1 GA

Reference URL: https://stackoverflow.com/questions/53144412/spring-webclient-throws-only-one-connection-receive-subscriber-allowed-when-re

Issue Links:

  • #21592 ClientResponse's body ignored on UnsupportedMediaTypeException
  • #22108 WebClient throws "Only one connection receive subscriber allowed." when response generates a WebClientResponseException

Referenced from: commits a5339d7

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Nov 9, 2018

Rossen Stoyanchev commented

This is related to the change for #21592 to consume and release the response content in case of UnsupportedMediaTypeException. The fix works when there is a Content-Type, not when there is no Content-Type, we also try to consume the body to see if it's empty (based on #20313) which leads to the given exception.

 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.