From 3bcb4d822943a029442cb4f016d884c21cb0dd46 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Tue, 18 Dec 2018 17:19:55 +1100 Subject: [PATCH] Issue #3167 - lazily create the WebSocketCoreClient Signed-off-by: Lachlan Roberts --- .../client/JavaxWebSocketClientContainer.java | 59 ++++++++++--------- .../server/JavaxWebSocketServerContainer.java | 34 ++++------- ...axWebSocketServerContainerInitializer.java | 15 +---- .../core/client/WebSocketCoreClient.java | 23 ++++---- 4 files changed, 55 insertions(+), 76 deletions(-) diff --git a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java index 7ba1c7fca90..b5252f940e8 100644 --- a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java +++ b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java @@ -18,6 +18,21 @@ package org.eclipse.jetty.websocket.javax.client; +import java.io.IOException; +import java.net.URI; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.Future; +import java.util.function.Supplier; +import javax.websocket.ClientEndpoint; +import javax.websocket.ClientEndpointConfig; +import javax.websocket.DeploymentException; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.Extension; +import javax.websocket.Session; + import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.util.DecoratedObjectFactory; @@ -30,20 +45,6 @@ import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketContainer; import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketExtensionConfig; import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketFrameHandlerFactory; -import javax.websocket.ClientEndpoint; -import javax.websocket.ClientEndpointConfig; -import javax.websocket.DeploymentException; -import javax.websocket.Endpoint; -import javax.websocket.EndpointConfig; -import javax.websocket.Extension; -import javax.websocket.Session; -import java.io.IOException; -import java.net.URI; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.Future; - /** * Container for Client use of the javax.websocket API. *

