From 7d65183e2c20b92991b60c9dac6293d6aeb9cc4a Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Fri, 13 Dec 2019 13:44:57 -0600 Subject: [PATCH 1/7] Issue #3730 - Cleaning up Scopes in WebSocketClient + Introducing HttpContainerScope to track HttpClient specific ByteBufferPool, SslContextFactory, and Executor. + New private WebSocketClient constructor that use HttpContainerScope + Deprecated many constructors as irrelevant now that HttpClient is an option to create a WebSocketClient. Signed-off-by: Joakim Erdfelt --- .../websocket/jsr356/ClientContainer.java | 3 +- .../websocket/client/HttpContainerScope.java | 119 ++++++++++++++++++ .../websocket/client/WebSocketClient.java | 91 +++++++++----- 3 files changed, 184 insertions(+), 29 deletions(-) create mode 100644 jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java index 0e1bb7f1e72e..7b342ce552f1 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java @@ -52,6 +52,7 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; +import org.eclipse.jetty.websocket.client.HttpContainerScope; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.io.UpgradeListener; import org.eclipse.jetty.websocket.common.WebSocketSession; @@ -123,7 +124,7 @@ public ClientContainer() */ public ClientContainer(final HttpClient httpClient) { - this(new SimpleContainerScope(WebSocketPolicy.newClientPolicy()), httpClient); + this(new HttpContainerScope(httpClient)); } /** diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java new file mode 100644 index 000000000000..2377ef403416 --- /dev/null +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java @@ -0,0 +1,119 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.websocket.client; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Executor; + +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.util.DecoratedObjectFactory; +import org.eclipse.jetty.util.component.ContainerLifeCycle; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.WebSocketSessionListener; +import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; + +/** + * A simple Scope that is focused around a HttpClient, DecoratedObjectFactory, and Client WebSocketPolicy. + */ +public class HttpContainerScope extends ContainerLifeCycle implements WebSocketContainerScope +{ + private final HttpClient httpClient; + private final DecoratedObjectFactory decoratedObjectFactory; + private final WebSocketPolicy webSocketPolicy; + private List sessionListeners = new ArrayList<>(); + + public HttpContainerScope(HttpClient httpClient) + { + this(httpClient, new DecoratedObjectFactory()); + } + + public HttpContainerScope(HttpClient httpClient, DecoratedObjectFactory decoratedObjectFactory) + { + this.httpClient = Objects.requireNonNull(httpClient, "HttpClient"); + this.decoratedObjectFactory = decoratedObjectFactory != null ? decoratedObjectFactory : new DecoratedObjectFactory(); + this.webSocketPolicy = WebSocketPolicy.newClientPolicy(); + } + + public HttpContainerScope(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool, DecoratedObjectFactory decoratedObjectFactory) + { + this.httpClient = new HttpClient(sslContextFactory); + this.httpClient.setExecutor(executor); + this.httpClient.setByteBufferPool(bufferPool); + this.decoratedObjectFactory = decoratedObjectFactory != null ? decoratedObjectFactory : new DecoratedObjectFactory(); + this.webSocketPolicy = WebSocketPolicy.newClientPolicy(); + } + + public HttpClient getHttpClient() + { + return httpClient; + } + + @Override + public ByteBufferPool getBufferPool() + { + return httpClient.getByteBufferPool(); + } + + @Override + public Executor getExecutor() + { + return httpClient.getExecutor(); + } + + @Override + public DecoratedObjectFactory getObjectFactory() + { + return decoratedObjectFactory; + } + + @Override + public WebSocketPolicy getPolicy() + { + return webSocketPolicy; + } + + @Override + public SslContextFactory getSslContextFactory() + { + return httpClient.getSslContextFactory(); + } + + @Override + public void addSessionListener(WebSocketSessionListener listener) + { + this.sessionListeners.add(listener); + } + + @Override + public void removeSessionListener(WebSocketSessionListener listener) + { + this.sessionListeners.remove(listener); + } + + @Override + public Collection getSessionListeners() + { + return sessionListeners; + } +} diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index 2d2e8e518c01..20b6a1784bcf 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -58,7 +58,6 @@ import org.eclipse.jetty.websocket.common.WebSocketSessionListener; import org.eclipse.jetty.websocket.common.events.EventDriverFactory; import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; /** @@ -86,21 +85,24 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont private boolean stopAtShutdown = true; /** - * Instantiate a WebSocketClient with defaults + * Instantiate a WebSocketClient with defaults. */ public WebSocketClient() { - this((HttpClient)null); + this(new HttpContainerScope(HttpClientProvider.get(null))); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** - * Instantiate a WebSocketClient using HttpClient for defaults + * Instantiate a WebSocketClient using provided HttpClient. * - * @param httpClient the HttpClient to base internal defaults off of + * @param httpClient the HttpClient to use for WebSocketClient. */ public WebSocketClient(HttpClient httpClient) { - this(httpClient, null); + // Use external HttpClient + this(new HttpContainerScope(Objects.requireNonNull(httpClient))); } /** @@ -111,37 +113,50 @@ public WebSocketClient(HttpClient httpClient) */ public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory objectFactory) { - this(new SimpleContainerScope(new WebSocketPolicy(WebSocketBehavior.CLIENT), null, null, null, objectFactory), null, null, httpClient); + // Use external HttpClient + this(new HttpContainerScope(Objects.requireNonNull(httpClient), objectFactory)); } /** * Create a new WebSocketClient * * @param sslContextFactory ssl context factory to use on the internal {@link HttpClient} + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(SslContextFactory sslContextFactory) { - this(sslContextFactory, null, null); + this(new HttpContainerScope(sslContextFactory, null, null, null)); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** * Create a new WebSocketClient * * @param executor the executor to use on the internal {@link HttpClient} + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(Executor executor) { - this(null, executor, null); + this(new HttpContainerScope(null, executor, null, null)); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** * Create a new WebSocketClient * * @param bufferPool byte buffer pool to use on the internal {@link HttpClient} + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(ByteBufferPool bufferPool) { - this(null, null, bufferPool); + this(new HttpContainerScope(null, null, bufferPool, null)); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** @@ -149,10 +164,14 @@ public WebSocketClient(ByteBufferPool bufferPool) * * @param sslContextFactory ssl context factory to use on the internal {@link HttpClient} * @param executor the executor to use on the internal {@link HttpClient} + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) { - this(sslContextFactory, executor, null); + this(new HttpContainerScope(sslContextFactory, executor, null, null)); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** @@ -173,10 +192,14 @@ public WebSocketClient(WebSocketContainerScope scope) * @param scope the Container Scope * @param sslContextFactory SSL ContextFactory to use in preference to one from * {@link WebSocketContainerScope#getSslContextFactory()} + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslContextFactory) { - this(sslContextFactory, scope.getExecutor(), scope.getBufferPool(), scope.getObjectFactory()); + this(new HttpContainerScope(sslContextFactory, scope.getExecutor(), scope.getBufferPool(), scope.getObjectFactory())); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** @@ -186,24 +209,13 @@ public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslConte * @param sslContextFactory shared SSL ContextFactory * @param executor shared Executor * @param bufferPool shared ByteBufferPool + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) { - this(sslContextFactory, executor, bufferPool, null); - } - - /** - * Create WebSocketClient using sharing instances of SSLContextFactory - * Executor, and ByteBufferPool - * - * @param sslContextFactory shared SSL ContextFactory - * @param executor shared Executor - * @param bufferPool shared ByteBufferPool - * @param objectFactory shared DecoratedObjectFactory - */ - private WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool, DecoratedObjectFactory objectFactory) - { - this(new SimpleContainerScope(new WebSocketPolicy(WebSocketBehavior.CLIENT), bufferPool, executor, sslContextFactory, objectFactory)); + this(new HttpContainerScope(sslContextFactory, executor, bufferPool, null)); + // Add as bean, as HttpClient was created in this class addBean(this.httpClient); } @@ -214,10 +226,14 @@ private WebSocketClient(SslContextFactory sslContextFactory, Executor executor, * @param scope the Container Scope * @param eventDriverFactory the EventDriver Factory to use * @param sessionFactory the SessionFactory to use + * @deprecated use {@link WebSocketClient#WebSocketClient(WebSocketContainerScope, EventDriverFactory, SessionFactory, HttpClient)} instead */ + @Deprecated public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory eventDriverFactory, SessionFactory sessionFactory) { - this(scope, eventDriverFactory, sessionFactory, null); + this(scope, eventDriverFactory, sessionFactory, HttpClientProvider.get(scope)); + // Add as bean, as HttpClient was created in this class + addBean(this.httpClient); } /** @@ -234,6 +250,7 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e if (httpClient == null) { this.httpClient = HttpClientProvider.get(scope); + // Add as bean, as HttpClient was created in this class addBean(this.httpClient); } else @@ -255,6 +272,24 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e this.sessionFactory = sessionFactory == null ? new WebSocketSessionFactory(this) : sessionFactory; } + WebSocketClient(final HttpContainerScope httpContainerScope) + { + this.httpClient = httpContainerScope.getHttpClient(); + + addBean(sessionTracker); + addSessionListener(sessionTracker); + + // Ensure we get a Client version of the policy. + this.policy = httpContainerScope.getPolicy(); + // Support Late Binding of Object Factory (for CDI) + this.objectFactorySupplier = httpContainerScope::getObjectFactory; + this.extensionRegistry = new WebSocketExtensionFactory(this); + addBean(extensionRegistry); + + this.eventDriverFactory = new EventDriverFactory(this); + this.sessionFactory = new WebSocketSessionFactory(this); + } + public Future connect(Object websocket, URI toUri) throws IOException { ClientUpgradeRequest request = new ClientUpgradeRequest(toUri); From 9da1820f13ca83af9b7be2a84b70cb141850de23 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 18 Dec 2019 14:38:37 -0600 Subject: [PATCH 2/7] Issue #3730 - Removing HttpContainerScope Signed-off-by: Joakim Erdfelt --- .../websocket/jsr356/ClientContainer.java | 3 +- .../websocket/client/HttpContainerScope.java | 119 ------------------ .../websocket/client/WebSocketClient.java | 82 ++++++++---- 3 files changed, 58 insertions(+), 146 deletions(-) delete mode 100644 jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java index 7b342ce552f1..a3e8f20abf24 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java @@ -52,7 +52,6 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; -import org.eclipse.jetty.websocket.client.HttpContainerScope; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.client.io.UpgradeListener; import org.eclipse.jetty.websocket.common.WebSocketSession; @@ -124,7 +123,7 @@ public ClientContainer() */ public ClientContainer(final HttpClient httpClient) { - this(new HttpContainerScope(httpClient)); + this(new WebSocketClient(httpClient)); } /** diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java deleted file mode 100644 index 2377ef403416..000000000000 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/HttpContainerScope.java +++ /dev/null @@ -1,119 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.Executor; - -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.util.DecoratedObjectFactory; -import org.eclipse.jetty.util.component.ContainerLifeCycle; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.WebSocketSessionListener; -import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; - -/** - * A simple Scope that is focused around a HttpClient, DecoratedObjectFactory, and Client WebSocketPolicy. - */ -public class HttpContainerScope extends ContainerLifeCycle implements WebSocketContainerScope -{ - private final HttpClient httpClient; - private final DecoratedObjectFactory decoratedObjectFactory; - private final WebSocketPolicy webSocketPolicy; - private List sessionListeners = new ArrayList<>(); - - public HttpContainerScope(HttpClient httpClient) - { - this(httpClient, new DecoratedObjectFactory()); - } - - public HttpContainerScope(HttpClient httpClient, DecoratedObjectFactory decoratedObjectFactory) - { - this.httpClient = Objects.requireNonNull(httpClient, "HttpClient"); - this.decoratedObjectFactory = decoratedObjectFactory != null ? decoratedObjectFactory : new DecoratedObjectFactory(); - this.webSocketPolicy = WebSocketPolicy.newClientPolicy(); - } - - public HttpContainerScope(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool, DecoratedObjectFactory decoratedObjectFactory) - { - this.httpClient = new HttpClient(sslContextFactory); - this.httpClient.setExecutor(executor); - this.httpClient.setByteBufferPool(bufferPool); - this.decoratedObjectFactory = decoratedObjectFactory != null ? decoratedObjectFactory : new DecoratedObjectFactory(); - this.webSocketPolicy = WebSocketPolicy.newClientPolicy(); - } - - public HttpClient getHttpClient() - { - return httpClient; - } - - @Override - public ByteBufferPool getBufferPool() - { - return httpClient.getByteBufferPool(); - } - - @Override - public Executor getExecutor() - { - return httpClient.getExecutor(); - } - - @Override - public DecoratedObjectFactory getObjectFactory() - { - return decoratedObjectFactory; - } - - @Override - public WebSocketPolicy getPolicy() - { - return webSocketPolicy; - } - - @Override - public SslContextFactory getSslContextFactory() - { - return httpClient.getSslContextFactory(); - } - - @Override - public void addSessionListener(WebSocketSessionListener listener) - { - this.sessionListeners.add(listener); - } - - @Override - public void removeSessionListener(WebSocketSessionListener listener) - { - this.sessionListeners.remove(listener); - } - - @Override - public Collection getSessionListeners() - { - return sessionListeners; - } -} diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index 20b6a1784bcf..a5598f04b601 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -89,8 +89,8 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont */ public WebSocketClient() { - this(new HttpContainerScope(HttpClientProvider.get(null))); - // Add as bean, as HttpClient was created in this class + this(null, HttpClientProvider.get(null)); + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -102,7 +102,7 @@ public WebSocketClient() public WebSocketClient(HttpClient httpClient) { // Use external HttpClient - this(new HttpContainerScope(Objects.requireNonNull(httpClient))); + this(null, Objects.requireNonNull(httpClient)); } /** @@ -114,7 +114,7 @@ public WebSocketClient(HttpClient httpClient) public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory objectFactory) { // Use external HttpClient - this(new HttpContainerScope(Objects.requireNonNull(httpClient), objectFactory)); + this(objectFactory, Objects.requireNonNull(httpClient)); } /** @@ -126,8 +126,8 @@ public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory objectFacto @Deprecated public WebSocketClient(SslContextFactory sslContextFactory) { - this(new HttpContainerScope(sslContextFactory, null, null, null)); - // Add as bean, as HttpClient was created in this class + this(null, newHttpClient(sslContextFactory, null, null)); + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -140,8 +140,8 @@ public WebSocketClient(SslContextFactory sslContextFactory) @Deprecated public WebSocketClient(Executor executor) { - this(new HttpContainerScope(null, executor, null, null)); - // Add as bean, as HttpClient was created in this class + this(null, newHttpClient(null, executor, null)); + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -154,8 +154,8 @@ public WebSocketClient(Executor executor) @Deprecated public WebSocketClient(ByteBufferPool bufferPool) { - this(new HttpContainerScope(null, null, bufferPool, null)); - // Add as bean, as HttpClient was created in this class + this(null, newHttpClient(null, null, bufferPool)); + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -169,8 +169,8 @@ public WebSocketClient(ByteBufferPool bufferPool) @Deprecated public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) { - this(new HttpContainerScope(sslContextFactory, executor, null, null)); - // Add as bean, as HttpClient was created in this class + this(null, newHttpClient(sslContextFactory, executor, null)); + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -182,7 +182,9 @@ public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) */ public WebSocketClient(WebSocketContainerScope scope) { - this(scope, null, null, null); + this(scope.getObjectFactory(), newHttpClient(scope.getSslContextFactory(), scope.getExecutor(), scope.getBufferPool())); + // Add as bean, as HttpClient was created in this constructor + addBean(this.httpClient); } /** @@ -197,8 +199,18 @@ public WebSocketClient(WebSocketContainerScope scope) @Deprecated public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslContextFactory) { - this(new HttpContainerScope(sslContextFactory, scope.getExecutor(), scope.getBufferPool(), scope.getObjectFactory())); - // Add as bean, as HttpClient was created in this class + /* This is constructor is in an awful place, it's got a signature that has a scope, + * a concept that javax.websocket ServerContainer uses to share its buffer pools / executors / etc + * with the underlying HttpClient. + * This means that the constructor should go through the HttpClientProvider.get(scope) behaviors. + * but it also has an arbitrary SslContextFactory parameter, which isn't in the scope that + * HttpClientProvider uses. + * Since this isn't used by Jetty's implementation of the javax.websocket ServerContainer + * this behavior has been changed to be non-scoped so as to be able to use the provided + * SslContextFactory for the underlying HttpClient instance. + */ + this(scope.getObjectFactory(), newHttpClient(sslContextFactory, scope.getExecutor(), scope.getBufferPool())); + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -214,7 +226,7 @@ public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslConte @Deprecated public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) { - this(new HttpContainerScope(sslContextFactory, executor, bufferPool, null)); + this(null, newHttpClient(sslContextFactory, executor, bufferPool)); // Add as bean, as HttpClient was created in this class addBean(this.httpClient); } @@ -231,8 +243,11 @@ public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, B @Deprecated public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory eventDriverFactory, SessionFactory sessionFactory) { + /* Nothing in Jetty uses this constructor anymore. + * It's left in for backwards compat reasons. + */ this(scope, eventDriverFactory, sessionFactory, HttpClientProvider.get(scope)); - // Add as bean, as HttpClient was created in this class + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -250,7 +265,7 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e if (httpClient == null) { this.httpClient = HttpClientProvider.get(scope); - // Add as bean, as HttpClient was created in this class + // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } else @@ -263,8 +278,9 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e // Ensure we get a Client version of the policy. this.policy = scope.getPolicy().delegateAs(WebSocketBehavior.CLIENT); - // Support Late Binding of Object Factory (for CDI) + // Support Late Binding of DecoratedObjectFactory (that CDI establishes in its own servlet context listeners) this.objectFactorySupplier = () -> scope.getObjectFactory(); + this.extensionRegistry = new WebSocketExtensionFactory(this); addBean(extensionRegistry); @@ -272,17 +288,25 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e this.sessionFactory = sessionFactory == null ? new WebSocketSessionFactory(this) : sessionFactory; } - WebSocketClient(final HttpContainerScope httpContainerScope) + /** + * Internal constructor (not public) + * + * @param decoratedObjectFactory the decorated Object Factory to use + * @param httpClient the HttpClient underpinnings + */ + WebSocketClient(DecoratedObjectFactory decoratedObjectFactory, HttpClient httpClient) { - this.httpClient = httpContainerScope.getHttpClient(); + this.httpClient = httpClient; addBean(sessionTracker); addSessionListener(sessionTracker); - // Ensure we get a Client version of the policy. - this.policy = httpContainerScope.getPolicy(); - // Support Late Binding of Object Factory (for CDI) - this.objectFactorySupplier = httpContainerScope::getObjectFactory; + // Always a pristine Client policy + this.policy = WebSocketPolicy.newClientPolicy(); + // We do not support late binding of DecoratedObjectFactory in this WebSocketClient + DecoratedObjectFactory objectFactory = decoratedObjectFactory == null ? new DecoratedObjectFactory() : decoratedObjectFactory; + this.objectFactorySupplier = () -> objectFactory; + this.extensionRegistry = new WebSocketExtensionFactory(this); addBean(extensionRegistry); @@ -290,6 +314,14 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e this.sessionFactory = new WebSocketSessionFactory(this); } + public static HttpClient newHttpClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) + { + HttpClient httpClient = new HttpClient(sslContextFactory); + httpClient.setExecutor(executor); + httpClient.setByteBufferPool(bufferPool); + return httpClient; + } + public Future connect(Object websocket, URI toUri) throws IOException { ClientUpgradeRequest request = new ClientUpgradeRequest(toUri); From e02ef3efdde3f61b882810058cbd1820ca7ad04a Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 18 Dec 2019 14:43:53 -0600 Subject: [PATCH 3/7] Issue #3730 - Making new Constructor private Signed-off-by: Joakim Erdfelt --- .../org/eclipse/jetty/websocket/client/WebSocketClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index a5598f04b601..835bd33e5e08 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -294,7 +294,7 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e * @param decoratedObjectFactory the decorated Object Factory to use * @param httpClient the HttpClient underpinnings */ - WebSocketClient(DecoratedObjectFactory decoratedObjectFactory, HttpClient httpClient) + private WebSocketClient(DecoratedObjectFactory decoratedObjectFactory, HttpClient httpClient) { this.httpClient = httpClient; From bb79f3e6e0da04306d59e1bc10aa2cec449c0525 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 18 Dec 2019 15:33:23 -0600 Subject: [PATCH 4/7] Issue #3730 - Collapsing now redundant private Constructor Signed-off-by: Joakim Erdfelt --- .../websocket/client/WebSocketClient.java | 68 ++++++++----------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index 835bd33e5e08..2caebf779f22 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -89,7 +89,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont */ public WebSocketClient() { - this(null, HttpClientProvider.get(null)); + this(HttpClientProvider.get(null), null); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -102,19 +102,33 @@ public WebSocketClient() public WebSocketClient(HttpClient httpClient) { // Use external HttpClient - this(null, Objects.requireNonNull(httpClient)); + this(Objects.requireNonNull(httpClient), null); } /** * Instantiate a WebSocketClient using HttpClient for defaults * - * @param httpClient the HttpClient to base internal defaults off of - * @param objectFactory the DecoratedObjectFactory for all client instantiated classes + * @param httpClient the HttpClient that underlying WebSocket client uses + * @param decoratedObjectFactory the DecoratedObjectFactory for all client instantiated classes */ - public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory objectFactory) + public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory decoratedObjectFactory) { - // Use external HttpClient - this(objectFactory, Objects.requireNonNull(httpClient)); + this.httpClient = httpClient; + + addBean(sessionTracker); + addSessionListener(sessionTracker); + + // Always a pristine Client policy + this.policy = WebSocketPolicy.newClientPolicy(); + // We do not support late binding of DecoratedObjectFactory in this WebSocketClient + DecoratedObjectFactory objectFactory = decoratedObjectFactory == null ? new DecoratedObjectFactory() : decoratedObjectFactory; + this.objectFactorySupplier = () -> objectFactory; + + this.extensionRegistry = new WebSocketExtensionFactory(this); + addBean(extensionRegistry); + + this.eventDriverFactory = new EventDriverFactory(this); + this.sessionFactory = new WebSocketSessionFactory(this); } /** @@ -126,7 +140,7 @@ public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory objectFacto @Deprecated public WebSocketClient(SslContextFactory sslContextFactory) { - this(null, newHttpClient(sslContextFactory, null, null)); + this(newHttpClient(sslContextFactory, null, null), null); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -140,7 +154,7 @@ public WebSocketClient(SslContextFactory sslContextFactory) @Deprecated public WebSocketClient(Executor executor) { - this(null, newHttpClient(null, executor, null)); + this(newHttpClient(null, executor, null), null); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -154,7 +168,7 @@ public WebSocketClient(Executor executor) @Deprecated public WebSocketClient(ByteBufferPool bufferPool) { - this(null, newHttpClient(null, null, bufferPool)); + this(newHttpClient(null, null, bufferPool), null); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -169,7 +183,7 @@ public WebSocketClient(ByteBufferPool bufferPool) @Deprecated public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) { - this(null, newHttpClient(sslContextFactory, executor, null)); + this(newHttpClient(sslContextFactory, executor, null), null); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -182,7 +196,7 @@ public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) */ public WebSocketClient(WebSocketContainerScope scope) { - this(scope.getObjectFactory(), newHttpClient(scope.getSslContextFactory(), scope.getExecutor(), scope.getBufferPool())); + this(newHttpClient(scope.getSslContextFactory(), scope.getExecutor(), scope.getBufferPool()), scope.getObjectFactory()); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -209,7 +223,7 @@ public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslConte * this behavior has been changed to be non-scoped so as to be able to use the provided * SslContextFactory for the underlying HttpClient instance. */ - this(scope.getObjectFactory(), newHttpClient(sslContextFactory, scope.getExecutor(), scope.getBufferPool())); + this(newHttpClient(sslContextFactory, scope.getExecutor(), scope.getBufferPool()), scope.getObjectFactory()); // Add as bean, as HttpClient was created in this constructor addBean(this.httpClient); } @@ -226,7 +240,7 @@ public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslConte @Deprecated public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) { - this(null, newHttpClient(sslContextFactory, executor, bufferPool)); + this(newHttpClient(sslContextFactory, executor, bufferPool), null); // Add as bean, as HttpClient was created in this class addBean(this.httpClient); } @@ -288,32 +302,6 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e this.sessionFactory = sessionFactory == null ? new WebSocketSessionFactory(this) : sessionFactory; } - /** - * Internal constructor (not public) - * - * @param decoratedObjectFactory the decorated Object Factory to use - * @param httpClient the HttpClient underpinnings - */ - private WebSocketClient(DecoratedObjectFactory decoratedObjectFactory, HttpClient httpClient) - { - this.httpClient = httpClient; - - addBean(sessionTracker); - addSessionListener(sessionTracker); - - // Always a pristine Client policy - this.policy = WebSocketPolicy.newClientPolicy(); - // We do not support late binding of DecoratedObjectFactory in this WebSocketClient - DecoratedObjectFactory objectFactory = decoratedObjectFactory == null ? new DecoratedObjectFactory() : decoratedObjectFactory; - this.objectFactorySupplier = () -> objectFactory; - - this.extensionRegistry = new WebSocketExtensionFactory(this); - addBean(extensionRegistry); - - this.eventDriverFactory = new EventDriverFactory(this); - this.sessionFactory = new WebSocketSessionFactory(this); - } - public static HttpClient newHttpClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) { HttpClient httpClient = new HttpClient(sslContextFactory); From 94988596a1684ef787f54dbcaf0a077c60305db2 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 19 Dec 2019 12:33:43 -0600 Subject: [PATCH 5/7] Issue #3730 - Further updates from PR Review Signed-off-by: Joakim Erdfelt --- .../websocket/jsr356/ClientContainer.java | 6 +-- .../websocket/client/WebSocketClient.java | 43 +++++-------------- 2 files changed, 11 insertions(+), 38 deletions(-) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java index a3e8f20abf24..1a1c6181e42c 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java @@ -57,7 +57,6 @@ import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.WebSocketSessionListener; import org.eclipse.jetty.websocket.common.scopes.DelegatedContainerScope; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; import org.eclipse.jetty.websocket.jsr356.client.AnnotatedClientEndpointMetadata; @@ -109,9 +108,7 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont public ClientContainer() { // This constructor is used with Standalone JSR Client usage. - this(new SimpleContainerScope(WebSocketPolicy.newClientPolicy())); - client.setDaemon(true); - client.addManaged(client.getHttpClient()); + this(new WebSocketClient()); } /** @@ -134,7 +131,6 @@ public ClientContainer(final HttpClient httpClient) public ClientContainer(final WebSocketContainerScope scope) { this(scope, null); - client.addManaged(client.getHttpClient()); } /** diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index 2caebf779f22..553baf457f68 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -90,8 +90,6 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont public WebSocketClient() { this(HttpClientProvider.get(null), null); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -101,8 +99,7 @@ public WebSocketClient() */ public WebSocketClient(HttpClient httpClient) { - // Use external HttpClient - this(Objects.requireNonNull(httpClient), null); + this(httpClient, null); } /** @@ -113,8 +110,9 @@ public WebSocketClient(HttpClient httpClient) */ public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory decoratedObjectFactory) { - this.httpClient = httpClient; + this.httpClient = Objects.requireNonNull(httpClient, "HttpClient"); + addBean(httpClient); addBean(sessionTracker); addSessionListener(sessionTracker); @@ -141,8 +139,6 @@ public WebSocketClient(HttpClient httpClient, DecoratedObjectFactory decoratedOb public WebSocketClient(SslContextFactory sslContextFactory) { this(newHttpClient(sslContextFactory, null, null), null); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -155,8 +151,6 @@ public WebSocketClient(SslContextFactory sslContextFactory) public WebSocketClient(Executor executor) { this(newHttpClient(null, executor, null), null); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -169,8 +163,6 @@ public WebSocketClient(Executor executor) public WebSocketClient(ByteBufferPool bufferPool) { this(newHttpClient(null, null, bufferPool), null); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -184,8 +176,6 @@ public WebSocketClient(ByteBufferPool bufferPool) public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) { this(newHttpClient(sslContextFactory, executor, null), null); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -193,12 +183,12 @@ public WebSocketClient(SslContextFactory sslContextFactory, Executor executor) * internal features like Executor, ByteBufferPool, SSLContextFactory, etc. * * @param scope the Container Scope + * @deprecated use {@link #WebSocketClient(HttpClient)} instead */ + @Deprecated public WebSocketClient(WebSocketContainerScope scope) { this(newHttpClient(scope.getSslContextFactory(), scope.getExecutor(), scope.getBufferPool()), scope.getObjectFactory()); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -224,8 +214,6 @@ public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslConte * SslContextFactory for the underlying HttpClient instance. */ this(newHttpClient(sslContextFactory, scope.getExecutor(), scope.getBufferPool()), scope.getObjectFactory()); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -241,8 +229,6 @@ public WebSocketClient(WebSocketContainerScope scope, SslContextFactory sslConte public WebSocketClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) { this(newHttpClient(sslContextFactory, executor, bufferPool), null); - // Add as bean, as HttpClient was created in this class - addBean(this.httpClient); } /** @@ -261,8 +247,6 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e * It's left in for backwards compat reasons. */ this(scope, eventDriverFactory, sessionFactory, HttpClientProvider.get(scope)); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); } /** @@ -276,24 +260,17 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e */ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory eventDriverFactory, SessionFactory sessionFactory, HttpClient httpClient) { - if (httpClient == null) - { - this.httpClient = HttpClientProvider.get(scope); - // Add as bean, as HttpClient was created in this constructor - addBean(this.httpClient); - } - else - { - this.httpClient = httpClient; - } + this.httpClient = httpClient == null ? HttpClientProvider.get(scope) : httpClient; + addBean(this.httpClient); addBean(sessionTracker); addSessionListener(sessionTracker); // Ensure we get a Client version of the policy. this.policy = scope.getPolicy().delegateAs(WebSocketBehavior.CLIENT); + // Support Late Binding of DecoratedObjectFactory (that CDI establishes in its own servlet context listeners) - this.objectFactorySupplier = () -> scope.getObjectFactory(); + this.objectFactorySupplier = scope::getObjectFactory; this.extensionRegistry = new WebSocketExtensionFactory(this); addBean(extensionRegistry); @@ -302,7 +279,7 @@ public WebSocketClient(final WebSocketContainerScope scope, EventDriverFactory e this.sessionFactory = sessionFactory == null ? new WebSocketSessionFactory(this) : sessionFactory; } - public static HttpClient newHttpClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) + private static HttpClient newHttpClient(SslContextFactory sslContextFactory, Executor executor, ByteBufferPool bufferPool) { HttpClient httpClient = new HttpClient(sslContextFactory); httpClient.setExecutor(executor); From 26fde02c551b78d65e9e59973e192dcdb57d2320 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 19 Dec 2019 12:43:49 -0600 Subject: [PATCH 6/7] Issue #3730 - Updating invalid test assertion Signed-off-by: Joakim Erdfelt --- .../eclipse/jetty/websocket/client/WebSocketClientInitTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientInitTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientInitTest.java index 82b4c677417e..3f66da51f767 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientInitTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientInitTest.java @@ -55,7 +55,6 @@ public void testInit_HttpClient_StartedOutside() throws Exception assertThat("HttpClient started", http.isStarted(), is(true)); HttpClient httpBean = ws.getBean(HttpClient.class); - assertThat("HttpClient should not be found in WebSocketClient", httpBean, nullValue()); assertThat("HttpClient bean is managed", ws.isManaged(httpBean), is(false)); assertThat("WebSocketClient should not be found in HttpClient", http.getBean(WebSocketClient.class), nullValue()); } From c2c2c56a026d1f4d124ce89493fe9c85f57945e7 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Thu, 19 Dec 2019 13:46:12 -0600 Subject: [PATCH 7/7] Issue #3730 - EventDriverFactory and SessionFactory setters Signed-off-by: Joakim Erdfelt --- .../jetty/websocket/jsr356/ClientContainer.java | 4 ++++ .../jetty/websocket/client/WebSocketClient.java | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java index 1a1c6181e42c..46d1f4878a60 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/ClientContainer.java @@ -183,8 +183,12 @@ protected ClientContainer(final WebSocketContainerScope scope, final HttpClient */ public ClientContainer(WebSocketClient client) { + Objects.requireNonNull(client, "WebSocketClient"); this.scopeDelegate = client; this.client = client; + addBean(this.client); + this.client.setEventDriverFactory(new JsrEventDriverFactory(scopeDelegate)); + this.client.setSessionFactory(new JsrSessionFactory(this)); this.internalClient = false; this.endpointClientMetadataCache = new ConcurrentHashMap<>(); diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index 553baf457f68..28e9cb58f2c4 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -76,10 +76,10 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont // WebSocket Specifics private final WebSocketPolicy policy; private final WebSocketExtensionFactory extensionRegistry; - private final EventDriverFactory eventDriverFactory; - private final SessionFactory sessionFactory; private final SessionTracker sessionTracker = new SessionTracker(); private final List sessionListeners = new ArrayList<>(); + private EventDriverFactory eventDriverFactory; + private SessionFactory sessionFactory; // defaults to true for backwards compatibility private boolean stopAtShutdown = true; @@ -379,6 +379,16 @@ public Future connect(Object websocket, URI toUri, ClientUpgradeRequest return wsReq.sendAsync(); } + public void setEventDriverFactory(EventDriverFactory eventDriverFactory) + { + this.eventDriverFactory = eventDriverFactory; + } + + public void setSessionFactory(SessionFactory sessionFactory) + { + this.sessionFactory = sessionFactory; + } + @Override protected void doStart() throws Exception {