Sunday, October 26, 2014

Websockets and the real-time web, part II [The Server Side]



The Server Side

After a little bit of history to support the motivation behind the creation of WebSockets, let us move forward and experiment with a pseudo-real-world code example. 

For a change, I will not be presenting the "Hello, world!" echo app or the proverbial chat example, no disregard for those classics, they are very important steps in the journey to learn WebSockets, but there are simply too many incarnations of those projects on any imaginable supporting platform and language (human or otherwise).

240.000 results for the search of "websockets chat example"
240.000 results for the search of "websockets chat example" (your mileage may vary.)

Instead, our little project for the day will be a parking lot occupancy monitor. In this example we will create a WebSocket-based service that reports, on real-time, the space availability of all the public parking lots owned by the fictional company A-Lotta-Parking.

A-Lotta-Parking Usage Monitor in action

As you may already be familiar with, the WebSocket client and server implementations, when writing the client part in JavaScript, the same implementation can be used with all the supporting clients. On the server side, however, there are a few libraries implementing JSR-356, but since Oracle included java native WebSocket support starting with Java EE 7, and as Tomcat 8 already supports that implementation, it is the one we will be using as our web server in this example.

I am going to focus on the WebSocket related classes in this example, so you may want to download the complete project from Github, for Eclipse Luna or NetBeans 8.0.1. The Github projects also come with some hopefully helpful comments.

Without further ado, let the coding begin!

WebSocket: The Server Side

The application we are going to develop is a simple monitor for a number of parking lots that belong to the same company, the goal is to monitor, in real-time, the used capacity of each of the parking lots. 

The basic building block of the application is a small java class that contains the information related to one of the parking venues, we will call it ParkingLotRec. This class contains the name, the total capacity and the used capacity of the parking lot. 

A list of objects of this class, wrapped in an instance of ParkingLotsUpdate is the payload that will be transmitted to the client monitoring the operation.

Listing 1: ParkingLotRec.java

package com.pmarquezh.alottaparking.parkinglot;

public class ParkingLotRec {
    private String plName;
    private int    plCapacity;
    private int    plUsedCapacity;

    public ParkingLotRec ( String plName, 
                           int    plCapacity, 
                           int    plUsedCapacity ) {
        
        this.plName                = plName;
        this.plCapacity            = plCapacity;
        this.plUsedCapacity        = plUsedCapacity;

    }

    public String getPlName() {
        return plName;
    }

    public void setPlName(String plName) {
        this.plName = plName;
    }

    public int getPlCapacity() {
        return plCapacity;
    }

    public void setPlCapacity(int plCapacity) {
        this.plCapacity = plCapacity;
    }

    public int getPlUsedCapacity() {
        return plUsedCapacity;
    }

    public void setPlUsedCapacity(int plUsedCapacity) {
        this.plUsedCapacity = plUsedCapacity;
    }
}

At the heart of any Java WebSocket application is the Server Endpoint, and now that we know the type of information that we want to push over the connection, let's see how and when it will flow.

As you may already know, Java Server Endpoints can be implemented by subclassing javax.websocket.Endpoint or by annotating an otherwise ordinary POJO. Since the annotated approach is a bit simpler, we will implement ours that way.

Listing 2: ParkingLotMonitorEndpoint.java
package com.pmarquezh.alottaparking.parkinglot;

import java.io.IOException;
import javax.websocket.CloseReason;
import javax.websocket.EncodeException;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint ( value = "/parkingLotUpdates", 
                  encoders = { MonitorUpdateEncoder.class } )
public class ParkingLotMonitorEndpoint implements ParkingLotsDataSourceListener {
    private Session               session;
    private ParkingLotsDataSource dataSource;
    
    @OnOpen
    public void openConnection ( Session session, EndpointConfig config ) {
        this.session = session;
        
        this.dataSource = new ParkingLotsDataSource ( );
        this.dataSource.addParkingLotDataSourceListener ( this );
    }
    
    @OnMessage
    public void handleCommand ( String command ) {
        System.out.println ( "@OnMessage: " + command );
        switch ( command ) {
            case "startMonitor":
                System.out.println ( "command: " + command );
                this.dataSource.start ( );
                break;

            case "stopMonitor":
                System.out.println ( "command: " + command );
                this.dataSource.stop ( );
                break;

            default:
               System.out.println ( "command: " + command );
               throw new RuntimeException ( "Command " + command + " not found." );
        }        
    }
        
    @OnError
    public void handleError ( Throwable t ) {
        System.out.println ( "Error: " + t.getMessage ( ) );
    }
    
