Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-5561

ZK Websocket Quarkus compatibility

XMLWordPrintable

    • Icon: New Feature New Feature
    • Resolution: Done
    • Icon: Normal Normal
    • 10.1.0
    • 10.0.0, 9.6.5
    • None
    • None

      User Story

      As an developer, I want to use the ZK websocket and WebsocketServerPush in a Quarkus application.

      Acceptance Criteria

      Adding the WebsocketWebappInit to enable similar WS support as other environments

      Details

      Multiple failure points currently:

      Quarkus appear to not trigger the WebsocketFilter, even though it is registered in the WebappInit

      Quarkus wraps websocket requests in its own io.undertow.websockets.vertx.VertxWebSocketHttpExchange which always returns null when prompted for session, which means that no session is ever retrieved from Quarkus

       

      Additional config info

      In Quarkus / undertow, zk.xml must be deployed under src/main/resources/metainfo/zk/zk.xml

      Quarkus / undertow doesn't start WS unless a WS config exist in Java code (not created during WebAppInit), so need to create a Dummy class (attached EnableWebsocket class) to enable WS support

      Quarkus require a specific extra library to support WS

      enable with quarkus command or in pom directly with 

      		<dependency>
      		    <groupId>io.quarkus</groupId>
      		    <artifactId>quarkus-websockets</artifactId>
      		</dependency>
      

      Reopened with test case

      Running manual websockets cause Error:

      See sample zk-quarkus-ws-2.zip

      2024-11-07 15:15:49,334 ERROR [io.und.web.request] (vert.x-eventloop-thread-0) UT026013: Unhandled error in annotated endpoint org.zkoss.foo.EchoServer@318be2a1: java.lang.IllegalStateException: Cannot use the basic remote from an IO thread
      	at io.undertow.websockets.UndertowSession.getBasicRemote(UndertowSession.java:336)
      	at org.zkoss.foo.EchoServer.onMessage(EchoServer.java:41)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
      	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
      	at io.undertow.websockets.annotated.BoundMethod.invoke(BoundMethod.java:87)
      	at io.undertow.websockets.annotated.AnnotatedEndpoint$2.onMessage(AnnotatedEndpoint.java:140)
      	at io.undertow.websockets.FrameHandler$5.run(FrameHandler.java:355)
      	at io.undertow.websockets.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:143)
      	at io.undertow.websockets.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:140)
      	at io.quarkus.websockets.client.runtime.WebsocketCoreRecorder$4$1.call(WebsocketCoreRecorder.java:181)
      	at io.undertow.websockets.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:536)
      	at io.undertow.websockets.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:525)
      	at io.undertow.websockets.FrameHandler.invokeTextHandler(FrameHandler.java:335)
      	at io.undertow.websockets.FrameHandler.onText(FrameHandler.java:250)
      	at io.undertow.websockets.FrameHandler.processFrame(FrameHandler.java:156)
      	at io.undertow.websockets.FrameHandler.channelRead0(FrameHandler.java:131)
      	at io.undertow.websockets.FrameHandler.channelRead0(FrameHandler.java:61)
      	at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
      	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
      	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
      	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
      	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
      	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:289)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
      	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
      	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1407)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
      	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
      	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918)
      	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
      	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
      	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
      	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
      	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
      	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994)
      	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
      	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
      	at java.base/java.lang.Thread.run(Thread.java:840)
      

            jumperchen jumperchen
            MDuchemin MDuchemin
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: