[ 
https://issues.apache.org/jira/browse/MYFACES-4660?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18037759#comment-18037759
 ] 

Volodymyr Siedlecki edited comment on MYFACES-4660 at 11/12/25 2:56 PM:
------------------------------------------------------------------------

I ran the TCK and found one error below.  I think it's likely caused by this 
change. 

Test:  
[https://github.com/jakartaee/faces/blob/5a6a31f5a6e6f3284d6f7bd8141028bef78f1102/tck/faces23/websocket/src/test/java/ee/jakarta/tck/faces/test/javaee8/websocket/Spec1396IT.java#L94]
 

Page: test-faces23-websocket/spec1396ViewScopedWebsocket.xhtml 

Problematic Line: 
https://github.com/apache/myfaces/blob/4.1.x/impl/src/main/java/org/apache/myfaces/push/cdi/WebsocketSessionManager.java#L145

{color:#cccccc}[{color}{color:#569cd6}11{color}{color:#cccccc}/{color}{color:#569cd6}12{color}{color:#cccccc}/{color}{color:#569cd6}25{color}{color:#cccccc},
 
{color}{color:#6a9955}9:50:58{color}{color:#cccccc}:{color}{color:#569cd6}616{color}{color:#cccccc}
 EST] {color}{color:#569cd6}00000069{color}{color:#cccccc} 
{color}{color:#569cd6}org.apache.myfaces.context.AjaxExceptionHandlerImpl{color}{color:#cccccc}
 E {color}{color:#ce9178}java.lang.NullPointerException{color}{color:#cccccc} 
occurred while processing INVOKE_APPLICATION 
[Location=clientId={color}{color:#ce9178}"form:button"{color}{color:#cccccc}]{color}
{color:#ce9178}java.lang.NullPointerException{color}{color:#cccccc}: Cannot 
invoke 
{color}{color:#ce9178}"java.util.concurrent.ConcurrentMap.keySet()"{color}{color:#cccccc}
 because the return value of 
{color}{color:#ce9178}"java.util.concurrent.ConcurrentMap.get(Object)"{color}{color:#cccccc}
 is {color}{color:#569cd6}null{color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.WebsocketSessionManager.getChannelTokensForUser(WebsocketSessionManager.java:145){color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.WebsocketSessionManager$Proxy$_$$_WeldClientProxy.getChannelTokensForUser(Unknown
 Source){color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.PushContextImpl.send(PushContextImpl.java:127){color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.PushContextImpl.send(PushContextImpl.java:116){color}
{color:#ce9178} at 
ee.jakarta.tck.faces.test.javaee8.websocket.Spec1396.send(Spec1396.java:47){color}
{color:#ce9178} at 
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103){color}
{color:#ce9178} at 
java.base/java.lang.reflect.Method.invoke(Method.java:580){color}
{color:#ce9178} at 
org.apache.el.parser.AstValue.invoke(AstValue.java:232){color}
{color:#ce9178} at 
org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:230){color}
{color:#ce9178} at 
org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96){color}
{color:#ce9178} at 
org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:67){color}
{color:#ce9178} at 
jakarta.faces.component.UICommand.broadcast(UICommand.java:65){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1248){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:429){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot._process(UIViewRoot.java:1719){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot.processApplication(UIViewRoot.java:930){color}
{color:#ce9178} at 
org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:43){color}
{color:#ce9178} at 
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:172){color}
{color:#ce9178} at 
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:125){color}
{color:#ce9178} at 
jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:223)
{color}


was (Author: volosied):
I ran the TCK and found one error below.  I think it's likely caused by this 
change. 

Test:  
[https://github.com/jakartaee/faces/blob/5a6a31f5a6e6f3284d6f7bd8141028bef78f1102/tck/faces23/websocket/src/test/java/ee/jakarta/tck/faces/test/javaee8/websocket/Spec1396IT.java#L94]
 

Page: test-faces23-websocket/spec1396ViewScopedWebsocket.xhtml 


{color:#cccccc}[{color}{color:#569cd6}11{color}{color:#cccccc}/{color}{color:#569cd6}12{color}{color:#cccccc}/{color}{color:#569cd6}25{color}{color:#cccccc},
 
{color}{color:#6a9955}9:50:58{color}{color:#cccccc}:{color}{color:#569cd6}616{color}{color:#cccccc}
 EST] {color}{color:#569cd6}00000069{color}{color:#cccccc} 
{color}{color:#569cd6}org.apache.myfaces.context.AjaxExceptionHandlerImpl{color}{color:#cccccc}
 E {color}{color:#ce9178}java.lang.NullPointerException{color}{color:#cccccc} 
occurred while processing INVOKE_APPLICATION 
[Location=clientId={color}{color:#ce9178}"form:button"{color}{color:#cccccc}]{color}
{color:#ce9178}java.lang.NullPointerException{color}{color:#cccccc}: Cannot 
invoke 
{color}{color:#ce9178}"java.util.concurrent.ConcurrentMap.keySet()"{color}{color:#cccccc}
 because the return value of 
{color}{color:#ce9178}"java.util.concurrent.ConcurrentMap.get(Object)"{color}{color:#cccccc}
 is {color}{color:#569cd6}null{color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.WebsocketSessionManager.getChannelTokensForUser(WebsocketSessionManager.java:145){color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.WebsocketSessionManager$Proxy$_$$_WeldClientProxy.getChannelTokensForUser(Unknown
 Source){color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.PushContextImpl.send(PushContextImpl.java:127){color}
{color:#ce9178} at 
org.apache.myfaces.push.cdi.PushContextImpl.send(PushContextImpl.java:116){color}
{color:#ce9178} at 
ee.jakarta.tck.faces.test.javaee8.websocket.Spec1396.send(Spec1396.java:47){color}
{color:#ce9178} at 
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103){color}
{color:#ce9178} at 
java.base/java.lang.reflect.Method.invoke(Method.java:580){color}
{color:#ce9178} at 
org.apache.el.parser.AstValue.invoke(AstValue.java:232){color}
{color:#ce9178} at 
org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:230){color}
{color:#ce9178} at 
org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96){color}
{color:#ce9178} at 
org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:67){color}
{color:#ce9178} at 
jakarta.faces.component.UICommand.broadcast(UICommand.java:65){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1248){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:429){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot._process(UIViewRoot.java:1719){color}
{color:#ce9178} at 
jakarta.faces.component.UIViewRoot.processApplication(UIViewRoot.java:930){color}
{color:#ce9178} at 
org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:43){color}
{color:#ce9178} at 
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:172){color}
{color:#ce9178} at 
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:125){color}
{color:#ce9178} at 
jakarta.faces.webapp.FacesServlet.service(FacesServlet.java:223)

{color}

> WebSockets - view destroying + multiple tabs/windows
> ----------------------------------------------------
>
>                 Key: MYFACES-4660
>                 URL: https://issues.apache.org/jira/browse/MYFACES-4660
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: General
>    Affects Versions: 4.0.0, 4.0.1, 4.0.2, 5.0.0
>            Reporter: Milan Siebenbürger
>            Priority: Minor
>             Fix For: 5.0.0, 4.1.2, 4.0.4
>
>         Attachments: test-faces23-websocket.war
>
>
> Hello,
> We have identified two (hopefully minor) bugs while using WebSockets.
> 1. destroying SessionScope channelToken when destroying ViewScope bean
> If the user reaches the NUMBER_OF_VIEWS_IN_SESSION limit, the ViewScope bean 
> (which holds channelTokens) is automatically destroyed (@PreDestroy). 
> Additionally, any channelToken from the parent sessionScope is destroyed, 
> even if it is still in use. Unfortunately, this destruction occurs after a 
> new view is created, so the component is rendered, the WebSocket session is 
> connected, but the channelToken in the WebsocketScopeManager is destroyed.
> The solution to this issue could be simple. The destruction of the 
> sessionScope channelToken could be left to the automatic destruction of the 
> SessionScope. We have been testing this solution for several weeks, and it 
> seems to be working fine.
>  
> 2. using application in multiple tabs / browser windows (with same http 
> session)
> When a user is using the application in more than one tab/window within the 
> same HTTP session, the user session channels are duplicated (with the same 
> channelToken) and connected to the same user identification, resulting in two 
> or more WebSocket sessions. Push messages are then sent to all 
> tokens/sessions. So far, everything is working as expected.
> However, when one of the views is destroyed (i.e., a tab/window is closed), 
> the connected WebSocket session is also destroyed (which is expected). 
> Unfortunately, this also will cause user connection to be removed . Since we 
> don't track how many times the user is using this particular channelToken, 
> the WebSocket connections in the other tabs/windows are also disrupted.
> A potential solution to this issue could involve tracking the number of times 
> the user starts using the channelToken. We could then remove the user 
> connection after all instances of its usage are destroyed, or, alternatively, 
> when the SessionScope object is destroyed.
> Unfortunately, implementing this solution would cause a breaking change. It 
> would involve replacing the Set holding channelTokens with a HashMap that 
> also keeps track of the number of usages (refer to 
> WebsocketSessionManager.java:62). Since the method getUserMap is public and 
> may be used by others (such as ourselves, for implementing WebSocket 
> heartbeat), they would need to update their code accordingly with the new 
> version of MyFaces. An alternative approach could be implemented using 
> another collection to hold the usage count of channelTokens. However, this 
> method may not be as elegant, although it would not necessitate users to 
> modify their applications.
> So, the questions:
>  * which of these to implement?
>  * and to which version (5.0? or 4.X?)
>  
> Of course, I will prepare the changes in the form of a pull request to check 
> the changes
>  
> Milan



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to