Fix lifecycle issues with WebSocketComponents and improve testing.
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
b0a953a9fc
commit
b51e40892d
|
@ -71,7 +71,7 @@ public class DeflaterPool extends CompressionPool<Deflater>
|
|||
capacity = threadPool.getMaxThreads();
|
||||
|
||||
pool = new DeflaterPool(capacity, Deflater.DEFAULT_COMPRESSION, true);
|
||||
container.addBean(pool);
|
||||
container.addBean(pool, true);
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ public class InflaterPool extends CompressionPool<Inflater>
|
|||
capacity = threadPool.getMaxThreads();
|
||||
|
||||
pool = new InflaterPool(capacity, true);
|
||||
container.addBean(pool);
|
||||
container.addBean(pool, true);
|
||||
return pool;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ public class WebSocketComponents extends ContainerLifeCycle
|
|||
addBean(inflaterPool);
|
||||
addBean(deflaterPool);
|
||||
addBean(bufferPool);
|
||||
addBean(extensionRegistry);
|
||||
addBean(objectFactory);
|
||||
}
|
||||
|
||||
public ByteBufferPool getBufferPool()
|
||||
|
|
|
@ -14,10 +14,13 @@
|
|||
package org.eclipse.jetty.websocket.core.server;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.compression.DeflaterPool;
|
||||
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||
import org.eclipse.jetty.websocket.core.WebSocketComponents;
|
||||
|
@ -42,6 +45,22 @@ public class WebSocketServerComponents extends WebSocketComponents
|
|||
super(null, null, bufferPool, inflaterPool, deflaterPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This ensures a {@link WebSocketComponents} is available at the {@link ServletContext} attribute {@link #WEBSOCKET_COMPONENTS_ATTRIBUTE}.
|
||||
* </p>
|
||||
* <p>
|
||||
* This should be called when the server is starting, usually by a {@link javax.servlet.ServletContainerInitializer}.
|
||||
* </p>
|
||||
* <p>
|
||||
* Servlet context attributes can be set with {@link #WEBSOCKET_BUFFER_POOL_ATTRIBUTE}, {@link #WEBSOCKET_INFLATER_POOL_ATTRIBUTE}
|
||||
* and {@link #WEBSOCKET_DEFLATER_POOL_ATTRIBUTE} to override the {@link ByteBufferPool}, {@link DeflaterPool} or
|
||||
* {@link InflaterPool} used by the components, otherwise this will try to use the pools shared on the {@link Server}.
|
||||
* </p>
|
||||
* @param server the server.
|
||||
* @param servletContext the ServletContext.
|
||||
* @return the WebSocketComponents that was created or found on the ServletContext.
|
||||
*/
|
||||
public static WebSocketComponents ensureWebSocketComponents(Server server, ServletContext servletContext)
|
||||
{
|
||||
WebSocketComponents components = (WebSocketComponents)servletContext.getAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE);
|
||||
|
@ -60,9 +79,29 @@ public class WebSocketServerComponents extends WebSocketComponents
|
|||
if (bufferPool == null)
|
||||
bufferPool = server.getBean(ByteBufferPool.class);
|
||||
|
||||
components = new WebSocketServerComponents(inflaterPool, deflaterPool, bufferPool);
|
||||
servletContext.setAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE, components);
|
||||
return components;
|
||||
WebSocketComponents serverComponents = new WebSocketServerComponents(inflaterPool, deflaterPool, bufferPool);
|
||||
|
||||
// These components may be managed by the server but not yet started.
|
||||
// In this case we don't want them to be managed by the components as well.
|
||||
if (server.isManaged(inflaterPool))
|
||||
serverComponents.unmanage(inflaterPool);
|
||||
if (server.isManaged(deflaterPool))
|
||||
serverComponents.unmanage(deflaterPool);
|
||||
if (server.isManaged(bufferPool))
|
||||
serverComponents.unmanage(bufferPool);
|
||||
|
||||
servletContext.setAttribute(WEBSOCKET_COMPONENTS_ATTRIBUTE, serverComponents);
|
||||
LifeCycle.start(serverComponents);
|
||||
servletContext.addListener(new ServletContextListener()
|
||||
{
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce)
|
||||
{
|
||||
LifeCycle.stop(serverComponents);
|
||||
}
|
||||
});
|
||||
|
||||
return serverComponents;
|
||||
}
|
||||
|
||||
public static WebSocketComponents getWebSocketComponents(ServletContext servletContext)
|
||||
|
|
|
@ -30,6 +30,12 @@
|
|||
<artifactId>websocket-core-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.core;
|
||||
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletContainerInitializerHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.compression.DeflaterPool;
|
||||
import org.eclipse.jetty.util.compression.InflaterPool;
|
||||
import org.eclipse.jetty.websocket.core.server.WebSocketServerComponents;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class WebSocketServerComponentsTest
|
||||
{
|
||||
private Server server;
|
||||
private ServletContextHandler contextHandler;
|
||||
private WebSocketComponents components;
|
||||
|
||||
@BeforeEach
|
||||
public void before()
|
||||
{
|
||||
server = new Server();
|
||||
contextHandler = new ServletContextHandler();
|
||||
server.setHandler(contextHandler);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentsInsideServletContainerInitializer() throws Exception
|
||||
{
|
||||
// ensureWebSocketComponents can only be called when the server is starting.
|
||||
contextHandler.addServletContainerInitializer(new ServletContainerInitializerHolder((c, ctx) ->
|
||||
components = WebSocketServerComponents.ensureWebSocketComponents(server, contextHandler.getServletContext())));
|
||||
|
||||
// Components is created only when the server is started.
|
||||
assertNull(components);
|
||||
server.start();
|
||||
assertNotNull(components);
|
||||
|
||||
// Components is started when it is created.
|
||||
assertTrue(components.isStarted());
|
||||
DeflaterPool deflaterPool = components.getDeflaterPool();
|
||||
InflaterPool inflaterPool = components.getInflaterPool();
|
||||
|
||||
// The components is stopped with the ServletContext.
|
||||
contextHandler.stop();
|
||||
assertTrue(components.isStopped());
|
||||
|
||||
// By default the default CompressionPools from the server are used, these should not be stopped with the context.
|
||||
assertTrue(inflaterPool.isStarted());
|
||||
assertTrue(deflaterPool.isStarted());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompressionPoolsManagedByContext() throws Exception
|
||||
{
|
||||
ContextHandler.Context servletContext = contextHandler.getServletContext();
|
||||
|
||||
// Use a custom InflaterPool and DeflaterPool that are not started or managed.
|
||||
InflaterPool inflaterPool = new InflaterPool(333, false);
|
||||
DeflaterPool deflaterPool = new DeflaterPool(333, Deflater.BEST_SPEED, false);
|
||||
servletContext.setAttribute(WebSocketServerComponents.WEBSOCKET_DEFLATER_POOL_ATTRIBUTE, deflaterPool);
|
||||
servletContext.setAttribute(WebSocketServerComponents.WEBSOCKET_INFLATER_POOL_ATTRIBUTE, inflaterPool);
|
||||
|
||||
// ensureWebSocketComponents can only be called when the server is starting.
|
||||
contextHandler.addServletContainerInitializer(new ServletContainerInitializerHolder((c, ctx) ->
|
||||
components = WebSocketServerComponents.ensureWebSocketComponents(server, servletContext)));
|
||||
|
||||
// Components is created only when the server is started.
|
||||
assertNull(components);
|
||||
server.start();
|
||||
assertNotNull(components);
|
||||
|
||||
// Components is started when it is created.
|
||||
assertTrue(components.isStarted());
|
||||
|
||||
// The components uses the CompressionPools set as servletContext attributes.
|
||||
assertThat(components.getInflaterPool(), is(inflaterPool));
|
||||
assertThat(components.getDeflaterPool(), is(deflaterPool));
|
||||
assertTrue(inflaterPool.isStarted());
|
||||
assertTrue(deflaterPool.isStarted());
|
||||
|
||||
// The components is stopped with the ServletContext.
|
||||
contextHandler.stop();
|
||||
assertTrue(components.isStopped());
|
||||
|
||||
// The inflater and deflater pools are stopped as they are not managed by the server.
|
||||
assertTrue(inflaterPool.isStopped());
|
||||
assertTrue(deflaterPool.isStopped());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompressionPoolsManagedByServer() throws Exception
|
||||
{
|
||||
ContextHandler.Context servletContext = contextHandler.getServletContext();
|
||||
|
||||
// Use a custom InflaterPool and DeflaterPool that are not started or managed.
|
||||
InflaterPool inflaterPool = new InflaterPool(333, false);
|
||||
DeflaterPool deflaterPool = new DeflaterPool(333, Deflater.BEST_SPEED, false);
|
||||
server.addManaged(inflaterPool);
|
||||
server.addManaged(deflaterPool);
|
||||
|
||||
// ensureWebSocketComponents can only be called when the server is starting.
|
||||
contextHandler.addServletContainerInitializer(new ServletContainerInitializerHolder((c, ctx) ->
|
||||
components = WebSocketServerComponents.ensureWebSocketComponents(server, servletContext)));
|
||||
|
||||
// The CompressionPools will only be started with the server.
|
||||
assertTrue(inflaterPool.isStopped());
|
||||
assertTrue(deflaterPool.isStopped());
|
||||
server.start();
|
||||
assertThat(components.getInflaterPool(), is(inflaterPool));
|
||||
assertThat(components.getDeflaterPool(), is(deflaterPool));
|
||||
assertTrue(inflaterPool.isStarted());
|
||||
assertTrue(deflaterPool.isStarted());
|
||||
|
||||
// The components is stopped with the ServletContext, but the CompressionPools are stopped with the server.
|
||||
contextHandler.stop();
|
||||
assertTrue(components.isStopped());
|
||||
assertTrue(inflaterPool.isStarted());
|
||||
assertTrue(deflaterPool.isStarted());
|
||||
server.stop();
|
||||
assertTrue(inflaterPool.isStopped());
|
||||
assertTrue(deflaterPool.isStopped());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue