Angular JS Magazine

miercuri, 31 decembrie 2014

Angular JS - Use an Angular-Websocket Client with a Java Websocket Endpoint

In this tip you can see how to use the Angular Websocket module for connecting client applications to servers. For this case, we have a Java endpoint, as below:

package com.mycompany.angularws;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/atpendpoint")
public class ATPWSEndpoint {

    private static final Logger LOG = Logger.getLogger(ATPWSEndpoint.class.getName());
    private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());

    @OnMessage
    public String onMessage(String message) {
        if (message != null) {
            if (message.equals("HELLO SERVER")) {
                return "{\"hello\": \"Hello, if you need the ATP list just press the button ...\"}";
            } else if (message.equals("ATP SERVER")) {
                return "[{\"name\": \"Nadal, Rafael (ESP)\", \"email\": \"nadalrafael@gmail.com\", \"rank\": \"1\"},"
                        + "{\"name\": \"Djokovic, Novak (SRB)\", \"email\": \"djokovicnovak@gmail.com\", \"rank\": \"2\"},"
                        + "{\"name\": \"Federer, Roger (SUI)\", \"email\": \"federerroger@gmail.com\", \"rank\": \"3\"},"
                        + "{\"name\": \"Wawrinka, Stan (SUI)\", \"email\": \"wawrinkastan@gmail.com\", \"rank\": \"4\"},"
                        + "{\"name\": \"Ferrer, David (ESP)\", \"email\": \"ferrerdavid@gmail.com\", \"rank\": \"5\"}]";
            }
        }
        return "";
    }

    @OnOpen
    public void onOpen(Session peer) {
        LOG.info("Connection opened ...");
        peers.add(peer);
    }

    @OnClose
    public void onClose(Session peer) {
        LOG.info("Connection closed ...");
        peers.remove(peer);
    }
}


And, we access this endpoint like this:

  • the client sends a hello message (HELLO SERVER), and the server answers with a simple text (Hello, if you need the ATP list just press the button ...).
  • the client send another message, (ATP SERVER), and the server answers with a JSON object containing a list of tennis players
  • the client will display this list in a tabel

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" type="text/css" 
                 href="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular-csp.css">
        <title>Angular JS Web-Socket</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">        
    </head>
    <body ng-app="ATP_PLAYERS" class="ng-cloak">                
        <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
        <script src="resources/js/angular-websocket.js"></script>

        <div ng-controller="atpController">

            <div id="helloId"></div>

            <form ng-submit="submit()">                
                <button id="btnAtpId" type="submit" disabled>Send Message</button>
            </form>

            <table>
                <thead>
                    <tr>
                        <th>Rank</th>   
                        <th>Name</th>   
                        <th>E-mail</th>   
                    </tr>
                </thead>
                <tbody>
                    <tr ng-repeat="item in ATP.atp">
                        <td>{{item.rank}}</td>               
                        <td>{{item.name}}</td>
                        <td>{{item.email}}</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <script language="javascript" type="text/javascript">
            angular.module('ATP_PLAYERS', ['ngWebSocket'])
                    .factory('ATP', function ($websocket) {
                        // Open a WebSocket connection
                        var ws = $websocket("ws://" + document.location.host + 
                              document.location.pathname + "atpendpoint");
                        var atp = [];

                        ws.onMessage(function (event) {
                            console.log('message: ', event.data);
                            var response;
                            try {
                                response = angular.fromJson(event.data);
                            } catch (e) {
                                document.getElementById("helloId").innerHTML = 
                                                                                   "Sorry, connection failed ...";
                                document.getElementById("btnAtpId").disabled = false;
                                console.log('error: ', e);
                                response = {'error': e};
                            }

                            if (response.hello) {
                                document.getElementById("helloId").innerHTML = response.hello;
                                document.getElementById("btnAtpId").disabled = false;
                            } else {
                                for (var i = 0; i < response.length; i++) {
                                    atp.push({
                                        rank: response[i].rank,
                                        name: response[i].name,
                                        email: response[i].email
                                    });
                                }
                            }
                        });
                        ws.onError(function (event) {
                            console.log('connection Error', event);
                        });
                        ws.onClose(function (event) {
                            console.log('connection closed', event);
                        });
                        ws.onOpen(function () {
                            console.log('connection open');
                            ws.send('HELLO SERVER');
                        });

                        return {
                            atp: atp,
                            status: function () {
                                return ws.readyState;
                            },
                            send: function (message) {
                                if (angular.isString(message)) {
                                    ws.send(message);
                                }
                                else if (angular.isObject(message)) {
                                    ws.send(JSON.stringify(message));
                                }
                            }
                        };
                    })
                    .controller('atpController', function ($scope, ATP) {
                        $scope.ATP = ATP;

                        $scope.submit = function () {
                            ATP.send("ATP SERVER");
                        };                                               
                    });
        </script>
    </body>
</html>