diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java index 155ada9009e..6b2aa59ed33 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionDataStore.java @@ -58,6 +58,8 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore protected SessionTableSchema _sessionTableSchema; protected boolean _schemaProvided; + private static final ByteArrayInputStream EMPTY = new ByteArrayInputStream(new byte[0]); + /** * SessionTableSchema */ @@ -707,17 +709,23 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore statement.setLong(10, data.getExpiry()); statement.setLong(11, data.getMaxInactiveMs()); - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos)) + if(!data.getAllAttributes().isEmpty()) { - SessionData.serializeAttributes(data, oos); - byte[] bytes = baos.toByteArray(); - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - statement.setBinaryStream(12, bais, bytes.length);//attribute map as blob - statement.executeUpdate(); - if (LOG.isDebugEnabled()) - LOG.debug("Inserted session " + data); + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) + { + SessionData.serializeAttributes( data, oos ); + byte[] bytes = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream( bytes ); + statement.setBinaryStream( 12, bais, bytes.length );//attribute map as blob + } } + else + { + statement.setBinaryStream( 12, EMPTY, 0); + } + statement.executeUpdate(); + if ( LOG.isDebugEnabled() ) LOG.debug( "Inserted session " + data ); } } } @@ -737,20 +745,26 @@ public class JDBCSessionDataStore extends AbstractSessionDataStore statement.setLong(5, data.getExpiry()); statement.setLong(6, data.getMaxInactiveMs()); - try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos)) + if(!data.getAllAttributes().isEmpty()) { - SessionData.serializeAttributes(data, oos); - byte[] bytes = baos.toByteArray(); - try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) { - statement.setBinaryStream(7, bais, bytes.length);//attribute map as blob - statement.executeUpdate(); - - if (LOG.isDebugEnabled()) - LOG.debug("Updated session " + data); + SessionData.serializeAttributes(data, oos); + byte[] bytes = baos.toByteArray(); + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) + { + statement.setBinaryStream( 7, bais, bytes.length );//attribute map as blob + } } } + else + { + statement.setBinaryStream( 7, EMPTY, 0); + } + statement.executeUpdate(); + + if ( LOG.isDebugEnabled() ) LOG.debug( "Updated session " + data ); } } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java index 3b3a9fd0493..3d209ce7023 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionData.java @@ -156,7 +156,7 @@ public class SessionData implements Serializable LOG.info("Legacy serialization detected for {}", data.getId()); //legacy serialization was used, we have just deserialized the //entire attribute map - data._attributes = new ConcurrentHashMap(); + data._attributes = new ConcurrentHashMap<>(); data.putAllAttributes((Map)o); } } diff --git a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketCoreSession.java b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketCoreSession.java index bf73bdd9516..1ed5fc8590f 100644 --- a/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketCoreSession.java +++ b/jetty-websocket/websocket-core/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketCoreSession.java @@ -29,6 +29,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.TimeoutException; import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Utf8Appendable; import org.eclipse.jetty.util.component.Dumpable; @@ -76,6 +77,7 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe private long maxTextMessageSize = WebSocketConstants.DEFAULT_MAX_TEXT_MESSAGE_SIZE; private Duration idleTimeout = WebSocketConstants.DEFAULT_IDLE_TIMEOUT; private Duration writeTimeout = WebSocketConstants.DEFAULT_WRITE_TIMEOUT; + private final ContextHandler contextHandler; public WebSocketCoreSession(FrameHandler handler, Behavior behavior, Negotiated negotiated) { @@ -83,9 +85,28 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe this.behavior = behavior; this.negotiated = negotiated; this.demanding = handler.isDemanding(); + + if (behavior == Behavior.SERVER) + { + ContextHandler.Context context = ContextHandler.getCurrentContext(); + this.contextHandler = (context != null) ? context.getContextHandler() : null; + } + else + { + this.contextHandler = null; + } + negotiated.getExtensions().initialize(new IncomingAdaptor(), new OutgoingAdaptor(), this); } + private void handle(Runnable runnable) + { + if (contextHandler != null) + contextHandler.handle(runnable); + else + runnable.run(); + } + /** * @return True if the sessions handling is demanding. */ @@ -152,7 +173,6 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe throw new ProtocolException("Frame has non-transmittable status code"); } } - } } @@ -325,7 +345,7 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe { try { - handler.onClosed(closeStatus, callback); + handle(() -> handler.onClosed(closeStatus, callback)); } catch (Throwable e) { @@ -337,7 +357,7 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe Throwable cause = closeStatus.getCause(); try { - handler.onError(cause, errorCallback); + handle(() -> handler.onError(cause, errorCallback)); } catch (Throwable e) { @@ -351,7 +371,7 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe { try { - handler.onClosed(closeStatus, callback); + handle(() -> handler.onClosed(closeStatus, callback)); } catch (Throwable e) { @@ -454,7 +474,7 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe try { // Open connection and handler - handler.onOpen(this, openCallback); + handle(() -> handler.onOpen(this, openCallback)); } catch (Throwable t) { @@ -664,7 +684,7 @@ public class WebSocketCoreSession implements IncomingFrames, FrameHandler.CoreSe // Handle inbound frame if (frame.getOpCode() != OpCode.CLOSE) { - handler.onFrame(frame, callback); + handle(() -> handler.onFrame(frame, callback)); return; } diff --git a/jetty-websocket/websocket-javax-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java b/jetty-websocket/websocket-javax-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java index 14956e01612..0ba2dee7304 100644 --- a/jetty-websocket/websocket-javax-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java +++ b/jetty-websocket/websocket-javax-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java @@ -292,6 +292,11 @@ public class JavaxWebSocketSession implements javax.websocket.Session return frameHandler; } + public void abort() + { + coreSession.abort(); + } + /** * {@inheritDoc} * diff --git a/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/ContainerDefaultConfigurator.java b/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/ContainerDefaultConfigurator.java index 613bd1f7ee6..c6c1c070c69 100644 --- a/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/ContainerDefaultConfigurator.java +++ b/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/ContainerDefaultConfigurator.java @@ -72,7 +72,9 @@ public final class ContainerDefaultConfigurator extends Configurator } catch (Exception e) { - throw new InstantiationException(String.format("%s: %s", e.getClass().getName(), e.getMessage())); + InstantiationException instantiationException = new InstantiationException(); + instantiationException.initCause(e); + throw instantiationException; } } diff --git a/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/JavaxWebSocketConfiguration.java b/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/JavaxWebSocketConfiguration.java index d0baa67fb5b..26f5b7cc274 100644 --- a/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/JavaxWebSocketConfiguration.java +++ b/jetty-websocket/websocket-javax-server/src/main/java/org/eclipse/jetty/websocket/javax/server/config/JavaxWebSocketConfiguration.java @@ -39,6 +39,7 @@ public class JavaxWebSocketConfiguration extends AbstractConfiguration addDependents("org.eclipse.jetty.annotations.AnnotationConfiguration", WebAppConfiguration.class.getName()); protectAndExpose("org.eclipse.jetty.websocket.servlet."); // For WebSocketUpgradeFilter protectAndExpose("org.eclipse.jetty.websocket.javax.server.config."); + protectAndExpose("org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainerProvider"); hide("org.eclipse.jetty.websocket.javax.server.internal"); } } diff --git a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/LocalServer.java b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/LocalServer.java index 9ed2a87aa3c..dd0d9561a31 100644 --- a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/LocalServer.java +++ b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/LocalServer.java @@ -82,6 +82,15 @@ public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provi private boolean ssl = false; private SslContextFactory.Server sslContextFactory; + public LocalServer() + { + QueuedThreadPool threadPool = new QueuedThreadPool(); + threadPool.setName("qtp-LocalServer"); + + // Configure Server + server = new Server(threadPool); + } + public void enableSsl(boolean ssl) { this.ssl = ssl; @@ -179,11 +188,6 @@ public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provi @Override protected void doStart() throws Exception { - QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setName("qtp-LocalServer"); - - // Configure Server - server = new Server(threadPool); if (ssl) { // HTTP Configuration diff --git a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/WSServer.java b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/WSServer.java index 52beae928fb..31993123b49 100644 --- a/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/WSServer.java +++ b/jetty-websocket/websocket-javax-tests/src/main/java/org/eclipse/jetty/websocket/javax/tests/WSServer.java @@ -24,12 +24,9 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; -import org.eclipse.jetty.annotations.AnnotationConfiguration; -import org.eclipse.jetty.plus.webapp.PlusConfiguration; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.toolchain.test.FS; import org.eclipse.jetty.toolchain.test.IO; import org.eclipse.jetty.toolchain.test.JAR; @@ -129,11 +126,7 @@ public class WSServer extends LocalServer implements LocalFuzzer.Provider context.setContextPath(this.contextPath); context.setBaseResource(new PathResource(this.contextDir)); context.setAttribute("org.eclipse.jetty.websocket.javax", Boolean.TRUE); - - context.addConfiguration(new AnnotationConfiguration()); - context.addConfiguration(new PlusConfiguration()); context.addConfiguration(new JavaxWebSocketConfiguration()); - return context; } @@ -162,7 +155,6 @@ public class WSServer extends LocalServer implements LocalFuzzer.Provider @Override protected Handler createRootHandler(Server server) throws Exception { - HandlerCollection handlers = new HandlerCollection(); contexts = new ContextHandlerCollection(); return contexts; } diff --git a/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/server/ContainerProviderServerTest.java b/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/server/ContainerProviderServerTest.java new file mode 100644 index 00000000000..1334c68cbfd --- /dev/null +++ b/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/server/ContainerProviderServerTest.java @@ -0,0 +1,89 @@ +// +// ======================================================================== +// 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.javax.tests.server; + +import java.nio.file.Path; +import java.util.concurrent.TimeUnit; +import javax.websocket.CloseReason; +import javax.websocket.ContainerProvider; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.WebSocketContainer; +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.websocket.javax.tests.EventSocket; +import org.eclipse.jetty.websocket.javax.tests.WSServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static javax.websocket.CloseReason.CloseCodes.NORMAL_CLOSURE; +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 ContainerProviderServerTest +{ + @ServerEndpoint("/echo") + public static class MySocket + { + @OnOpen + public void onOpen() + { + WebSocketContainer client = ContainerProvider.getWebSocketContainer(); + assertNotNull(client); + } + } + + private WSServer server; + + @BeforeEach + public void startServer() throws Exception + { + Path testdir = MavenTestingUtils.getTargetTestingPath(ContainerProviderServerTest.class.getName()); + server = new WSServer(testdir, "app"); + server.createWebInf(); + server.copyEndpoint(MySocket.class); + server.start(); + WebAppContext webapp = server.createWebAppContext(); + server.deployWebapp(webapp); + } + + @AfterEach + public void stopServer() throws Exception + { + server.stop(); + } + + @Test + public void testJavaxWsContainerInServer() throws Exception + { + WebSocketContainer client = ContainerProvider.getWebSocketContainer(); + EventSocket clientSocket = new EventSocket(); + Session session = client.connectToServer(clientSocket, server.getWsUri().resolve("/app/echo")); + session.close(new CloseReason(NORMAL_CLOSURE, null)); + assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(clientSocket.closeReason.getCloseCode(), is(NORMAL_CLOSURE)); + assertNull(clientSocket.error); + } +} diff --git a/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/server/WebAppClassLoaderTest.java b/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/server/WebAppClassLoaderTest.java new file mode 100644 index 00000000000..0e1def2f7db --- /dev/null +++ b/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/server/WebAppClassLoaderTest.java @@ -0,0 +1,141 @@ +// +// ======================================================================== +// 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.javax.tests.server; + +import java.nio.file.Path; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.websocket.CloseReason; +import javax.websocket.ContainerProvider; +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.WebSocketContainer; +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.toolchain.test.MavenTestingUtils; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.websocket.javax.common.JavaxWebSocketSession; +import org.eclipse.jetty.websocket.javax.tests.EventSocket; +import org.eclipse.jetty.websocket.javax.tests.WSServer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class WebAppClassLoaderTest +{ + @ServerEndpoint("/echo") + public static class MySocket + { + public final static CountDownLatch closeLatch = new CountDownLatch(1); + public final static Map classLoaders = new ConcurrentHashMap<>(); + + public MySocket() + { + classLoaders.put("constructor", Thread.currentThread().getContextClassLoader()); + } + + @OnOpen + public void onOpen(Session session) + { + classLoaders.put("onOpen", Thread.currentThread().getContextClassLoader()); + } + + @OnMessage + public void onMessage(Session session, String msg) + { + classLoaders.put("onMessage", Thread.currentThread().getContextClassLoader()); + } + + @OnError + public void onError(Throwable error) + { + classLoaders.put("onError", Thread.currentThread().getContextClassLoader()); + } + + @OnClose + public void onClose(CloseReason closeReason) + { + classLoaders.put("onClose", Thread.currentThread().getContextClassLoader()); + closeLatch.countDown(); + } + } + + private WSServer server; + private WebAppContext webapp; + + @BeforeEach + public void startServer() throws Exception + { + Path testdir = MavenTestingUtils.getTargetTestingPath(WebAppClassLoaderTest.class.getName()); + server = new WSServer(testdir, "app"); + server.createWebInf(); + server.copyEndpoint(MySocket.class); + server.start(); + webapp = server.createWebAppContext(); + server.deployWebapp(webapp); + } + + @AfterEach + public void stopServer() throws Exception + { + server.stop(); + } + + private void awaitServerClose() throws Exception + { + ClassLoader webAppClassLoader = webapp.getClassLoader(); + Class mySocketClass = webAppClassLoader.loadClass(MySocket.class.getName()); + CountDownLatch closeLatch = (CountDownLatch)mySocketClass.getDeclaredField("closeLatch").get(null); + assertTrue(closeLatch.await(5, TimeUnit.SECONDS)); + } + + private ClassLoader getClassLoader(String event) throws Exception + { + ClassLoader webAppClassLoader = webapp.getClassLoader(); + Class mySocketClass = webAppClassLoader.loadClass(MySocket.class.getName()); + Map classLoaderMap = (Map)mySocketClass.getDeclaredField("classLoaders").get(null); + return classLoaderMap.get(event); + } + + @ParameterizedTest + @ValueSource(strings = {"constructor", "onOpen", "onMessage", "onError", "onClose"}) + public void testForWebAppClassLoader(String event) throws Exception + { + WebSocketContainer client = ContainerProvider.getWebSocketContainer(); + EventSocket clientSocket = new EventSocket(); + Session session = client.connectToServer(clientSocket, server.getWsUri().resolve("/app/echo")); + session.getBasicRemote().sendText("trigger onMessage -> onError -> onClose"); + ((JavaxWebSocketSession)session).abort(); + assertTrue(clientSocket.closeLatch.await(5, TimeUnit.SECONDS)); + awaitServerClose(); + + ClassLoader webAppClassLoader = webapp.getClassLoader(); + assertThat(event, getClassLoader(event), is(webAppClassLoader)); + } +} diff --git a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java index f89476b6ab2..d9233a3b9ce 100644 --- a/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java +++ b/jetty-websocket/websocket-servlet/src/main/java/org/eclipse/jetty/websocket/servlet/WebSocketMapping.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.websocket.servlet; import java.io.IOException; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -263,39 +264,30 @@ public class WebSocketMapping implements Dumpable, LifeCycle.Listener if (servletContext == null) throw new IllegalStateException("null servletContext from request"); - ClassLoader loader = servletContext.getClassLoader(); - ClassLoader old = Thread.currentThread().getContextClassLoader(); + ServletUpgradeRequest upgradeRequest = new ServletUpgradeRequest(negotiation); + ServletUpgradeResponse upgradeResponse = new ServletUpgradeResponse(negotiation); - try + AtomicReference result = new AtomicReference<>(); + ((ContextHandler.Context)servletContext).getContextHandler().handle(() -> + result.set(creator.createWebSocket(upgradeRequest, upgradeResponse))); + Object websocketPojo = result.get(); + + // Handling for response forbidden (and similar paths) + if (upgradeResponse.isCommitted()) + return null; + + if (websocketPojo == null) { - Thread.currentThread().setContextClassLoader(loader); - - ServletUpgradeRequest upgradeRequest = new ServletUpgradeRequest(negotiation); - ServletUpgradeResponse upgradeResponse = new ServletUpgradeResponse(negotiation); - - Object websocketPojo = creator.createWebSocket(upgradeRequest, upgradeResponse); - - // Handling for response forbidden (and similar paths) - if (upgradeResponse.isCommitted()) - return null; - - if (websocketPojo == null) - { - // no creation, sorry - upgradeResponse.sendError(SC_SERVICE_UNAVAILABLE, "WebSocket Endpoint Creation Refused"); - return null; - } - - FrameHandler frameHandler = factory.newFrameHandler(websocketPojo, upgradeRequest, upgradeResponse); - if (frameHandler != null) - return frameHandler; - + // no creation, sorry + upgradeResponse.sendError(SC_SERVICE_UNAVAILABLE, "WebSocket Endpoint Creation Refused"); return null; } - finally - { - Thread.currentThread().setContextClassLoader(old); - } + + FrameHandler frameHandler = factory.newFrameHandler(websocketPojo, upgradeRequest, upgradeResponse); + if (frameHandler != null) + return frameHandler; + + return null; } @Override diff --git a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestHelper.java b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestHelper.java index 6a66daadf65..43c865aa537 100644 --- a/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestHelper.java +++ b/tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/JdbcTestHelper.java @@ -173,17 +173,17 @@ public class JdbcTestHelper ResultSet result = null; try (Connection con = DriverManager.getConnection(DEFAULT_CONNECTION_URL);) { - statement = con.prepareStatement("select * from " + TABLE + - " where " + ID_COL + " = ? and " + CONTEXT_COL + - " = ? and virtualHost = ?"); + statement = con.prepareStatement( + "select * from " + TABLE + + " where " + ID_COL + " = ? and " + CONTEXT_COL + + " = ? and virtualHost = ?" ); statement.setString(1, data.getId()); statement.setString(2, data.getContextPath()); statement.setString(3, data.getVhost()); result = statement.executeQuery(); - if (!result.next()) - return false; + if (!result.next()) return false; assertEquals(data.getCreated(), result.getLong(CREATE_COL)); assertEquals(data.getAccessed(), result.getLong(ACCESS_COL)); @@ -199,16 +199,19 @@ public class JdbcTestHelper Blob blob = result.getBlob(MAP_COL); - SessionData tmp = new SessionData(data.getId(), data.getContextPath(), data.getVhost(), result.getLong(CREATE_COL), - result.getLong(ACCESS_COL), result.getLong(LAST_ACCESS_COL), result.getLong(MAX_IDLE_COL)); + SessionData tmp = + new SessionData( data.getId(), data.getContextPath(), data.getVhost(), result.getLong(CREATE_COL), + result.getLong(ACCESS_COL), result.getLong(LAST_ACCESS_COL), + result.getLong(MAX_IDLE_COL)); - try (InputStream is = blob.getBinaryStream(); - ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is)) + if (blob.length() > 0) { - - SessionData.deserializeAttributes(tmp, ois); + try (InputStream is = blob.getBinaryStream(); + ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is)) + { + SessionData.deserializeAttributes(tmp, ois); + } } - //same number of attributes assertEquals(data.getAllAttributes().size(), tmp.getAllAttributes().size()); //same keys