Hi, I am currently using spring-boot-starter-webflux: 2.4.0 I want to use reactor-netty as the WebServer, but WebSocketVersion.V13 is hard-coded in ReactorNettyWebSocketClient https://github.com/reactor/reactor-netty/issues/1418 I relied on spring-boot-starter-tomcat and used TomcatWebSocketClient to solve the handshake problem, but WebServer became tomcat. Is there any way to specify WebServer
Comment From: wilkinsona
You can define your own NettyReactiveWebServerFactory
bean. You may also need to set spring.main.web-application-type=reactive
. If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.
Comment From: liuzhongkai
There is no problem in starting with this method, but an exception will be thrown when a request comes in
Comment From: liuzhongkai
2020-12-11 17:54:05.417 INFO 74865 --- [ main] com.uusoft.im.ThImApplication : No active profile set, falling back to default profiles: default
2020-12-11 17:54:06.543 INFO 74865 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-12-11 17:54:06.552 INFO 74865 --- [ main] com.uusoft.im.ThImApplication : Started ThImApplication in 1.397 seconds (JVM running for 2.135)
2020-12-11 17:54:23.523 ERROR 74865 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [6484c307-1] 500 Server Error for HTTP GET "/socket/index/market-exponent?appId=zJ2mR5fY3eQ6cI2gQ3xX9fF1iM6mE2uU&time=1607515359117&token=0a4ca082ba89c22f3393936d6e00d77b"
java.lang.ClassCastException: reactor.netty.http.server.HttpServerOperations cannot be cast to javax.servlet.http.HttpServletRequest
at org.springframework.web.reactive.socket.server.upgrade.TomcatRequestUpgradeStrategy.getNativeRequest(TomcatRequestUpgradeStrategy.java:159) ~[spring-webflux-5.3.1.jar:5.3.1]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ HTTP GET "/socket/index/market-exponent?appId=zJ2mR5fY3eQ6cI2gQ3xX9fF1iM6mE2uU&time=1607515359117&token=0a4ca082ba89c22f3393936d6e00d77b" [ExceptionHandlingWebHandler]
Stack trace:
at org.springframework.web.reactive.socket.server.upgrade.TomcatRequestUpgradeStrategy.getNativeRequest(TomcatRequestUpgradeStrategy.java:159) ~[spring-webflux-5.3.1.jar:5.3.1]
at org.springframework.web.reactive.socket.server.upgrade.TomcatRequestUpgradeStrategy.upgrade(TomcatRequestUpgradeStrategy.java:134) ~[spring-webflux-5.3.1.jar:5.3.1]
at org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService.lambda$handleRequest$1(HandshakeWebSocketService.java:235) ~[spring-webflux-5.3.1.jar:5.3.1]
at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:151) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.Mono.subscribe(Mono.java:3972) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:173) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.innerNext(FluxConcatMap.java:281) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxConcatMap$ConcatMapInner.onNext(FluxConcatMap.java:860) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2346) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:169) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2154) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2028) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.Mono.subscribe(Mono.java:3987) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:448) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onSubscribe(FluxConcatMap.java:218) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:164) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.FluxIterable.subscribe(FluxIterable.java:86) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.Mono.subscribe(Mono.java:3987) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:173) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.4.0.jar:3.4.0]
at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:611) ~[reactor-netty-http-1.0.1.jar:1.0.1]
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:612) ~[reactor-netty-core-1.0.1.jar:1.0.1]
at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:453) ~[reactor-netty-core-1.0.1.jar:1.0.1]
at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:510) ~[reactor-netty-http-1.0.1.jar:1.0.1]
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) ~[reactor-netty-core-1.0.1.jar:1.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:185) ~[reactor-netty-http-1.0.1.jar:1.0.1]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324) ~[netty-codec-4.1.54.Final.jar:4.1.54.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296) ~[netty-codec-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.54.Final.jar:4.1.54.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.54.Final.jar:4.1.54.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.54.Final.jar:4.1.54.Final]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_211]
Comment From: liuzhongkai
This is a websocket request connection, check the source code and find that the org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService.initUpgradeStrategy() method will always be the implementation of tomcat when the tomcat dependency is included, but my WebServer configuration Is NettyReactiveWebServerFactory, which is a conflict
Comment From: wilkinsona
It would appear that you haven't customised the WebSocketService
that's used. You can do so by defining a WebFluxConfigurer
bean and implementing its getWebSocketService()
method.
As I said above, if you have any further questions, please follow up on Stack Overflow or Gitter.
Comment From: liuzhongkai
It is possible to use a custom WebSocketService and rewrite all the contents of the handleRequest method, but this will cause the contents of this method to be less up to date. The actual problem with this is the loading mechanism of the HandshakeWebSocketService.upgradeStrategy object, which should not be avoided
Comment From: wilkinsona
There's no need to write a custom service, you can use HandshakeWebSocketService
constructed with a ReactorNettyRequestUpgradeStrategy
.
I'm going to lock this issue now. Please follow up on Stack Overflow or Gitter if you require any further help. The issue tracker isn't the right place for this.