JEE7 WebSocket and JSF - Notification System


WebSocket: WebSocket provides a mechanism to create a persistent connection between client (browser) and the server, such that both parties can send and receive data as long as the connection is open.

Prior to WebSocket, AJAX  and long poll (example Gmail) techniques were used to achieve/implement a server update. The drawback of above technique is that the communication always had to be initiated by client(browser) and server responded to it. WebSocket on the other hand, once after a socket is open, message can be sent by either server or the client anytime.

Support for WebSocket(JSR 356) has been added in JEE 7, you can use either Glassfish 4 or Jetty to run the example from this blog.

WebSocket

WebSocket system has two parts: client side and server side. The difference between a websocket client and a websocket server lies only in the means by which the two parties are connected. A websocket client is a websocket endpoint that initiates a connection to a peer and a websocket server is a websocket endpoint that is published and awaits connections from peers.

In a typical web application where the client is a browser, WebSocket client is implemented in javascript and the server side WebSocket endpoint is implemented in java using api added by JSR 356.
Note:  you can also write a standalone WebSocket client in java.

Server Side End Point:

The Server End Point (aka listener) is a program that awaits/listens to incoming WebSocket connection requests on the server. JSR 356 provides two means of creating a server side end point: programmatic endpoints and annotated endpoint. To create a programmatic endpoint, you extend the javax.websocket.Endpoint class and override its life cycle methods. To create an annotated endpoint, you decorate a Java class and some of its methods with the annotations provided by the javax.websocket.Server packages.
The example in this blog uses annotation based (simpler) approach.

Any java class can be made a WebSocket server endpoint by annotating it with @ServerEndpoint( URI). This annotation takes a parameter "URI" (Note: parameter is required). It identifies unique name for the endpoint. The server publishes WebSocket endpoint and the client uses the endpoint's URI to connect to the server. The URI is relative to the root of the web socket container and must begin with a leading "/". 

WebSocket connection, being asynchronous in nature,  life-cycle events like connection open or connection close and incoming messages are implemented as call back methods. There is an annotation for each of such events;  for example method responsible for receiving open socket request from client is annotated with @OnOpen annotation and method to process message is annotated with @OnMessage and likewise for close @onClose. These call back methods are invoked by container to handle corresponding events.

@OnMessage
  public void messageReceiver(String message) {
    System.out.println("Received message:" + message);
  }

  @OnOpen
  public void onOpen(Session session) {
    System.out.println("onOpen: " + session.getId());
    sessions.add(session);
    System.out.println("onOpen: Notification list size: " + sessions.size());
  }

ClientSide End Point:
Client side WebSocket for a browser client is implemented using javascript. WebSocket being a W3C standard, most new versions of browsers support it. Lets take a look at javascript code from template.xhtml.
A WebSocket is created by simply instantiating WebSocket class, the parameter "URL" is in the format server: port/End Point URI. Here the End Point is what is defined in the server side "End Point" declaration.
var host = "ws://localhost:8080/JSFWebSockets/notification";
var wSocket = new WebSocket(host); 

Browser support/compatibility is determined by:
browserSupport = ("WebSocket" in window) ? true : false;

Method "initializeReception()" is meant to be called as body.onLoad() {see createPerson.xhtml}, once its determined that the browser is compatible, a web socket connection is open
if (browserSupport)
{
  wSocket.onopen = function()
  {
     wSocket.send("ping");
  }
}
Notice that javascript code pattern is very similar to the server side code, there is a method corresponding to call back function for onOpen,  onMessage and onClose.
Once a WebSocket connection with the server is open, message can be sent and received by either side.

About the example:

This example implements a simple Notification system using web sockets.

How To Run:
Tools: Glassfish 4, Netbeans 7.3 and Maven (archetype: webapp-javaee7)
Download source code from here
Build application using netbeans and then deploy application to Glassfish server.

The default page is createPerson.xhtml (just a dummy page, ignore the Person part), load the page in browser (the javascript from template.xhtml opens up socket connection) and then in an another browser window open notification.xhtml, type a message and press button to send message; you will see a alert message on createPerson.xhtml window and also on notification.xhtml. Try this with opening up a few more createPerson.xhtml browser windows and resend notification. You should see a alert message on each of the windows. To get a list of client connected to the server endpoint load receivers.xhtml  in a separate window.



4 comments: