• 沒有找到結果。

Relaying Events from the Server to the Browser

在文檔中 HTML5 and JavaScript Web Apps (頁 111-116)

alert("WebSocket connection opened successfully");

};

alert("WebSocket connection closed");

};

After the WebSocket connection opens, the onmessage event fires whenever the server sends data to the client. If the client wants to send data to the server, it can do so as follows:

objWebSocket.send("Hello World");

Sending messages in the form of strings over raw WebSockets isn’t very appealing, however, when you want to develop enterprise-style web applications. Because current WebSocket implementations deal mostly with strings, you can use JSON to transfer data to and from the server.

But how do you propagate the server-side events that are fired on the server and then bubble them up on the client? One approach is to relay the events. When a specific server-side event is fired, use a listener or observer to translate the data to JSON and send it to all connected clients.

Relaying Events from the Server to the Browser

Before you can successfully communicate with a server, you need to know what you’re talking to and how. For the chapter’s examples, I’m using the JBoss AS7 application

server and embedding Jetty within the web application. The main reasoning behind this approach is to take advantage of a lightweight Java EE 6.0 [Full Profile] application server. There are a few other Java options out there, such as GlassFish or running Jetty standalone, but this solution offers contexts and dependency injection (CDI), distribut‐

ed transactions, scalable JMS messaging, and data grid support out of the box. Such support is extremely valuable in cutting-edge enterprise initiatives and private cloud architectures.

Because this approach embeds one server (Jetty) with another server (JBoss), we can use it with any app server, even one that may not support WebSockets, and enable existing, older applications to take advantage of real-time connections.

The full deployable source code for this example is on the “embedded-jetty branch”. A few things are worth noting here:

Security

Because the WebSocket server is running on a different port (8081) than the JBoss AS7 server (8080), we must account for not having authentication cookies, and so on. A reverse proxy can handle this problem, however, as you’ll see in the last section of this chapter.

Proxies

As if existing proxy servers weren’t already a huge problem for running WebSockets and HTTP over the same port, in this example, we are now running them separately.

Threading

Because we’re observing and listening for CDI events, we must perform some same thread operations and connection sharing.

The code below first sets up the WebSocket server using Jetty’s WebSocketHandler and embeds it inside a ServletContextListener. Although the app shares a synchronized set of WebSocket connections across threads, we ensure that only a single thread can execute a method or block at one time by using the synchronized keyword. To relay the CDI event to the browser, we must store all the WebSocket connections in a Concur rentHashSet and write new connections to it as they come online. At any time, the ConcurrentHashSet will be read on a different thread so we know where to relay the CDI events. The ChatWebSocketHandler contains a global set of WebSocket connections and adds each new connection within the Jetty server.

public class ChatWebSocketHandler extends WebSocketHandler { private static Set<ChatWebSocket> websockets =

new ConcurrentHashSet<ChatWebSocket>();

public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {

return new ChatWebSocket();

}

public class ChatWebSocket implements WebSocket.OnTextMessage {

public static synchronized Set<ChatWebSocket> getWebsockets() { return websockets;

} }

Next, we embed the Jetty WebSocket-capable server within the web application:

private Server server = null;

/**

* Start Embedding Jetty server when WEB Application is started.

* */

public void contextInitialized(ServletContextEvent event) { try {

// 1) Create a Jetty server with the 8081 port.

InetAddress addr = InetAddress.getLocalHost();

this.server = new Server();

chatWebSocketHandler.setHandler(new DefaultHandler());

server.setHandler(chatWebSocketHandler);

Now we’ll create a method to observe CDI events and send the fired Member events to all active connections. This relays a very simple cdievent JavaScript object, which will be pushed to all connected clients and then evaluated on the browser through a Java‐

Script interpreter.

public void observeItemEvent(@Observes Member member) { try {

The above code observes the following event when a new Member is registered through the web interface. As you can see below, memberEventSrc.fire(member) is fired when a user registers through the provided RESTful URL.

@POST

@Consumes(MediaType.APPLICATION_FORM_URLENCODED)

@Produces(MediaType.APPLICATION_JSON)

@FormParam("email") String email,

member.setPhoneNumber(phone);

try {

//Fire the CDI event

memberEventSrc.fire(member);

Finally, we set up the WebSocket JavaScript client and safely avoid using the eval() method to execute the received JavaScript.

...

Here is the JavaScript code that listens for the CDI event and executes the necessary client-side code:

window.addEventListener('memberEvent', function(e) { alert(e.name + ' just registered!');

}, false);

As you can see, this is a very prototyped approach to achieve a running WebSocket server, but it’s a step forward in adding a usable programming layer on top of the Web‐

Socket protocol.

Using the new and shiny

As of this writing, JBoss has just begun to implement WebSockets natively on JBoss AS7.

The same example from above has been converted for native WebSocket support (without embedding Jetty) on JBoss AS 7.1.2 and beyond. This gives you the benefit of having both HTTP and WS traffic over the same port without needing to worry about managing data across threads. To see a chat room example that uses native WebSocket, check out https://github.com/html5e/HTML5-Mobile-WebSocket. You can find the JBoss WebSocket source at https://github.com/mikebrock/jboss-websockets.

在文檔中 HTML5 and JavaScript Web Apps (頁 111-116)

相關文件