    @OnClose
    public void closeConnection ( CloseReason reason ) {
        dataSource.stop ( );
    }

    public void handleCommandResponse ( String response ) {
        try {
            session.getBasicRemote ( ).sendText ( response );
        } catch ( IOException ioe ) {
            this.handleError ( ioe );
        }
    }

    @Override
    public void handleParkingLotUsageData ( ParkingLotsUpdate plu ) {
        try {
            session.getBasicRemote ( ).sendObject ( plu );
        } catch ( IOException | EncodeException ioe ) {
            this.handleError ( ioe );
        }
    }    
}

Noteworthy

@ServerEndpoint ( value = "/parkingLotUpdates", 
                  encoders = { MonitorUpdateEncoder.class } )
At the top of the class, we find the familiar @ServerEndpoint annotation with a value of /parkingLotUpdates, the name under which the service will be published, but we also see a less common encoders parameter with a value of: MonitorUpdateEncoder.class.  

Encoders and Decoders provide support for converting between WebSocket messages and custom Java types. In our case, the MonitorUpdateEncoder class has the noble job of transforming ParkingLotsUpdate objects (a list of ParkingLotRec objects) generated by our monitor engine into a JSON representation, suitable for consumption by the client.


Listing 3: MonitorUpdateEncoder.java

package com.pmarquezh.alottaparking.parkinglot;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.websocket.*;

/**
 *    This Encoder transforms the list of update objects into a JSON representation. 
 * 
 *    I used Java's own JSONObject library for this task. Included from Java EE7 and on. 
*/
public class MonitorUpdateEncoder implements Encoder.Text {
    
    @Override
    public void init ( EndpointConfig config ) { }
    
    @Override
    public void destroy ( ) { }
    
    @Override
    public String encode ( ParkingLotsUpdate plu ) {
        
        
        JsonArrayBuilder ab = Json.createArrayBuilder ( );
        
        for ( ParkingLotRec r : plu.getLots ( ) ) {
            ab.add ( Json.createObjectBuilder ( )
                        .add ( "plName", r.getPlName                  ( ) )
                        .add ( "plCapacity", r.getPlCapacity          ( ) )
                        .add ( "plUsedCapacity", r.getPlUsedCapacity  ( ) )
                   );
        }
        
        JsonObject parkingInfo = Json.createObjectBuilder ( )
                                 .add ( "lotsMonitor", ab ).build ( );
        
        return parkingInfo.toString ( );
    }
       
}

Our Encoder implementation uses the javax.json.Json classes that were also released with Java EE 7 but are not bundled with Tomcat 8, so I included them in the Gitbub projects (got the.jar from the mvn repository).

Noteworthy
public class ParkingLotMonitorEndpoint implements ParkingLotsDataSourceListener { 

Our endpoint class implements ParkingLotsDataSourceListener, which is an interface that defines a single method: handleParkingLotUsageData, the method to invoke when there is new data to be pushed to the client.

For our purpose, new usage data is produced by a thread running in the ParkingLotsDataSource Class and, when ready, it is pushed to all the registered listeners in the form of an instance of ParkingLotsUpdate.

Listing 4: ParkingLotsDataSource.java (Relevant methods)

    //   Create a new thread to simulate incoming data from the different parking lots.
    public void start ( ) {

        if ( this.updateThread == null ) {
            
            shouldUpdate = true;
            
            updateThread = new Thread ( ) {
                @Override
                public void run ( ) {
                    while ( shouldUpdate ) {
                        doUpdate ( );
                        try { 
                            Thread.sleep ( generateRandomParkingLotUpdatePeriod ( ) ); 
                        } catch ( InterruptedException ie ) {
                            System.out.println ( "updateThread.run ( ): " + ie.getMessage ( ) );
                            shouldUpdate = false;
                        }
                    }
                }
            };
            
            updateThread.start ( );

        }
    }

    //   Update the parking lot usage. Invoked from "updateThread"
    public void doUpdate ( ) {
        this.updateUsage ( ); 
        this.notifyListeners ( parkingLotsUsage );
    }    
    
    //   Broadcast the new data to registered listeners
    private void notifyListeners ( List lots ) {
        for ( ParkingLotsDataSourceListener l : this.listeners ) {
            ParkingLotsUpdate plu = new ParkingLotsUpdate ( lots );
            l.handleParkingLotUsageData ( plu );
        }       
    }

