From c29bad23010b870ccb8223458e1d8905ca7d5305 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Wed, 31 Mar 2021 18:36:15 +1100 Subject: [PATCH] Issue #6106 - add tests for WebSocket/CDI integration. Signed-off-by: Lachlan Roberts --- tests/test-cdi/pom.xml | 18 ++ .../websocket/JavaxWebSocketCdiTest.java | 160 ++++++++++++++++++ .../websocket/JettyWebSocketCdiTest.java | 158 +++++++++++++++++ .../jetty/cdi/tests/websocket/LogFactory.java | 34 ++++ 4 files changed, 370 insertions(+) create mode 100644 tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JavaxWebSocketCdiTest.java create mode 100644 tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JettyWebSocketCdiTest.java create mode 100644 tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/LogFactory.java diff --git a/tests/test-cdi/pom.xml b/tests/test-cdi/pom.xml index e973750bab2..505c36f1b8a 100644 --- a/tests/test-cdi/pom.xml +++ b/tests/test-cdi/pom.xml @@ -48,6 +48,24 @@ jetty-slf4j-impl test + + org.eclipse.jetty.websocket + websocket-javax-server + ${project.version} + test + + + org.eclipse.jetty.websocket + websocket-jetty-server + ${project.version} + test + + + org.eclipse.jetty.websocket + websocket-jetty-client + ${project.version} + test + org.eclipse.jetty.toolchain jetty-test-helper diff --git a/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JavaxWebSocketCdiTest.java b/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JavaxWebSocketCdiTest.java new file mode 100644 index 00000000000..07565fa27dc --- /dev/null +++ b/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JavaxWebSocketCdiTest.java @@ -0,0 +1,160 @@ +// +// ======================================================================== +// Copyright (c) Webtide LLC and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.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.cdi.tests.websocket; + +import java.io.IOException; +import java.net.URI; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; +import javax.inject.Inject; +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +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.cdi.CdiDecoratingListener; +import org.eclipse.jetty.cdi.CdiServletContainerInitializer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.BlockingArrayQueue; +import org.eclipse.jetty.websocket.javax.client.JavaxWebSocketClientContainerProvider; +import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer; +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.assertTrue; + +public class JavaxWebSocketCdiTest +{ + private Server _server; + private WebSocketContainer _client; + private ServerConnector _connector; + + @BeforeEach + public void before() throws Exception + { + _server = new Server(); + _connector = new ServerConnector(_server); + _server.addConnector(_connector); + + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + + // Enable Weld + CDI + context.setInitParameter(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, CdiDecoratingListener.MODE); + context.addServletContainerInitializer(new CdiServletContainerInitializer()); + context.addServletContainerInitializer(new org.jboss.weld.environment.servlet.EnhancedListener()); + + // Add WebSocket endpoints + JavaxWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) -> + wsContainer.addEndpoint(CdiEchoSocket.class)); + + // Add to Server + _server.setHandler(context); + + // Start Server + _server.start(); + + _client = JavaxWebSocketClientContainerProvider.getContainer(null); + } + + @AfterEach + public void after() throws Exception + { + JavaxWebSocketClientContainerProvider.stop(_client); + _server.stop(); + } + + @ClientEndpoint + public static class TestClientEndpoint + { + BlockingArrayQueue _textMessages = new BlockingArrayQueue<>(); + CountDownLatch _closeLatch = new CountDownLatch(1); + + @OnMessage + public void onMessage(String message) + { + _textMessages.add(message); + } + + @OnClose + public void onClose() + { + _closeLatch.countDown(); + } + } + + @Test + public void testBasicEcho() throws Exception + { + // If we can get an echo from the websocket endpoint we know that CDI injection of the logger worked as there was no NPE. + TestClientEndpoint clientEndpoint = new TestClientEndpoint(); + URI uri = URI.create("ws://localhost:" + _connector.getLocalPort() + "/echo"); + Session session = _client.connectToServer(clientEndpoint, uri); + session.getBasicRemote().sendText("hello world"); + assertThat(clientEndpoint._textMessages.poll(5, TimeUnit.SECONDS), is("hello world")); + session.close(); + assertTrue(clientEndpoint._closeLatch.await(5, TimeUnit.SECONDS)); + } + + @ServerEndpoint("/echo") + public static class CdiEchoSocket + { + @Inject + public Logger logger; + + private Session session; + + @OnOpen + public void onOpen(Session session) + { + logger.info("onOpen() session:" + session); + this.session = session; + } + + @OnMessage + public void onMessage(String message) throws IOException + { + this.session.getBasicRemote().sendText(message); + } + + @OnError + public void onError(Throwable t) + { + t.printStackTrace(); + } + + @OnClose + public void onClose(CloseReason close) + { + logger.info("onClose() close:" + close); + this.session = null; + } + } +} diff --git a/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JettyWebSocketCdiTest.java b/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JettyWebSocketCdiTest.java new file mode 100644 index 00000000000..0c0b9694cb3 --- /dev/null +++ b/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/JettyWebSocketCdiTest.java @@ -0,0 +1,158 @@ +// +// ======================================================================== +// Copyright (c) Webtide LLC and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.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.cdi.tests.websocket; + +import java.io.IOException; +import java.net.URI; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; +import javax.inject.Inject; + +import org.eclipse.jetty.cdi.CdiDecoratingListener; +import org.eclipse.jetty.cdi.CdiServletContainerInitializer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.BlockingArrayQueue; +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; +import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; +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.assertTrue; + +public class JettyWebSocketCdiTest +{ + private Server _server; + private WebSocketClient _client; + private ServerConnector _connector; + + @BeforeEach + public void before() throws Exception + { + _server = new Server(); + _connector = new ServerConnector(_server); + _server.addConnector(_connector); + + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + + // Enable Weld + CDI + context.setInitParameter(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, CdiDecoratingListener.MODE); + context.addServletContainerInitializer(new CdiServletContainerInitializer()); + context.addServletContainerInitializer(new org.jboss.weld.environment.servlet.EnhancedListener()); + + // Add WebSocket endpoints + JettyWebSocketServletContainerInitializer.configure(context, (servletContext, wsContainer) -> + wsContainer.addMapping("/echo", CdiEchoSocket.class)); + + // Add to Server + _server.setHandler(context); + + // Start Server + _server.start(); + + _client = new WebSocketClient(); + _client.start(); + } + + @AfterEach + public void after() throws Exception + { + _client.stop(); + _server.stop(); + } + + @WebSocket + public static class TestClientEndpoint + { + BlockingArrayQueue _textMessages = new BlockingArrayQueue<>(); + CountDownLatch _closeLatch = new CountDownLatch(1); + + @OnWebSocketMessage + public void onMessage(String message) + { + _textMessages.add(message); + } + + @OnWebSocketClose + public void onClose() + { + _closeLatch.countDown(); + } + } + + @Test + public void testBasicEcho() throws Exception + { + // If we can get an echo from the websocket endpoint we know that CDI injection of the logger worked as there was no NPE. + TestClientEndpoint clientEndpoint = new TestClientEndpoint(); + URI uri = URI.create("ws://localhost:" + _connector.getLocalPort() + "/echo"); + Session session = _client.connect(clientEndpoint, uri).get(5, TimeUnit.SECONDS); + session.getRemote().sendString("hello world"); + assertThat(clientEndpoint._textMessages.poll(5, TimeUnit.SECONDS), is("hello world")); + session.close(); + assertTrue(clientEndpoint._closeLatch.await(5, TimeUnit.SECONDS)); + } + + @WebSocket() + public static class CdiEchoSocket + { + @Inject + public Logger logger; + + private Session session; + + @OnWebSocketConnect + public void onOpen(Session session) + { + logger.info("onOpen() session:" + session); + this.session = session; + } + + @OnWebSocketMessage + public void onMessage(String message) throws IOException + { + this.session.getRemote().sendString(message); + } + + @OnWebSocketError + public void onError(Throwable t) + { + t.printStackTrace(); + } + + @OnWebSocketClose + public void onClose(int statusCode, String reason) + { + logger.info("onClose() close: " + statusCode + ":" + reason); + this.session = null; + } + } +} diff --git a/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/LogFactory.java b/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/LogFactory.java new file mode 100644 index 00000000000..b201259e636 --- /dev/null +++ b/tests/test-cdi/src/test/java/org/eclipse/jetty/cdi/tests/websocket/LogFactory.java @@ -0,0 +1,34 @@ +// +// ======================================================================== +// Copyright (c) Webtide LLC and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.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.cdi.tests.websocket; + +import java.util.logging.Logger; +import javax.enterprise.inject.Default; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.InjectionPoint; + +public class LogFactory +{ + @Produces + @Default + public Logger createLogger(InjectionPoint injectionPoint) + { + return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); + } +}