@@ -52,25 +53,21 @@ import java.util.concurrent.Future; @ManagedObject("JSR356 Client Container") public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer implements javax.websocket.WebSocketContainer { - protected final WebSocketCoreClient coreClient; + protected WebSocketCoreClient coreClient; + protected Supplier coreClientFactory; private final JavaxWebSocketClientFrameHandlerFactory frameHandlerFactory; - private ClassLoader contextClassLoader; private DecoratedObjectFactory objectFactory; private WebSocketExtensionRegistry extensionRegistry; public JavaxWebSocketClientContainer() { - this(new WebSocketCoreClient()); - this.coreClient.getHttpClient().setName("Javax-WebSocketClient@" + Integer.toHexString(this.coreClient.getHttpClient().hashCode())); - // We created WebSocketCoreClient, let lifecycle be managed by us - addManaged(coreClient); + this(() -> new WebSocketCoreClient()); } - public JavaxWebSocketClientContainer(HttpClient httpClient) + public JavaxWebSocketClientContainer(Supplier coreClientFactory) { - this(new WebSocketCoreClient(httpClient)); - // We created WebSocketCoreClient, let lifecycle be managed by us - addManaged(coreClient); + this((WebSocketCoreClient)null); + this.coreClientFactory = coreClientFactory; } public JavaxWebSocketClientContainer(WebSocketCoreClient coreClient) @@ -78,7 +75,6 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple super(); this.coreClient = coreClient; this.addBean(this.coreClient); - this.contextClassLoader = this.getClass().getClassLoader(); this.objectFactory = new DecoratedObjectFactory(); this.extensionRegistry = new WebSocketExtensionRegistry(); this.frameHandlerFactory = new JavaxWebSocketClientFrameHandlerFactory(this); @@ -98,11 +94,18 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple protected HttpClient getHttpClient() { - return coreClient.getHttpClient(); + return getWebSocketCoreClient().getHttpClient(); } - protected WebSocketCoreClient getWebSocketCoreClient() throws Exception + protected WebSocketCoreClient getWebSocketCoreClient() { + if (coreClient == null) + { + coreClient = coreClientFactory.get(); + this.coreClient.getHttpClient().setName("Javax-WebSocketClient@" + Integer.toHexString(this.coreClient.getHttpClient().hashCode())); + addManaged(coreClient); + } + return coreClient; } @@ -132,7 +135,7 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple Objects.requireNonNull(configuredEndpoint, "WebSocket configured endpoint cannot be null"); Objects.requireNonNull(destURI, "Destination URI cannot be null"); - ClientUpgradeRequestImpl upgradeRequest = new ClientUpgradeRequestImpl(this, coreClient, destURI, configuredEndpoint); + ClientUpgradeRequestImpl upgradeRequest = new ClientUpgradeRequestImpl(this, getWebSocketCoreClient(), destURI, configuredEndpoint); EndpointConfig config = configuredEndpoint.getConfig(); if (config != null && config instanceof ClientEndpointConfig) diff --git a/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java b/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java index f4048aec5ae..0095032d503 100644 --- a/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java +++ b/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainer.java @@ -22,7 +22,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; - import javax.websocket.DeploymentException; import javax.websocket.EndpointConfig; import javax.websocket.WebSocketContainer; @@ -40,10 +39,10 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; import org.eclipse.jetty.websocket.core.client.WebSocketCoreClient; +import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainer; +import org.eclipse.jetty.websocket.javax.common.InvalidWebSocketException; import org.eclipse.jetty.websocket.javax.server.internal.AnnotatedServerEndpointConfig; import org.eclipse.jetty.websocket.javax.server.internal.JavaxWebSocketCreator; -import org.eclipse.jetty.websocket.javax.common.InvalidWebSocketException; -import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainer; import org.eclipse.jetty.websocket.javax.server.internal.UndefinedServerEndpointConfig; import org.eclipse.jetty.websocket.servlet.WebSocketCreatorMapping; @@ -83,13 +82,20 @@ public class JavaxWebSocketServerContainer extends JavaxWebSocketClientContainer /** * Main entry point for {@link JavaxWebSocketServerContainerInitializer}. - * * @param webSocketCreatorMapping the {@link WebSocketCreatorMapping} that this container belongs to * @param httpClient the {@link HttpClient} instance to use */ public JavaxWebSocketServerContainer(WebSocketCreatorMapping webSocketCreatorMapping, HttpClient httpClient, Executor executor) { - super(new WebSocketCoreClient(httpClient)); + super(() -> + { + // TODO Can the client share the websocket or container buffer pool + WebSocketCoreClient client = new WebSocketCoreClient(httpClient); + if (executor != null && httpClient == null) + client.getHttpClient().setExecutor(executor); + + return client; + }); this._webSocketCreatorMapping = webSocketCreatorMapping; this.executor = executor; this.frameHandlerFactory = new JavaxWebSocketServerFrameHandlerFactory(this); @@ -125,24 +131,6 @@ public class JavaxWebSocketServerContainer extends JavaxWebSocketClientContainer return this._webSocketCreatorMapping.getObjectFactory(); } - @Override - protected WebSocketCoreClient getWebSocketCoreClient() throws Exception - { - // Lazy Start Http Client - if (!coreClient.getHttpClient().isStarted()) - { - coreClient.getHttpClient().start(); - } - - // Lazy Start WebSocket Client - if (!coreClient.isStarted()) - { - coreClient.start(); - } - - return coreClient; - } - @Override protected EndpointConfig newEmptyConfig(Object endpoint) { diff --git a/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainerInitializer.java b/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainerInitializer.java index 6b362c8cb45..f12c22af90a 100644 --- a/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainerInitializer.java +++ b/jetty-websocket/javax-websocket-server/src/main/java/org/eclipse/jetty/websocket/javax/server/JavaxWebSocketServerContainerInitializer.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.javax.server; import java.util.HashSet; import java.util.Set; import java.util.concurrent.Executor; - import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; @@ -153,20 +152,8 @@ public class JavaxWebSocketServerContainerInitializer implements ServletContaine if (executor == null) executor = context.getServer().getThreadPool(); - // Do we need to make a client? - if (httpClient == null) - { - // TODO Do we always need a HttpClient? - // TODO Can the client share the websocket or container buffer pool - httpClient = new HttpClient(); - httpClient.setName("Javax-WebSocketServer@" + Integer.toHexString(httpClient.hashCode())); + if (httpClient!=null && httpClient.getExecutor()==null) httpClient.setExecutor(executor); - context.addBean(httpClient, true); - } - else if (httpClient.getExecutor() == null) - { - httpClient.setExecutor(executor); - } // Create the Jetty ServerContainer implementation JavaxWebSocketServerContainer jettyContainer = new JavaxWebSocketServerContainer(webSocketCreatorMapping, httpClient, executor); diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/WebSocketCoreClient.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/WebSocketCoreClient.java index 4722d4dfdd5..982cac55536 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/WebSocketCoreClient.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/client/WebSocketCoreClient.java @@ -18,6 +18,10 @@ package org.eclipse.jetty.websocket.core.client; +import java.io.IOException; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.component.ContainerLifeCycle; @@ -29,10 +33,6 @@ import org.eclipse.jetty.websocket.core.ExtensionConfig; import org.eclipse.jetty.websocket.core.FrameHandler; import org.eclipse.jetty.websocket.core.WebSocketExtensionRegistry; -import java.io.IOException; -import java.net.URI; -import java.util.concurrent.CompletableFuture; - public class WebSocketCoreClient extends ContainerLifeCycle implements FrameHandler.CoreCustomizer { @@ -51,12 +51,7 @@ public class WebSocketCoreClient extends ContainerLifeCycle implements FrameHand public WebSocketCoreClient() { - this(new HttpClient(new SslContextFactory())); - // TODO is there more HttpClient configuration we should do by default? - httpClient.getSslContextFactory().setEndpointIdentificationAlgorithm("HTTPS"); - httpClient.setName("WSCoreClient"); - // Internally created, let websocket client's lifecycle manage it. - addManaged(httpClient); + this(null,null); } public WebSocketCoreClient(HttpClient httpClient) @@ -66,7 +61,13 @@ public class WebSocketCoreClient extends ContainerLifeCycle implements FrameHand public WebSocketCoreClient(HttpClient httpClient, FrameHandler.CoreCustomizer customizer) { - this.httpClient = httpClient == null?new HttpClient():httpClient; + if (httpClient==null) + { + httpClient = new HttpClient(new SslContextFactory()); + httpClient.getSslContextFactory().setEndpointIdentificationAlgorithm("HTTPS"); + httpClient.setName(String.format("%s@%x",getClass().getSimpleName(),hashCode())); + } + this.httpClient = httpClient; this.extensionRegistry = new WebSocketExtensionRegistry(); this.objectFactory = new DecoratedObjectFactory(); this.customizer = customizer;