    //   Notify the simulation thread that we are closing shop.
    public void stop ( ) {
        this.updateThread.interrupt ( );
    }


As you can see, the start method creates a thread called updateThread, which in turn calls doUpdate () repeatedly at randomly spaced intervals (just to spice up a bit the simulation.)

doUpdate is responsible for gathering the new data and then posting it to all registered listeners via notifyListeners ().
 
To wrap up the server side implementation, when our listener (ParkingLotMonitorEndpoint) receives the new data (an instance of ParkingLotsUpdate) , it kindly pushes it to the registered clients through the WebSocket connection, but not before encoding it into a JSON representation that can be happily consumed at the other endpoint (remember the MonitorUpdateEncoder viewed a bit earlier).

And so this is, my dear reader, one of the ways to implement a server side WebSocket based monitor, which will diligently push new data continuously to the clients until the connection is explicitly closed (or a nasty network error occurs.)

For the visual magic part, the client side implementation, please go on to the third part of this article, where we will be working with JSON, jQuery, HTML5 and one of the coolest JavaScript charting libraries I know: ZingChart.

What would you have done differently?


Sunrise at the Santa Cruz Sea Port, Tenerife
Photo Credit: Paulo Márquez Herrero


PM/pm

Websockets and the real-time web, part III [The Client Side]

Link to Part I of the Article: http://ruminationsontechnology.blogspot.com.es/2014/10/websockets-and-real-time-web-part-i.html

Link to Part II of the Article: http://ruminationsontechnology.blogspot.com/2014/10/preview-websockets-and-real-time-web.html

The Client Side

Now that we visited the belly of the beast in part II of this article, let us complete the circle by taking a look at the client side of the implementation.

As noted in part II, the complete code for the tutorial in this article can be downloaded from Github, for Eclipse Luna or NetBeans 8.0.1.

As a quick refresher, we are implementing a web based monitor that reports, on real-time, the space availability of all the public parking lots owned by the fictional company A-Lotta-Parking.

The client side implementation will rely on:
  • JavaScript/jQuery
  • HTML5 
 And I assume that you have a basic working knowledge of them.

The HTML

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>A-Lotta-Parking</title>
        <script src="js/jquery/jquery-2.1.0.js"></script>
        <script src="js/zingchart/zingchart-html5-min.js"></script>
        <script src="js/zingchart/zingchart.jquery.js"></script>
        <script src="js/alottaparking.js"></script>

        <link href="css/alottaparking.css" rel="stylesheet">
    </head>
    <body>
        <nav id="buttons">
            <button id="btnOpenConnection">Open WS</button>
            <button id="btnStartMonitor" disabled>Start Monitor</button>
            <button id="btnStopMonitor" disabled>Stop Monitor</button>
            <button id="btnCloseServerConnection" disabled>Close WS</button>
        </nav>
        <section id="chart"></section>
        <section>
            <table>
                <thead>
                    <tr>
                        <th>N°</th>
                        <th>Lot Name</th>
                        <th>Capacity</th>
                        <th>Used Capacity</th>
                        <th>Used Percentage</th>
                    </tr>
                </thead>
                <tbody id="tableData">
                </tbody>
            </table>
        </section>
    </body>
</html>

Other than the mandatory includes in the head section, our index.html file has three blocks:

The header block, where there are four buttons for the control of the operation.

The first section block, where the monitoring chart will exist, and...

The second section block, where initially there is a simple html table skeleton, which will, during active operation, display the data related to the chart above it.

That was pretty straightforward.

The JavaScript

alotaparking.js

    function openSocketConnection ( ) {
        
        //   Create the WebSocket
        websocket = new WebSocket ( "ws://localhost:8084/A-Lotta-Parking/parkingLotUpdates" );

        //   When the server messages the client, we receive the message here.
        websocket.onmessage = function ( evt ) {

            var obj = $.parseJSON( evt.data );
            if ( obj.lotsMonitor !== undefined ) { processSnapshot   ( obj ); }
        };

        //   When the server closes the WebSocket, we receive the notification here.
        websocket.onclose = function ( evt ) {
            //alert("Server closed WebSocket");
        };

        //   Set html buttons state
        buttonStates ( "openedState" );

    }

    //   When the client requests to start the monitoring, we sent the "startMonitor" message here.
    function sendStartCommand ( ) {
        websocket.send ( "startMonitor" ); 

        //   Set html buttons state
        buttonStates ( "startedState" );
        
    }

    //   When the client requests to stop the monitoring, we sent the "stopMonitor" message here.
    function sendStopCommand ( ) {
        websocket.send ( "stopMonitor" ); 

        //   Set html buttons state
        buttonStates ( "stoppedState" );
    
    }

