GH-8600: Fix WebSocket removeRegistration (#8601)

* GH-8600: Fix WebSocket `removeRegistration`

Fixes https://github.com/spring-projects/spring-integration/issues/8600

When we register a dynamic WebSocket endpoint and use a `WebSocketHandlerDecoratorFactory`
such an endpoint is not removed on an `IntegrationFlow` destruction.
The actual `WebSocketHandler` is decorated, however we still use an initial one
for condition.

* Refactor `IntegrationWebSocketContainer` to expose a `protected` setter for the
`WebSocketHandler` which is called from the `ServerWebSocketContainer` after decoration

**Cherry-pick to `6.0.x` & `5.5.x`**

* Fix language in Javadocs

Co-authored-by: Gary Russell <grussell@vmware.com>

---------

Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
Artem Bilan
2023-04-19 12:54:00 -04:00
committed by GitHub
parent 934e90a110
commit 1a579a6492
4 changed files with 33 additions and 10 deletions

View File

@@ -208,7 +208,7 @@ public final class ClientWebSocketContainer extends IntegrationWebSocketContaine
* <p>
* Opened {@link WebSocketSession} is populated to the wrapping {@link ClientWebSocketContainer}.
* <p>
* The {@link #webSocketHandler} is used to handle {@link WebSocketSession} events.
* The {@link #getWebSocketHandler()} is used to handle {@link WebSocketSession} events.
*/
private final class IntegrationWebSocketConnectionManager extends ConnectionManagerSupport {
@@ -258,8 +258,7 @@ public final class ClientWebSocketContainer extends IntegrationWebSocketContaine
}
ClientWebSocketContainer.this.headers.setSecWebSocketProtocol(getSubProtocols());
CompletableFuture<WebSocketSession> future =
this.client.execute(ClientWebSocketContainer.this.webSocketHandler,
ClientWebSocketContainer.this.headers, getUri());
this.client.execute(getWebSocketHandler(), ClientWebSocketContainer.this.headers, getUri());
future.whenComplete((session, throwable) -> {
if (throwable == null) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 the original author or authors.
* Copyright 2014-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,8 +67,8 @@ public abstract class IntegrationWebSocketContainer implements DisposableBean {
protected final Log logger = LogFactory.getLog(getClass()); // NOSONAR
protected final WebSocketHandler webSocketHandler = new IntegrationWebSocketHandler(); // NOSONAR
private WebSocketHandler webSocketHandler = new IntegrationWebSocketHandler();
protected final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>(); // NOSONAR
private final List<String> supportedProtocols = new ArrayList<>();
@@ -104,6 +104,15 @@ public abstract class IntegrationWebSocketContainer implements DisposableBean {
}
}
/**
* Replace the default {@link WebSocketHandler} with the one provided here, e.g. via decoration factories.
* @param handler the actual {@link WebSocketHandler} to replace.
* @since 5.5.18
*/
protected void setWebSocketHandler(WebSocketHandler handler) {
this.webSocketHandler = handler;
}
public WebSocketHandler getWebSocketHandler() {
return this.webSocketHandler;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 the original author or authors.
* Copyright 2014-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -150,11 +150,12 @@ public class ServerWebSocketContainer extends IntegrationWebSocketContainer
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
WebSocketHandler webSocketHandler = this.webSocketHandler;
WebSocketHandler webSocketHandler = getWebSocketHandler();
if (this.decoratorFactories != null) {
for (WebSocketHandlerDecoratorFactory factory : this.decoratorFactories) {
webSocketHandler = factory.decorate(webSocketHandler);
setWebSocketHandler(webSocketHandler);
}
}