Skip to content

WebClient defaultStatusHandler raise a WebClientRequestException in a NONE-Web Environment #45668

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

Closed
hantsy opened this issue May 26, 2025 · 5 comments

Comments

@hantsy
Copy link

hantsy commented May 26, 2025

My example project: https://github.com/hantsy/spring6-sandbox/tree/master/boot-http-service

  • Java 21
  • Spring Boot 3.5.0
  • WebFlux Stack

Reproducing Steps:

  1. run mvn clean compile -DskipTests in the project root folder.
  2. run mvn spring-boot:run in server and client folder respectively.

You will see an exception like the following in the client console.

org.springframework.web.reactive.function.client.WebClientRequestException: 
executor not accepting a task
	
at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:137) ~[spring-webflux-6.2.7.jar:6.2.7]

If I remove the spring.main.web-application-type line in the client application.properties and set up the server.port=8888, and rerun the application, the .defaultStatusHandler will raise WebClientRespoonseException.$NotFound as expected.

But the WebClient should work in a none-web application as expected.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 26, 2025
@wilkinsona
Copy link
Member

I'm unable to reproduce the problem by following the provided steps. Here's the client's output:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.0)

2025-05-27T07:50:42.985+01:00  INFO 22086 --- [client] [           main] c.example.demo.client.ClientApplication  : Starting ClientApplication v0.0.1-SNAPSHOT using Java 21.0.5 with PID 22086 (/Users/aw036093/dev/temp/spring6-sandbox/boot-http-service/client/target/client-0.0.1-SNAPSHOT.jar started by aw036093 in /Users/aw036093/dev/temp/spring6-sandbox/boot-http-service)
2025-05-27T07:50:42.986+01:00 DEBUG 22086 --- [client] [           main] c.example.demo.client.ClientApplication  : Running with Spring Boot v3.5.0, Spring v6.2.7
2025-05-27T07:50:42.987+01:00  INFO 22086 --- [client] [           main] c.example.demo.client.ClientApplication  : No active profile set, falling back to 1 default profile: "default"
2025-05-27T07:50:43.527+01:00 DEBUG 22086 --- [client] [           main] c.e.d.client.ClientExampleInitializer    : get all posts.
2025-05-27T07:50:43.609+01:00 ERROR 22086 --- [client] [           main] i.n.r.d.DnsServerAddressStreamProviders  : Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'. Use DEBUG level to see the full stack: java.lang.UnsatisfiedLinkError: failed to load the required native library
2025-05-27T07:50:43.645+01:00 DEBUG 22086 --- [client] [           main] c.e.d.client.ClientExampleInitializer    : save post and update post
2025-05-27T07:50:43.648+01:00  INFO 22086 --- [client] [           main] reactor.Mono.FlatMap.1                   : | onSubscribe([Fuseable] MonoFlatMap.FlatMapMain)
2025-05-27T07:50:43.648+01:00  INFO 22086 --- [client] [           main] reactor.Mono.FlatMap.1                   : | request(unbounded)
2025-05-27T07:50:43.649+01:00 DEBUG 22086 --- [client] [           main] c.e.d.client.ClientExampleInitializer    : get post by id that not existed.
2025-05-27T07:50:43.673+01:00  INFO 22086 --- [client] [           main] c.example.demo.client.ClientApplication  : Started ClientApplication in 0.888 seconds (process running for 1.148)
2025-05-27T07:50:43.806+01:00  INFO 22086 --- [client] [tor-http-nio-16] reactor.Mono.FlatMap.1                   : | onNext(<201 CREATED Created,[Location:"/posts/ce7be93d-ceee-4609-8b3a-16b0868b16ce", content-length:"0"]>)
2025-05-27T07:50:43.809+01:00 DEBUG 22086 --- [client] [tor-http-nio-16] c.e.d.client.ClientExampleInitializer    : Post id: ce7be93d-ceee-4609-8b3a-16b0868b16ce
2025-05-27T07:50:43.809+01:00  INFO 22086 --- [client] [tor-http-nio-16] reactor.Mono.FlatMap.2                   : | onSubscribe([Fuseable] MonoFlatMap.FlatMapMain)
2025-05-27T07:50:43.809+01:00  INFO 22086 --- [client] [tor-http-nio-16] reactor.Mono.FlatMap.2                   : | request(unbounded)
2025-05-27T07:50:43.810+01:00  INFO 22086 --- [client] [tor-http-nio-16] reactor.Mono.FlatMap.1                   : | onComplete()
2025-05-27T07:50:43.830+01:00 ERROR 22086 --- [client] [tor-http-nio-12] c.e.d.client.ClientExampleInitializer    : error:

org.springframework.web.reactive.function.client.WebClientResponseException$InternalServerError: 500 Internal Server Error from GET http://localhost:8080/posts/a2984a20-28d3-4bce-9321-13670908819c
	at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:332) ~[spring-webflux-6.2.7.jar!/:6.2.7]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ 500 INTERNAL_SERVER_ERROR from GET http://localhost:8080/posts/a2984a20-28d3-4bce-9321-13670908819c [DefaultWebClient]
