Affects: 6.1.0-SNAPSHOT
- Spring Version: 6.1.0-SNAPSHOT
- JDK Version: Java 17
When I tried to run the test case, it reported this error, The stack:
Expecting actual throwable to be an instance of:
org.springframework.web.client.ResourceAccessException
but was:
java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:127)
at reactor.core.publisher.Mono.block(Mono.java:1738)
at org.springframework.http.client.ReactorNettyClientRequest.executeInternal(ReactorNettyClientRequest.java:95)
...(150 remaining lines not displayed - this can be changed with Assertions.setMaxStackTraceElementsDisplayed)
java.lang.AssertionError:
Expecting actual throwable to be an instance of:
org.springframework.web.client.ResourceAccessException
but was:
java.lang.IllegalStateException: Timeout on blocking read for 5000000000 NANOSECONDS
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:127)
at reactor.core.publisher.Mono.block(Mono.java:1738)
at org.springframework.http.client.ReactorNettyClientRequest.executeInternal(ReactorNettyClientRequest.java:95)
...(150 remaining lines not displayed - this can be changed with Assertions.setMaxStackTraceElementsDisplayed)
at org.springframework.web.client.RestClientIntegrationTests.invalidDomain(RestClientIntegrationTests.java:709)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:992)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
RestClientIntegrationTests > invalidDomain(ClientHttpRequestFactory) > [6] Reactor Netty FAILED
java.lang.AssertionError at RestClientIntegrationTests.java:709
Comment From: sbrannen
Please attempt to run it again.
That sounds like one of our flaky reactive tests.
In light of that, I'm closing this issue.
However, if you find that it fails repeatedly for you, please report back here with further details on your environment.
Comment From: hunjipo
In my environment, it always fails.
- OS: Windows 11 22H2 22621.2134
- Java: Java 17.0.7
- CPU: AMD Ryzen 9 7945HX
- IDEA: 2023.1.2
Comment From: sbrannen
Thanks for the feedback, @hunjipo.
It could potentially be an issue when running on MS Windows.
Someone from the team will investigate it.
Comment From: quaff
It may caused by proxy, please disable it and try again. I've encountered such exception if proxy enabled:
Expecting actual throwable to be an instance of:
org.springframework.web.client.ResourceAccessException
but was:
org.springframework.web.client.HttpServerErrorException$ServiceUnavailable: 503 Service Unavailable: "<h1>Domain Not Resolved</h1><p>[D]Domain Not Resolved|lookup example.invalid on 8.8.8.8:53: no such host</p>"
Comment From: hunjipo
It may caused by proxy, please disable it and try again. I've encountered such exception if proxy enabled:
Expecting actual throwable to be an instance of: org.springframework.web.client.ResourceAccessException but was: org.springframework.web.client.HttpServerErrorException$ServiceUnavailable: 503 Service Unavailable: "<h1>Domain Not Resolved</h1><p>[D]Domain Not Resolved|lookup example.invalid on 8.8.8.8:53: no such host</p>"
@quaff Thanks, this is a good direction, and I did indeed have proxy enabled at that time. However, I didn't enable the proxy today, and I also turned off the HTTP proxy in the IDEA settings. Despite this, the test case still failed. Another noteworthy point is that we are throwing a different exception.
Comment From: sdeleuze
I can reproduce time to time without a proxy the original exception reported (IllegalStateException
). I am wondering if we should use blockOptional()
with Optional.orElseThrow(Supplier)
to throw a ResourceAccessException
for the empty use case.
Comment From: rstoyanchev
It depends if we want to treat the timeout as a ResourceAccessException
, essentially an I/O error. In this case the exchangeTimeout
is configured at the level of the ReactorNettyClientRequestFactory
, but a timeout can also occur at a lower level. So if we decide to handle it this way, then we should also handle the Reactor Netty TimeoutException
for consistency.
If we simply increase the default exchangeTimeout
, then the test expectations should be met.
Also note that for HTTP Interface Client we have a similar case with two levels of timeout settings, and if you configure timeouts at the HTTP client level, which are more fine-grained, then the exchangeTimeout
can get in the way, and it can create confusion as described in #30248. This is why currently the HTTP Interface client does not impose a timeout by default, and instead relies on underlying client timeout values. It occurs to me that when used with RestClient
users will once again hit an additional timeout. Perhaps it's worth considering leaving the exchangeTimeout
not set at all by default.
Comment From: sdeleuze
After a related team discussion, we agreed that the wide range of possible different behaviors (dozens of milliseconds to dozens of seconds timeouts, some proxies and security software returning various HTTP code with different bodies, DNS behavior different across OSes) do not allow to have a reliable integration test for invalid domain, so we will just remove those.