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

[jsr372-experts] Re: websocket.

From: Bauke Scholtz <balusc_at_gmail.com>
Date: Wed, 04 Jan 2017 07:04:25 +0000

Hi,

Since m08 you can nest f:ajax into f:websocket. See also javax.faces.Push
javadoc.

As to user, yes indeed channels with same user attribute will receive the
same message. And no, this value cannot be controlled by the client, if
that was your concern.

Cheers, B

On Tue, Jan 3, 2017, 23:56 Michael Müller <michael.mueller_at_mueller-bruehl.de>
wrote:

> Hi all,
>
> Here are some questions and thoughts about websocket:
>
>
> Technically, a websocket is an upgrade of the HTTP protocol which
> establishes a bidirectional communication channel between two peers. Once
> the connection is established it will be kept open until one of the peers
> closes it. Thus, it can be used to send any time any information (with
> respect to technical limitations) from any of both peers to the other.
> Because the channel is open all the time, this connection is faster than a
> series of HTTP request response cycles.
>
> Although a websocket establishes a channel between two peers, it is
> broadly used to broadcast information from one server to all clients. An
> example might be a chat room, where all individual user inputs are
> distributed to all (other) users. A simplified version of this scenario
> might be implemented using Java EE 7 like this:
>
> @OnMessage
> public void onMessage(String message, Session session) throws
> IOException, EncodeException{
> for (Session peer : peers) {
> peer.getBasicRemote().sendObject(session.getId() + ": " + message);
> }
> }
>
>
> Within JSF, we may send data from client to server at any time by
> initiating an ajax request.
> But, before JSF 2.3 there is no standard way to push information from
> server to client.
>
> Here <f:websocket> comes into play.
>
> Via @Push the developer may push information from server to client.
> If I understood it correctly, a send(message) will perform a broadcast,
> whilst .send(message, user) will send to a named user.
> What happens, if a couple of clients use the same value for user? Will it
> be a selective broadcast, e.g. like sending data to one of a couple of
> chatrooms?
> (due to some technical problems which I reported earlier, I could not
> verify this detail yet)
>
> Back on client side, the data is handled by a JavaScript function.
>
>
> Let's take a look at a possible usage of a websocket with JSF 2.2 / Java
> EE 7:
>
> <div>
> Enter message:
> <h:inputText onkeypress="if (event.keyCode === 13)
> {acceptValue(this);}"/>
> <br/>
> </div>
> <h:inputTextarea id="messages" style="width: 100%; min-height: 10em;"/>
>
> A small JavaScript file is needed to establish the communication channel
> and to handle the client side sending and receiving part of the messages.
>
> var websocket;
>
> window.onload = function () {
> websocket = new WebSocket(obtainUri());
> websocket.onerror = function (evt) {
> onError(evt)
> };
> websocket.onmessage = function (evt) {
> onMessage(evt)
> };
> }
>
> function obtainUri(){
> return "ws://" + document.location.host + document.location.pathname +
> "chat";
> }
>
> function onError(evt) {
> writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
> }
>
>
> function acceptValue(element) {
> websocket.send(element.value);
> element.value = "";
> return false;
> }
>
> function onMessage(evt) {
> element = document.getElementById("messages");
> if (element.value.length === 0) {
> element.value = evt.data;
> } else {
> oldTexts = element.value.split("\n").slice(-19);
> element.value = oldTexts.join("\n") + "\n" + evt.data;
> element.scrollTop = element.scrollHeight;
> }
> return;
> }
>
> It is not very much code to broadcast a message from an input field to a
> textarea of all connected clients. Since I use JavaScript, I can implement
> any scenario like broacasting admin messages etc. This solution takes
> advance of the high performing open communication channel in both
> directions.
>
> Now, back to JSF 2.3 and <f:websocket>
>
> To distribute the received data, I need to implement some JavaScript code.
> Formerly, JSF tags could be used to hide all those non-Java stuff. Although
> I can use JavaScript by JSF.js to perform an ajax request, a common way is
> to hide this by using <f:ajax>. With respect to <f:websocket> such a JSF
> feature (hiding away JavaScript) is missing. And we can use <f:websocket>
> only to push data from server to client. Thus we can not take advantage of
> the faster channel from client to server.
>
> I suggest optionally to connect the <f:websocket> to an input element as
> well to an output element, e.g.
>
> <f:websocket channel="xxx" user="yyy" input="idOfUiInputElement"
> output="idOfUiElement">
>
> input is optional whilst output is mutable exclusive with onmessage. Both
> attributes may point to the same element.
>
> For output we may define a behavior like "adds all messages", "replaces
> content with new message", "keeps last n messages".
>
> For the JavaScript fans, we may establish a mutual exclusive option to
> send data via the open channel.
>
> Thoughts?
>
> --
>
> Herzliche Grüße - Best Regards,
>
> Michael Müller
> Brühl, Germany
> blog.mueller-bruehl.de
> it-rezension.de
> @muellermi
>
>
> Read my books
> "Web Development with Java and JSF": https://leanpub.com/jsf
> "Java Lambdas and Parallel Streams":
> http://www.apress.com/de/book/9781484224861
> "Visitors" a photographic image book: https://leanpub.com/visitors
>
>
>