Original Stack Trace:
		at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:332) ~[spring-webflux-6.2.7.jar!/:6.2.7]
		at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException$1(DefaultClientResponse.java:214) ~[spring-webflux-6.2.7.jar!/:6.2.7]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onNext(FluxOnErrorReturn.java:162) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:122) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2096) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:260) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:144) ~[reactor-core-3.7.6.jar!/:3.7.6]
		at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:413) ~[reactor-netty-core-1.2.6.jar!/:1.2.6]
		at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:455) ~[reactor-netty-core-1.2.6.jar!/:1.2.6]
		at reactor.netty.channel.ChannelOperations.terminate(ChannelOperations.java:509) ~[reactor-netty-core-1.2.6.jar!/:1.2.6]
		at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:821) ~[reactor-netty-http-1.2.6.jar!/:1.2.6]
		at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:115) ~[reactor-netty-core-1.2.6.jar!/:1.2.6]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:107) ~[netty-codec-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) ~[netty-codec-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318) ~[netty-codec-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1357) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:868) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:796) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:732) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:658) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998) ~[netty-common-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.121.Final.jar!/:4.1.121.Final]
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.121.Final.jar!/:4.1.121.Final]
		at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]

2025-05-27T07:50:43.830+01:00 DEBUG 22086 --- [client] [tor-http-nio-15] c.e.d.client.ClientExampleInitializer    : The existing post: Post[id=a2189bf5-6dfe-4d4c-a0dd-e63284eff4ac, title=First Post, content=Content of First Post, status=DRAFT, createdAt=2025-05-27T07:50:18.075474]
2025-05-27T07:50:43.830+01:00  INFO 22086 --- [client] [tor-http-nio-16] reactor.Mono.FlatMap.2                   : | onNext(Post[id=ce7be93d-ceee-4609-8b3a-16b0868b16ce, title=test, content=test content, status=DRAFT, createdAt=2025-05-27T07:50:43.794102])
2025-05-27T07:50:43.835+01:00 DEBUG 22086 --- [client] [tor-http-nio-16] c.e.d.client.ClientExampleInitializer    : post: Post[id=ce7be93d-ceee-4609-8b3a-16b0868b16ce, title=test, content=test content, status=DRAFT, createdAt=2025-05-27T07:50:43.794102]
2025-05-27T07:50:43.835+01:00 DEBUG 22086 --- [client] [tor-http-nio-16] c.e.d.client.ClientExampleInitializer    : getting post: Post[id=ce7be93d-ceee-4609-8b3a-16b0868b16ce, title=test, content=test content, status=DRAFT, createdAt=2025-05-27T07:50:43.794102]
2025-05-27T07:50:43.835+01:00 DEBUG 22086 --- [client] [tor-http-nio-15] c.e.d.client.ClientExampleInitializer    : The existing post: Post[id=8f65ec83-75b5-4f5c-bfed-02ad72ef7413, title=Second Post, content=Content of Second Post, status=DRAFT, createdAt=2025-05-27T07:50:18.076155]
2025-05-27T07:50:43.835+01:00 DEBUG 22086 --- [client] [tor-http-nio-15] c.e.d.client.ClientExampleInitializer    : The existing post: Post[id=ce7be93d-ceee-4609-8b3a-16b0868b16ce, title=test, content=test content, status=DRAFT, createdAt=2025-05-27T07:50:43.794102]
2025-05-27T07:50:43.836+01:00  INFO 22086 --- [client] [tor-http-nio-16] reactor.Mono.FlatMap.2                   : | onComplete()
2025-05-27T07:50:43.840+01:00 DEBUG 22086 --- [client] [tor-http-nio-16] c.e.d.client.ClientExampleInitializer    : updated status: <204 NO_CONTENT No Content,[]>

@wilkinsona wilkinsona added the status: waiting-for-feedback We need additional information before we can continue label May 27, 2025
@hantsy
Copy link
Author

hantsy commented May 27, 2025

I used Windows 10 pro to test it, the exception is different from this org.springframework.web.reactive.function.client.WebClientResponseException$InternalServerError: 500 Internal Server Error from GET http://localhost:8080/posts/a2984a20-28d3-4bce-9321-13670908819c

  1. If the client is a web application with a server port, and it worked as expected, a WebClientResponseExcpetoin indicates there is a 404 error.
  2. If change the application type to none, I get the WebClientRequestException as described above.

I have added the RestExceptionHandler in the server, and in the client module, at the end of the listener method, it tried to get post by a non-existing id, which should return status 404.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 27, 2025
@wilkinsona
Copy link
Member

Thanks, but that doesn't help me to reproduce the described behavior.

The situation's not helped by the complexity of the sample. It seems to include quite a few things that are unrelated to WebClient's behavior. For example, the mapping to problem details does not seem to be relevant. Creating, saving, and deleting entries in a repository also seems to be unrelated from what you have described and a simple HTTP call that receives a 404 response should be sufficient.

If you would like us to spend more time investigating, please take the time to produce a sample that focuses only on the problem and contains the bare minimum of code and dependencies that is necessary to reproduce it.

@wilkinsona wilkinsona added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels May 27, 2025
@spring-projects-issues
Copy link
Collaborator

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Jun 3, 2025
@spring-projects-issues
Copy link
Collaborator

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

@spring-projects-issues spring-projects-issues closed this as not planned Won't fix, can't repro, duplicate, stale Jun 10, 2025
@spring-projects-issues spring-projects-issues removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged labels Jun 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants