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: Wed, 16 Dec 2015 20:55:37 +0100

Hi,

While developing and testing the o:socket I wasn't satisfied with how WS
session and HTTP session interacted with each other (among others, HTTP
session timeout doesn't trigger a re-handshake of the WS session, causing
its endpoint config to still refer the old HTTP session), so I have further
improved the o:socket to be less dependent on that and made even more
Portlet friendly as there are no hard javax.servlet dependencies anymore.

For security, there's currently in o:socket only a servlet filter in place
which should return 400 on WS handshake requests on non-existing channels:
https://github.com/omnifaces/omnifaces/blob/master/src/main/java/org/omnifaces/cdi/push/SocketChannelFilter.java.
As this isn't Portlet compatible, I'm for Mojarra's f:socket thinking to
programmatically add /javax.faces.push/* to servlet mapping and then do the
job in FacesServlet instead. Would this be OK for Portlets too? Neil? Or
perhaps I should append the current FacesServlet mapping to the push URL
and then inspect the presence of the /javax.faces.push prefix as currently
also done for /javax.faces.resource requests.

Cheers, B


On Fri, Dec 11, 2015 at 1:50 PM, Bauke Scholtz <balusc_at_gmail.com> wrote:

> Hi,
>
> It has in the meanwhile been further improved though. For a live demo, see
> also http://snapshot.omnifaces.org/push/socket
>
> Cheers, B
>
> On 13:46, Fri, Dec 11, 2015 arjan tijms <arjan.tijms_at_gmail.com> wrote:
>
>> Hi,
>>
>> I noticed Bauke already attached the patch for the full feature here:
>>
>> https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1396
>>
>> So if anyone wants to take a look at the code and/or try it out, please
>> do ;)
>>
>> Kind regards,
>> Arjan Tijms
>>
>>
>>
>>
>>
>>
>>
>> On Fri, Dec 11, 2015 at 1:19 PM, Josh Juneau <juneau001_at_gmail.com> wrote:
>>
>>>
>>> Thanks for all of your work on this...it will be great to have all of
>>> the functionality of <o:socket> in the standard <f:socket>!
>>>
>>> Josh Juneau
>>> juneau001_at_gmail.com
>>> http://jj-blogger.blogspot.com
>>> https://www.apress.com/index.php/author/author/view/id/1866
>>>
>>>
>>> On Thu, Dec 10, 2015 at 7:49 AM, Bauke Scholtz <balusc_at_gmail.com> wrote:
>>>
>>>> Yes, interpret it as ".. agree on me taking over .." :) Currently still
>>>> work in progress, programmatic CDI management is not funny.
>>>>
>>>> Just in case, I made some more changes to OmniFaces socket:
>>>> - Added "port" attribute which allows explicitly specifying WS server
>>>> port number (as it's possible that the very same container runs the WS
>>>> server on a different port than the HTTP server).
>>>> - Endpoint is now lazily programmatically registered on first usage of
>>>> o:socket instead than eagerly on startup.
>>>> - Endpoint now accepts only connections from predefined channel names
>>>> (the ones specified in o:socket channel attribute), all others will just be
>>>> aborted by an exception.
>>>>
>>>> Cheers, B
>>>>
>>>> On Tue, Dec 8, 2015 at 11:09 PM, arjan tijms <arjan.tijms_at_gmail.com>
>>>> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> On Tue, Dec 8, 2015 at 8:38 PM, Bauke Scholtz <balusc_at_gmail.com>
>>>>> wrote:
>>>>>
>>>>>> 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).
>>>>>>
>>>>>
>>>>> If I understood correctly, JSF 2.3 can depend on pretty much
>>>>> everything from the Java EE Web Profile, so this shouldn't be a problem by
>>>>> itself. For Tomcat and friends it would then be a matter of adding the JSON
>>>>> encoder separately, wouldn't it? That's currently how it works for the CDI
>>>>> and BeanValidation dependencies.
>>>>>
>>>>> Nevertheless, may be nice to see if some explicit pluggability
>>>>> mechanism can be used here.
>>>>>
>>>>> For an initial version in Mojarra it may be an option to omit JSON
>>>>> first, and then do the JSON support in a second iteration.
>>>>>
>>>>>
>>>>>
>>>>>> 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>.
>>>>>>
>>>>>
>>>>> Just to be sure, with "taking over" I guess you mean "agree that the
>>>>> current approach/design of o:socket is carried over to Mojarra by you",
>>>>> right? ;)
>>>>>
>>>>> Kind regards,
>>>>> Arjan Tijms
>>>>>
>>>>>
>>>>>
>>>>>> 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
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>