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: Tue, 8 Dec 2015 20:38:10 +0100

Hi Manfred,

It would only require a change in PartialViewContext API. It must offer a
method which triggers the partial response writer to start and end the
<eval>. Right now this is nowhere available in public API and even not in
Mojarra implementation. Directly accessing the PartialResponseWriter to
achieve the <eval> job isn't possible. I'd propose adding
PartialViewContext#getEvalScripts() which returns a mutable List<String> so
that the developer can add scripts to <eval> of the <partial-response>.
This allows easily executing scripts on complete of ajax response. Both
OmniFaces and PrimeFaces have an enhanced PartialViewContext implementation
which offers this additional method which is ultimately used by
respectively RequestContext#execute() and Ajax#oncomplete(). The <o:socket>
uses it to open/close the push channel during ajax requests depending on
its "enabled" attribute.

Further the o:socket encodes the push message as JSON string in and the
receiver script parses it back to JSON object before invoking the onmessage
function. This JSON step is not necessary, but really nice to have. Only,
it may require an internal JSON encoder or perhaps the javax.json API
(which is unfortunately not available on servletcontainers like Tomcat and
Jetty on contrary to WebSockets). I could omit the JSON feature and leave
it up to the developer. If JSON is not mandatory, it will be easy to create
an API and impl for the RI.

I only wonder if both you and Ed agree on taking over the <o:socket> in its
current form for JSF 2.3 <f:socket>. Among others, I omitted the SSE
support as it isn't standardized yet while WS is even backed by a Java EE
API (JSR356) which is even implemented in barebones servletcontainers like
Tomcat and Jetty. And, some attributes have been reworked to keep it as
simple as possible.

Cheers, B


On Tue, Dec 8, 2015 at 5:40 PM, manfred riem <manfred.riem_at_oracle.com>
wrote:

> Hi Bauke,
>
> Looks good!
>
> How much work would it be to make it all available for the RI?
>
> Thanks!
>
> Kind regards,
> Manfred Riem
>
>
> On 12/7/15, 1:38 PM, Bauke Scholtz wrote:
>
> For the rendered javadoc see also first link in my previous mail:
> http://omnifaces.org/docs/javadoc/current/org/omnifaces/cdi/push/Socket.html
> It reads more pretty.
>
> Cheers, B
>
> On Mon, Dec 7, 2015 at 7:08 PM, arjan tijms <arjan.tijms_at_gmail.com> wrote:
>
>> Hi,
>>
>> Looks great! I noticed there's a bunch of information about the working
>> and usage of this in the javadoc of this class:
>> https://github.com/omnifaces/omnifaces/blob/master/src/main/java/org/omnifaces/cdi/push/Socket.java
>>
>> That one may be a good read for the EG specifically.
>>
>> Would be great if a version of this can be pushed to the RI before long.
>> It's been a while since the last commit for a 2.3 feature, and nothing
>> better to keep the community interested than some actual working code they
>> can play around with I guess ;)
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>> On Mon, Dec 7, 2015 at 10:23 AM, Bauke Scholtz <balusc_at_gmail.com> wrote:
>>
>>> 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
>>>>
>>>
>>>
>>
>