    //   When the client requests that the server close the websocket, we send the "closeConnection" here.
    //   
    //   Of course, as a client, we have the power to close the websocket connection from
    //   the client side using "websocket.close()". I just chose to do it in a different 
    //   fashion and politely request the server to do so on our behalf.
    //   
    //   In this tutorial, we are also using the other method, we are listening to the "beforeunload" event, 
    //   which is triggered when the user closes the browser window, in that case, we close the WebSocket from 
    //   the client side (as can be seen in the "destroy" function a few linea ahead.
    function sendCloseCommand ( ) {
        websocket.send ( "closeConnection" ); 

        //   Set html buttons state
        buttonStates ( "closedState" );

    }

    //   Closes the WebSocket connection from the client side.
    function closeSocketConnection ( ) {
        websocket.close ( );
    }

    //   We are exiting, close everything.
    function destroy ( ) {
        sendStopCommand       ( );
        closeSocketConnection ( );
    }

As with any HTML5 websocket implementation, we have to cover the lifecycle methods and events, which are:


websocket = new Websocket ( url );
Creates a new connection to the WebSocket represented by url.

websocket.onmessage
Listener that receives incoming messages from the server endpoint.

websocket.onclose
Listener that receives a CLOSE notification when the server closes the connection.

websocket.send
Method that sends messages to the server endpoint. The messages that can be sent by this application are :
  • startMonitor
  • stopMonitor
  • closeConnection
websocket.close
Method to close the connection from the client side.

The different functions have accompanying comments in the code to make it easier to study them.

In this simple application I have defined three different states so we can experiment with the WebSocket lifecycle. The different states change by clicking on the different buttons as shown in the following simplified Finite State Machine diagram:

Simplified Finite State Diagram

 What functionality would you add to this simple example application?


Paragliding to the moon at Puerto de La Cruz, Tenerife
Photo Credit: Paulo Márquez Herrero

PM/pm

Thursday, October 2, 2014

Websockets and the real-time web, part I




 
Let us start with bit of history...

The basic motivation behind websockets is not new, ever since the use of the web went viral we have attempted to build the ultimate mechanism to push information to the users on real-time, without requiring them to repeatedly hit the refresh/reload button in their web browsers.

I can agree with the thought that a billion users worldwide reloading the content of their web browsers in a continuum can seem a bit Orwellian, a little barbaric and even ridiculous, but that is basically what many of the pseudo-real-time-web solutions do, only that they do it via some HTML or JavaScript-based mechanism on behalf of their human masters, among those techniques I could mention ajax, comet and the infamous meta refresh tag.

The problem is not that the creators of these technologies were unprepared for the task at hand or that they lacked imagination, or even that HTTP is a static, stateless, client-controlled request-response protocol.

The problem is that we humans are never satisfied with whatever new toy we are presented with, we need to bend it, jailbreak it, disassemble it, break it, fix it, over-clock it, tune it up, overhaul it, and, ultimately, attempt to use it in ways that the poor and now doomed toy was never intended or designed to be used. And that, my dear reader, is the basis of all innovation since the dawn of our species. But I digress...

Over time, a few techniques and technologies were developed to help solve the problem in a more elegant way, those usually involved piggybacking some external technology on the web browser via plug-ins such as Adobe Flash, Java Applets or using proprietary browser technologies, but none of them became the universal de-facto standard, with Adobe Flash being the one that came closest to claiming that prize.

A few years ago, around 2009, work began on a new way of realizing the elusive goal of having a standards-defined, universally-supported and lightweight technology that allowed full-duplex communication over a single TCP socket. That work, over a few iterations, spawned RFC 6455, better known as the definition for The Websocket Protocol.

So now that you have a shiny spanking new and well supported standard, is it time to rewrite every single web app ever written to use websockets.? Well as is the case with mostly everything web, the answer is: it depends. Some applications will surely benefit from this new technology, for others, it will be hardly noticeable, moreover, the websockets standard is not alone in the race for the ultimate real-time solution for the web as we know it, lower level protocols such as SCTP, BEEP and Google's SPDY are being developed and evolved as you read these lines and could spell a short reign for websockets, or maybe not.

What are you planning to do (or have already done) on real-time?

Street Lamp at San Cristobal de La Laguna, Tenerife.

Photo Credit: Paulo Márquez Herrero

[Coming Soon: Websockets and the real-time web, part II (let us code) ]
PM/pm