官术网_书友最值得收藏!

JSF WebSocket support

In typical web applications, servers always respond to requests from a browser; there is no way for a server to send data to the client browser without responding to a request. WebSocket technology provides full duplex communication between a browser and a server, allowing servers to independently send data to a client, without having to respond to a request. WebSocket technology allows a myriad of new applications to be developed for the web, including updating stock tickers, multiplayer online games, and chat applications.

Although some of these types of web applications were developed before the advent of WebSockets, they relied on hacks to work around the limitations of the HTTP protocol. With WebSockets, these hacks are no longer necessary.

Traditionally, writing applications taking advantage of the WebSocket protocol required a lot of JavaScript code. JSF 2.3 introduces WebSocket support and abstracts out most of the JavaScript plumbing, allowing us to focus on developing the business logic of our applications.

The following example illustrates a simple chat application developed using JSF 2.3 WebSocket support.

First, let's take a look at an application-scoped CDI named bean responsible for sending messages to all browser clients:

package net.ensode.javaee8book.jsfwebsocket; 
 
import java.io.Serializable; 
import javax.enterprise.context.ApplicationScoped; 
import javax.faces.push.Push; 
import javax.faces.push.PushContext; 
import javax.inject.Inject; 
import javax.inject.Named; 
 
@Named 
@ApplicationScoped 
public class JsfWebSocketMessageSender implements Serializable { 
 
    @Inject 
    @Push 
    private PushContext pushContext; 
 
    public void send(String message) { 
        System.out.println("Sending message: " + message); 
        pushContext.send(message); 
    } 
} 

As shown in the preceding example, in order to send data via WebSockets to the clients we need to inject an instance of an implementation of the javax.faces.push.PushContext interface, and annotate it with the @Push annotation. To actually send the message to the client, we need to invoke the send() method of the injected PushContext implementation; in our example, this is done in the send() method of our CDI named bean.

In our example, there is a session scoped CDI named bean that takes input from the user and passes it to the send() method of the preceding application scoped CDI named bean. Our session scoped CDI bean looks as follows:

package net.ensode.javaee8book.jsfwebsocket; 
import java.io.Serializable; import javax.enterprise.context.SessionScoped; import javax.inject.Inject; import javax.inject.Named; @Named @SessionScoped public class JsfWebSocketController implements Serializable { @Inject
private JsfWebSocketMessageSender jsfWebSocketMessageSender;
private String userName; private String message; public void sendMessage() {
jsfWebSocketMessageSender.send(String.format("%s: %s",

userName,

message));
} //setters getters and less relevant methods omitted for brevity. }

The sendMessage() method of the preceding class calls the send() method of the application scoped CDI bean we discussed earlier, passing the name of the user and the message to be broadcast to all browsers. The aforementioned sendMessage() method is invoked via Ajax when a user clicks a button on the corresponding page, as shown in the following markup:

    <h:body> 
        <f:websocket channel="pushContext"           
onmessage="socketListener" />
<h:form prependId="false"> <h:panelGrid columns="2"> <h:outputLabel for="chatWindow" value="Chat
Window:"/> <textarea id="chatWindow" rows="10"/> <h:outputLabel for="chatInput" value="Type
something here:"/> <h:inputText id="chatInput" value="#{jsfWebSocketController.message}"/> <h:panelGroup/> <h:commandButton actionListener="#
{jsfWebSocketController.sendMessage()}" value="Send message"> <f:ajax execute="chatInput"
render="chatWindow"/> </h:commandButton> </h:panelGrid> </h:form> <script type="text/javascript">
function socketListener(message, channel, event) {

var textArea = document.getElementById('chatWindow');

var textAreaValue = textArea.value;

if (textAreaValue.trim() !== '') {

textAreaValue += "\n";

}

textAreaValue += message;

textArea.value = textAreaValue;

textArea.scrollTop = textArea.scrollHeight;

}

</script>
</h:body>

The <f:websocket> tag in the preceding markup is needed to enable WebSocket support in our page. The value of its channel attribute links the page to the corresponding PushContext instance on the server (in our example, it is defined in the application scoped JsfWebSocketMessageSender CDI named bean). By convention, the value of the channel attribute must match the variable name on the corresponding CDI named bean (pushContext, in our example).

We're only showing the most relevant sections of the example; the complete example can be downloaded from this book's GitHub repository at https://github.com/dheffelfinger/Java-EE-8-Application-Development-Code-Samples.

After building and deploying our application we can see it in action:

主站蜘蛛池模板: 礼泉县| 樟树市| 丹江口市| 来宾市| 花莲市| 汾西县| 仙游县| 岳普湖县| 胶州市| 乃东县| 右玉县| 崇阳县| 依兰县| 红原县| 定陶县| 松桃| 神木县| 和政县| 房山区| 阜阳市| 阿瓦提县| 西平县| 南丰县| 班玛县| 诸暨市| 辽阳县| 涡阳县| 浙江省| 呼伦贝尔市| 荃湾区| 新河县| 巴东县| 平罗县| 卓尼县| 启东市| 芷江| 武安市| 普定县| 江西省| 德兴市| 湄潭县|