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

[jsr372-experts] Re: [JAVASERVERFACES-SPEC_PUBLIC-1396] f:socket for SSE and WebSocket PROPOSAL

From: Bauke Scholtz <balusc_at_gmail.com>
Date: Mon, 7 Dec 2015 10:23:22 +0100

Hi,

Last weekend I developed and added o:socket for OmniFaces, which could be
used as base for f:socket:
http://omnifaces.org/docs/javadoc/current/org/omnifaces/cdi/push/Socket.html
Source code can be found here:
https://github.com/omnifaces/omnifaces/tree/master/src/main/java/org/omnifaces/cdi/push
(4 classes).

Some considerations I took are however differ from f:socket:

- I dropped SSE support. As per http://caniuse.com/#feat=websockets vs
http://caniuse.com/#feat=eventsource the WS enjoy broader support
(IE/Edge!) and the protocol is also much more efficient than SSE (no
persistent open connection). A single protocol also keeps server/client
side code much simpler.

- I dropped proposed widgetvar/autoconnect attributes and instead added
enabled attribute. It basically controls whether the underlying WS init
script will be rendered or not. This is evaluated during view render time
and can be ajax-updated. The socket can be explicitly closed via a public
script function taking just channel name.

- I dropped proposed onerror attribute and instead added onclose attribute.
It will also be invoked during onerror and is more useful as the CloseEvent
is then available which also contains the error code. The script is written
that way that it's also invoked when WS is not supported (e.g. IE6-9), a
custom error code of -1 is then passed.

The combination with o:commandScript (similar component is also scheduled
for JSF 2.3, see spec issue 613) makes it a very nice tool to trigger ajax
updates via push.

Cheers, Bauke



On Thu, Sep 3, 2015 at 11:01 PM, Edward Burns <edward.burns_at_oracle.com>
wrote:

> >>>>> On Mon, 24 Aug 2015 05:31:16 -0700, Edward Burns <
> edward.burns_at_oracle.com> said:
>
> EB> Executive Summary: Ed cites discussion thus far and concludes our
> EB> next step is to answer this question: How does this feature interact
> EB> with the JSF request processing lifecycle? In Ed's thinking, it
> EB> does not. Ed asks Cagatay (or anyone else who knows the answer) to
> EB> explain how this works for PrimeFaces p:socket.
>
> I'm having a hard time resolving the sketches people have been sharing
> here on the list with the examples of <p:socket> from the PrimeFaces
> showcase. There are seven examples. Let's take the simplest four of
> them in turn and ask the question, "How does the usage of p:socket
> interact with the JSF lifecycle?"
>
> Counter <http://www.primefaces.org/showcase/push/counter.xhtml>
>
> On first render, the count value is taken from the ApplicationScoped
> GlobalCounterView bean. When the button is pressed, an Ajax postback
> happens and an actionListener is invoked. The actionListener method
> causes a publish() on the PrimeFaces EventBus. The listener for this
> event is synchronously invoked, which returns the count string, which
> somehow makes its way to the WebSocket endpoint, which sends it down the
> WebSocket to the clients. At the same time, the JSF lifecycle yields an
> Ajax response, but the Ajax response does not contain any visible
> markup. Rather, the WebSocket connection is used to cause the counter
> to be updated via jQuery on all browsers currently viewing the same
> page.
>
> Conclusion: the <p:socket> does not interact directly with the JSF
> lifecycle, it just receives the update from the browser. On the other
> hand, the dispatching of the event that causes the push to the browser
> *does* happen during the Ajax request postback.
>
> ViewParam <
> http://www.primefaces.org/showcase/push/viewparam.xhtml?data=foo>
>
> On first render, the incoming data=foo query parameter is decode into
> the <f:viewParam>. During updateModelValues, the value is pushed into
> the EL expression #{viewParamPush.data}. Before Render Response, the
> prerender() method is called. This causes the a publish on the
> PrimeFaces EventBus. The listener for this event is synchronously
> invoked, which returns the data, which somehow makes its way to the
> WebSocket endpoint, which sends it down the WebSocket to the clients.
>
> Conclusion: the <p:socket> does not interact directly with the
> lifecycle. On the other hand, the decoding of the viewParam does happen
> during the full GET request.
>
> Notify <http://www.primefaces.org/showcase/push/notify.xhtml>
>
> On first render, the simple form gets the two values from the request
> scoped bean NotifyView. When the button is pressed, an Ajax submit
> happens, and the action listener NotifyView.send() method is called.
> This causes a publish to the EventBus. Synchronously on the same thread
> the listener is invoked which uses the JSONEncoder to convert the
> FacesMessage to JSON, which is sent to the browser.
>
> Consclusion: Same pattern as before.
>
> Checkin <http://www.primefaces.org/showcase/mobile/checkin.xhtml>
>
> This one uses javascript to set the value of some hidden fields using
> the browser's current position. This is combined with the value of the
> text field and sent via an Ajax POST. The publish() method is bound as
> the actionListener of the button, and this causes a publish to the
> EventBus. From there the listener for the event receives the Checkin
> pojo, which is sent to the browser as JSON.
>
> Conclusion: Same patterns as before.
>
> At this point, I think it is pretty clear that the intended usage of
> <p:socket> is simply to provide a shorthand for opening up a generic
> connection between the server and the client and that the data sent over
> that connection does not have anything to do with the request processing
> lifecycle.
>
> So the bottom line for our design of <f:socket> in JSF 2.3 is that it
> will follow the example of <p:socket> and not necessarily have anything
> to do with the JSF requets processing lifecycle.
>
> Ed
>
>
> --
> | edward.burns_at_oracle.com | office: +1 407 458 0017
> | 44 Business days til JavaOne 2015
> | 59 Business days til DOAG 2015
>