HandshakeWebSocketService#initUpgradeStrategy
does not check for the availability of relevant classes before attempting to instanciate StandardWebSocketUpgradeStrategy
.
static RequestUpgradeStrategy initUpgradeStrategy() {
if (tomcatWsPresent) {
return new TomcatRequestUpgradeStrategy();
}
else if (jettyWsPresent) {
return new JettyRequestUpgradeStrategy();
}
else if (undertowWsPresent) {
return new UndertowRequestUpgradeStrategy();
}
else if (reactorNettyPresent) {
// As late as possible (Reactor Netty commonly used for WebClient)
return ReactorNettyStrategyDelegate.forReactorNetty1();
}
else if (reactorNetty2Present) {
// As late as possible (Reactor Netty commonly used for WebClient)
return ReactorNettyStrategyDelegate.forReactorNetty2();
}
else {
// Let's assume Jakarta WebSocket API 2.1+
return new StandardWebSocketUpgradeStrategy();
}
}
This breaks when you attempt to load a context without a dependency on jakarta.websocket-client-api.
It looks like it should be handled gracefully by the following code in WebFluxConfigurationSupport:
private WebSocketService initWebSocketService() {
WebSocketService service = getWebSocketService();
if (service == null) {
try {
service = new HandshakeWebSocketService();
}
catch (IllegalStateException ex) {
// Don't fail, test environment perhaps
service = new NoUpgradeStrategyWebSocketService();
}
}
return service;
}
but because a ClassNotFoundException is thrown instead of IllegalStateException; the context simply fails to load instead of falling back to NoUpgradeStrategyWebSocketService
Comment From: MFAshby
The workaround in my case was to add the following dependencies (my problem was loading a minimal context for a test case):
<!-- SpringBootConfigStorageIntegrationTest loads the whole spring context, which winds up creating a
HandshakeWebSocketService, which falls back to jakarta websocket without testing if it's actually
on the classpath -->
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-client-api</artifactId>
<scope>test</scope>
</dependency>
Comment From: zhanyan-Ader1y
I created a new repository for this problem.
Class not found reason is jakarta.websocket
dependency not passed down from webflux module.
Whether it is necessary to verify the existence of jakarta.websocket
, and throw IllegalStateException?
optional("jakarta.websocket:jakarta.websocket-api") optional("jakarta.websocket:jakarta.websocket-client-api")