Issue #3167 - lazily create the WebSocketCoreClient

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2018-12-18 17:19:55 +11:00
parent 1999b23d67
commit 3bcb4d8229
4 changed files with 55 additions and 76 deletions

View File

@ -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.
* <p>
@ -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<WebSocketCoreClient> 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<WebSocketCoreClient> 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)

View File

@ -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)
{

View File

@ -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);

View File

@ -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;