Search code examples
jsfwebsocketpayara

Error "websocket is null" with <f:websocket> in a JSF page


Context : Jakarta EE 10, Payara 6.2024.7, Web profile. Java 21.

My application uses the OpenAI API and LangChain4j for un "customized" Chat.

In a Web page a form sends a question into a websocket to the API and receives in this websocket the streaming of the tokens answered by the API. When all the tokens are sent, the server send the message "streamingfinished" that triggers a listener of <f:ajax> included in <f:websocket>. This listener updates the history of the conversation and the textarea that contains the conversation is rendered. Here is an excerpt of the code:

<h:form id="formId" prependId="false">
    <h:commandButton value="Send the question" action="#{bb.send}">
    </h:commandButton>
    <f:websocket channel="chat" scope="view" onmessage="socketListener"
                 onerror="websocketErrorListener" 
                 onclose="websocketCloseListener">
       <f:ajax event="streamingfinished" listener="#{bb.updateConversation}"
               render="conversationId"/>
   </f:websocket>
   <h:outputText value="Conversation :"/>
   <h:inputTextarea id="conversationId" rows="30" cols="50" readonly="true"
                    value="#{bb.conversation}" />
   ...
</h:form>

During the execution all is right until the execution of the listener. The conversation is updated (so the listener is executed correctly) but the textarea of the conversation is not rendered because of the error "websocket is null". I don't understand my error. Could it be a bug in Payara or in <f:websocket> ? The stacktrace shows that the error occurs when the listener is processed by Tyrus, the implementation of Java API for websocket:

    [Payara 6.2024.7] [GRAVE] [] [jakarta.enterprise.resource.webcontainer.faces.context] [tid: _ThreadID=103 _ThreadName=http-thread-pool::http-listener-1(4)] [timeMillis: 1725610467356] [levelValue: 1000] [[
  java.lang.NullPointerException: Cannot invoke "jakarta.faces.component.UIWebsocket.isRendered()" because "websocket" is null
java.lang.NullPointerException: Cannot invoke "jakarta.faces.component.UIWebsocket.isRendered()" because "websocket" is null
    at com.sun.faces.push.WebsocketFacesListener.processEvent(WebsocketFacesListener.java:100)
    at jakarta.faces.event.SystemEvent.processListener(SystemEvent.java:124)
    at jakarta.faces.event.ComponentSystemEvent.processListener(ComponentSystemEvent.java:109)
    at com.sun.faces.application.applicationimpl.Events.processListenersAccountingForAdds(Events.java:285)
    at com.sun.faces.application.applicationimpl.Events.invokeViewListenersFor(Events.java:202)
    at com.sun.faces.application.applicationimpl.Events.publishEvent(Events.java:102)
    at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:118)
    at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:110)
    at jakarta.faces.application.ApplicationWrapper.publishEvent(ApplicationWrapper.java:660)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:72)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:178)
    at jakarta.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:692)
    at jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:449)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1554)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:331)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211)
    at org.glassfish.tyrus.servlet.TyrusServletFilter.doFilter(TyrusServletFilter.java:83)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:253)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:211)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:257)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:166)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:757)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:577)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:372)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:239)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:520)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:217)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:174)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:153)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:196)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:535)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:515)
    at java.base/java.lang.Thread.run(Thread.java:1583

Solution

  • As @BalusC said in his comment, removing prependId="false" was the solution.