jsr372-experts@javaserverfaces-spec-public.java.net

[jsr372-experts] Use clientId instead of channel name in jsf.push.open(...) and jsf.push.close(...)

From: Leonardo Uribe <leonardo.uribe_at_irian.at>
Date: Thu, 20 Oct 2016 22:33:55 -0500

Hi

Following the review of websocket API, I have found there are 3 new
javascript
methods:

jsf.push.init(...)
jsf.push.open(channel)
jsf.push.close(channel)

The first one was already discussed in a previous email, but the remaining
two
suggest developers can only use one f:websocket declaration per channel
in a view.

This is a severe restriction that limits code reuse. Imagine this example:

<f:websocket channel="refresh" ...>
    <f:ajax event="updatePanelA"/>
</f:websocket>

And in other section of the same view there is something like this:

<f:websocket channel="refresh" ...>
    <f:ajax event="updatePanelB"/>
</f:websocket>

The idea is both declarations can share the same channel, but both have
different purposes. Since both channels are connected automatically,
it is only necessary to create one websocket connection per view.

What I mean is the channel name is a logical pointer that can have multiple
"receivers", even in the same view. f:websocket must be smart enough to
detect when two components are sharing the same channel (if the channel
token is equals for both jsf.push.init(...) scripts, it is fine to share
it). If "connected" is set to false, you can just generate another
channel token in the Renderer to isolate the session, and in that way you
could have two or more websocket connections for the same channel
in a view.

If jsf.push.open(channel) and jsf.push.close(channel) use the channel
name, it is not possible to identify which websocket connection must be
opened or closed under the previous reasoning. So, I would like propose
that jsf.push.open(...) and jsf.push.close(...) use the clientId
instead, because it has more sense in that way and it allows more
flexibility to do so. It also raise the question if we should create
f:wsopen and f:wsclose client behavior tags to wrap there two javascript
methods and bound them to buttons and other jsf components more easily.

Another possible concept that support use the clientId is just render
an invisible "div" panel for each f:websocket declaration in the
place the component is located like this:

<div id="mainForm:j_id_p" style="display:none"></div>

If jsf.push.init(...) pass the clientId, it is possible to include
a check for this panel in the DOM tree. If the panel exists then process
the functions associated with the component, otherwise ignore or
close automatically the websocket connection. If there is a section in
the view that has been removed using f:ajax and that section has a
f:websocket declaration then this code will detect the change and
avoid further processing. This will ensure consistency between
f:websocket and f:ajax.

regards,

Leonardo Uribe