From fb37943764b5f700b3e2a2127de23bc6adee271f Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Tue, 7 Sep 2021 09:13:26 +1000 Subject: [PATCH] SCI's can't add websocket endpoints Fixes #19781 --- .../runtime/UndertowDeploymentRecorder.java | 6 ++- .../websockets/client/deployment/pom.xml | 4 ++ .../deployment/WebsocketClientProcessor.java | 20 +++++---- .../client/runtime/WebsocketCoreRecorder.java | 10 ++++- .../it/websocket/AddWebSocketHandler.java | 41 +++++++++++++++++++ .../io/quarkus/it/main/WebsocketTestCase.java | 25 +++++++++++ 6 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 integration-tests/main/src/main/java/io/quarkus/it/websocket/AddWebSocketHandler.java diff --git a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java index 730b858eea093..32f006d18ccc3 100644 --- a/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java +++ b/extensions/undertow/runtime/src/main/java/io/quarkus/undertow/runtime/UndertowDeploymentRecorder.java @@ -523,7 +523,11 @@ public void run() { } public void addServletContextAttribute(RuntimeValue deployment, String key, Object value1) { - deployment.getValue().addServletContextAttribute(key, value1); + if (value1 instanceof RuntimeValue) { + deployment.getValue().addServletContextAttribute(key, ((RuntimeValue) value1).getValue()); + } else { + deployment.getValue().addServletContextAttribute(key, value1); + } } public void addServletExtension(RuntimeValue deployment, ServletExtension extension) { diff --git a/extensions/websockets/client/deployment/pom.xml b/extensions/websockets/client/deployment/pom.xml index 079ab2aa0e009..0fa240617ff7e 100644 --- a/extensions/websockets/client/deployment/pom.xml +++ b/extensions/websockets/client/deployment/pom.xml @@ -21,6 +21,10 @@ io.quarkus quarkus-websockets-client + + io.quarkus + quarkus-undertow-spi + io.quarkus quarkus-junit5-internal diff --git a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java b/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java index 44574779a8e86..c38f426a850e0 100644 --- a/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java +++ b/extensions/websockets/client/deployment/src/main/java/io/quarkus/undertow/websockets/client/deployment/WebsocketClientProcessor.java @@ -12,6 +12,7 @@ import javax.websocket.ContainerProvider; import javax.websocket.Endpoint; import javax.websocket.server.ServerApplicationConfig; +import javax.websocket.server.ServerContainer; import javax.websocket.server.ServerEndpointConfig; import org.jboss.jandex.AnnotationInstance; @@ -34,10 +35,11 @@ import io.quarkus.deployment.builditem.ServiceStartBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; -import io.quarkus.netty.deployment.EventLoopSupplierBuildItem; import io.quarkus.runtime.RuntimeValue; +import io.quarkus.undertow.deployment.ServletContextAttributeBuildItem; import io.quarkus.undertow.websockets.client.runtime.WebsocketCoreRecorder; import io.undertow.websockets.DefaultContainerConfigurator; +import io.undertow.websockets.ServerWebSocketContainer; import io.undertow.websockets.UndertowContainerProvider; import io.undertow.websockets.WebSocketDeploymentInfo; @@ -70,16 +72,16 @@ void scanForAnnotatedEndpoints(CombinedIndexBuildItem indexBuildItem, } @BuildStep - @Record(ExecutionTime.RUNTIME_INIT) + @Record(ExecutionTime.STATIC_INIT) public ServerWebSocketContainerBuildItem deploy(final CombinedIndexBuildItem indexBuildItem, WebsocketCoreRecorder recorder, BuildProducer reflection, - EventLoopSupplierBuildItem eventLoopSupplierBuildItem, List annotatedEndpoints, BeanContainerBuildItem beanContainerBuildItem, WebsocketConfig websocketConfig, BuildProducer infoBuildItemBuildProducer, - Optional factoryBuildItem) throws Exception { + Optional factoryBuildItem, + BuildProducer servletContextAttributeBuildItemBuildProducer) throws Exception { final Set endpoints = new HashSet<>(); final Set config = new HashSet<>(); @@ -121,10 +123,14 @@ public ServerWebSocketContainerBuildItem deploy(final CombinedIndexBuildItem ind websocketConfig.maxFrameSize, websocketConfig.dispatchToWorker); infoBuildItemBuildProducer.produce(new WebSocketDeploymentInfoBuildItem(deploymentInfo)); + RuntimeValue serverContainer = recorder.createServerContainer( + beanContainerBuildItem.getValue(), + deploymentInfo, + factoryBuildItem.map(ServerWebSocketContainerFactoryBuildItem::getFactory).orElse(null)); + servletContextAttributeBuildItemBuildProducer + .produce(new ServletContextAttributeBuildItem(ServerContainer.class.getName(), serverContainer)); return new ServerWebSocketContainerBuildItem( - recorder.createServerContainer(beanContainerBuildItem.getValue(), eventLoopSupplierBuildItem.getMainSupplier(), - deploymentInfo, - factoryBuildItem.map(ServerWebSocketContainerFactoryBuildItem::getFactory).orElse(null))); + serverContainer); } public static void registerCodersForReflection(BuildProducer reflection, diff --git a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java b/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java index 1c384fc46a3e5..1a420478fefb4 100644 --- a/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java +++ b/extensions/websockets/client/runtime/src/main/java/io/quarkus/undertow/websockets/client/runtime/WebsocketCoreRecorder.java @@ -19,6 +19,7 @@ import io.quarkus.arc.runtime.BeanContainer; import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; +import io.quarkus.vertx.core.runtime.VertxCoreRecorder; import io.undertow.websockets.ServerWebSocketContainer; import io.undertow.websockets.UndertowContainerProvider; import io.undertow.websockets.WebSocketDeploymentInfo; @@ -26,6 +27,7 @@ import io.undertow.websockets.util.ObjectFactory; import io.undertow.websockets.util.ObjectHandle; import io.undertow.websockets.util.ObjectIntrospecter; +import io.vertx.core.impl.VertxInternal; @Recorder public class WebsocketCoreRecorder { @@ -105,7 +107,6 @@ public RuntimeValue createDeploymentInfo(Set an } public RuntimeValue createServerContainer(BeanContainer beanContainer, - Supplier eventLoopGroupSupplier, RuntimeValue infoVal, ServerWebSocketContainerFactory serverContainerFactory) throws DeploymentException { WebSocketDeploymentInfo info = infoVal.getValue(); @@ -136,7 +137,12 @@ public void release() { } }; } - }, Thread.currentThread().getContextClassLoader(), eventLoopGroupSupplier, + }, Thread.currentThread().getContextClassLoader(), new Supplier() { + @Override + public EventLoopGroup get() { + return ((VertxInternal) VertxCoreRecorder.getVertx().get()).getEventLoopGroup(); + } + }, Collections.singletonList(new ContextSetupHandler() { @Override public Action create(Action action) { diff --git a/integration-tests/main/src/main/java/io/quarkus/it/websocket/AddWebSocketHandler.java b/integration-tests/main/src/main/java/io/quarkus/it/websocket/AddWebSocketHandler.java new file mode 100644 index 0000000000000..93dd2b6222880 --- /dev/null +++ b/integration-tests/main/src/main/java/io/quarkus/it/websocket/AddWebSocketHandler.java @@ -0,0 +1,41 @@ +package io.quarkus.it.websocket; + +import javax.enterprise.inject.spi.DeploymentException; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.Session; +import javax.websocket.server.ServerContainer; +import javax.websocket.server.ServerEndpointConfig; + +import io.quarkus.runtime.annotations.RegisterForReflection; + +@WebListener +public class AddWebSocketHandler implements ServletContextListener { + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + + @Override + public void contextInitialized(ServletContextEvent sce) { + try { + ((ServerContainer) sce.getServletContext().getAttribute(ServerContainer.class.getName())) + .addEndpoint(ServerEndpointConfig.Builder.create(WebSocketEndpoint.class, "/added-dynamic").build()); + + } catch (DeploymentException | javax.websocket.DeploymentException e) { + throw new RuntimeException(e); + } + } + + @RegisterForReflection + public static class WebSocketEndpoint extends Endpoint { + + @Override + public void onOpen(Session session, EndpointConfig config) { + session.getAsyncRemote().sendText("DYNAMIC"); + } + + } +} diff --git a/integration-tests/main/src/test/java/io/quarkus/it/main/WebsocketTestCase.java b/integration-tests/main/src/test/java/io/quarkus/it/main/WebsocketTestCase.java index 2fcf61f794671..e92668b8eb883 100644 --- a/integration-tests/main/src/test/java/io/quarkus/it/main/WebsocketTestCase.java +++ b/integration-tests/main/src/test/java/io/quarkus/it/main/WebsocketTestCase.java @@ -32,6 +32,8 @@ public class WebsocketTestCase { @TestHTTPResource("wsopen") URI openURI; + @TestHTTPResource("added-dynamic") + URI added; @Test public void websocketTest() throws Exception { @@ -57,6 +59,29 @@ public void onMessage(String s) { } } + @Test + public void addedWebSocketTest() throws Exception { + + LinkedBlockingDeque message = new LinkedBlockingDeque<>(); + Session session = ContainerProvider.getWebSocketContainer().connectToServer(new Endpoint() { + @Override + public void onOpen(Session session, EndpointConfig endpointConfig) { + session.addMessageHandler(new MessageHandler.Whole() { + @Override + public void onMessage(String s) { + message.add(s); + } + }); + } + }, ClientEndpointConfig.Builder.create().build(), added); + + try { + Assertions.assertEquals("DYNAMIC", message.poll(20, TimeUnit.SECONDS)); + } finally { + session.close(); + } + } + @Test public void websocketServerEncodingAndDecodingTest() throws Exception { LinkedBlockingDeque message = new LinkedBlockingDeque<>();