From fe9b59ea01ef91d82cd972b3e1800655149de349 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 22 Feb 2023 14:05:53 -0500 Subject: [PATCH] GH-3813: ClientWebSocketContainer URI setting (#8561) * GH-3813: ClientWebSocketContainer URI setting Fixes https://github.com/spring-projects/spring-integration/issues/3813 Introduce a `ClientWebSocketContainer(WebSocketClient client, URI uri)` ctor to let end-user to decide what and how should be encoded the URI for WebSocket connection * Fix language in docs Co-authored-by: Gary Russell --------- Co-authored-by: Gary Russell --- .../websocket/ClientWebSocketContainer.java | 27 +++++++++++++++---- .../ClientWebSocketContainerTests.java | 4 +-- src/reference/asciidoc/web-sockets.adoc | 6 ++++- src/reference/asciidoc/whats-new.adoc | 7 +++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/spring-integration-websocket/src/main/java/org/springframework/integration/websocket/ClientWebSocketContainer.java b/spring-integration-websocket/src/main/java/org/springframework/integration/websocket/ClientWebSocketContainer.java index 463259df63..2ec61043c0 100644 --- a/spring-integration-websocket/src/main/java/org/springframework/integration/websocket/ClientWebSocketContainer.java +++ b/spring-integration-websocket/src/main/java/org/springframework/integration/websocket/ClientWebSocketContainer.java @@ -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. @@ -16,6 +16,7 @@ package org.springframework.integration.websocket; +import java.net.URI; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; @@ -56,14 +57,14 @@ public final class ClientWebSocketContainer extends IntegrationWebSocketContaine private final IntegrationWebSocketConnectionManager connectionManager; + private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; + private volatile CountDownLatch connectionLatch; private volatile WebSocketSession clientSession; private volatile Throwable openConnectionException; - private volatile int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; - private volatile boolean connecting; public ClientWebSocketContainer(WebSocketClient client, String uriTemplate, Object... uriVariables) { @@ -71,6 +72,17 @@ public final class ClientWebSocketContainer extends IntegrationWebSocketContaine this.connectionManager = new IntegrationWebSocketConnectionManager(client, uriTemplate, uriVariables); } + /** + * Constructor with a prepared {@link URI}. + * @param client the {@link WebSocketClient} to use. + * @param uri the url to connect to + * @since 6.1 + */ + public ClientWebSocketContainer(WebSocketClient client, URI uri) { + Assert.notNull(client, "'client' must not be null"); + this.connectionManager = new IntegrationWebSocketConnectionManager(client, uri); + } + public void setOrigin(String origin) { this.headers.setOrigin(origin); } @@ -204,13 +216,18 @@ public final class ClientWebSocketContainer extends IntegrationWebSocketContaine private final boolean syncClientLifecycle; - IntegrationWebSocketConnectionManager(WebSocketClient client, String uriTemplate, - Object... uriVariables) { + IntegrationWebSocketConnectionManager(WebSocketClient client, String uriTemplate, Object... uriVariables) { super(uriTemplate, uriVariables); this.client = client; this.syncClientLifecycle = ((client instanceof Lifecycle) && !((Lifecycle) client).isRunning()); } + IntegrationWebSocketConnectionManager(WebSocketClient client, URI uri) { + super(uri); + this.client = client; + this.syncClientLifecycle = ((client instanceof Lifecycle) && !((Lifecycle) client).isRunning()); + } + @Override public void startInternal() { if (this.syncClientLifecycle) { diff --git a/spring-integration-websocket/src/test/java/org/springframework/integration/websocket/ClientWebSocketContainerTests.java b/spring-integration-websocket/src/test/java/org/springframework/integration/websocket/ClientWebSocketContainerTests.java index a944b76193..211abc0918 100644 --- a/spring-integration-websocket/src/test/java/org/springframework/integration/websocket/ClientWebSocketContainerTests.java +++ b/spring-integration-websocket/src/test/java/org/springframework/integration/websocket/ClientWebSocketContainerTests.java @@ -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. @@ -93,7 +93,7 @@ public class ClientWebSocketContainerTests { webSocketClient.setUserProperties(userProperties); ClientWebSocketContainer container = - new ClientWebSocketContainer(webSocketClient, server.getWsBaseUrl() + "/ws/websocket"); + new ClientWebSocketContainer(webSocketClient, new URI(server.getWsBaseUrl() + "/ws/websocket")); TestWebSocketListener messageListener = new TestWebSocketListener(); container.setMessageListener(messageListener); diff --git a/src/reference/asciidoc/web-sockets.adoc b/src/reference/asciidoc/web-sockets.adoc index 437a8a0f2f..cdf0ee3057 100644 --- a/src/reference/asciidoc/web-sockets.adoc +++ b/src/reference/asciidoc/web-sockets.adoc @@ -87,6 +87,10 @@ It does so under the provided `paths` and other server WebSocket options (such a This registration is achieved with an infrastructural `WebSocketIntegrationConfigurationInitializer` component, which does the same as the `@EnableWebSocket` annotation. This means that, by using `@EnableIntegration` (or any Spring Integration namespace in the application context), you can omit the `@EnableWebSocket` declaration, because the Spring Integration infrastructure detects all WebSocket endpoints. +Starting with version 6.1, the `ClientWebSocketContainer` can be configured with a provided `URI` instead of `uriTemplate` and `uriVariables` combination. +This is useful in cases when custom encoding is required for some parts of the uri. +See an `UriComponentsBuilder` API for convenience. + [[web-socket-inbound-adapter]] === WebSocket Inbound Channel Adapter @@ -431,4 +435,4 @@ dynamicServerFlow.destroy(); NOTE: It is important to call `.addBean(serverWebSocketContainer)` on the dynamic flow registration to add the instance of `ServerWebSocketContainer` into an `ApplicationContext` for endpoint registration. When a dynamic flow registration is destroyed, the associated `ServerWebSocketContainer` instance is destroyed, too, as well as the respective endpoint registration, including URL path mappings. -IMPORTANT: The dynamic Websocket endpoints can only be registered via Spring Integration mechanism: when regular Spring `@EnableWebsocket` is used, Spring Integration configuration backs off and no infrastructure for dynamic endpoints is registered. \ No newline at end of file +IMPORTANT: The dynamic Websocket endpoints can only be registered via Spring Integration mechanism: when regular Spring `@EnableWebsocket` is used, Spring Integration configuration backs off and no infrastructure for dynamic endpoints is registered. diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index d26add490a..3ed5ce789c 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -26,3 +26,10 @@ See <<./zip.adoc#zip,Zip Support>> for more information. [[x6.1-general]] === General Changes + + +[[x6.1-web-sockets]] +=== Web Sockets Changes + +A `ClientWebSocketContainer` can now be configured with a predefined `URI` instead of a combination of `uriTemplate` and `uriVariables`. +See <<./web-sockets.adoc#web-socket-overview, WebSocket Overview>> for more information.