STOMP with shared workers
authorgustavo <gu.martinm@gmail.com>
Sun, 22 May 2016 11:14:26 +0000 (13:14 +0200)
committergustavo <gu.martinm@gmail.com>
Sun, 22 May 2016 11:14:26 +0000 (13:14 +0200)
angularjs/stomp/src/stomp/app/app.module.js
angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.controller.js [new file with mode: 0644]
angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.html [new file with mode: 0644]
angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.module.js [new file with mode: 0644]
angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.js [new file with mode: 0644]
angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.spec.js [new file with mode: 0644]
angularjs/stomp/src/stomp/app/shared-stomp/shared-worker.service.js [new file with mode: 0644]
angularjs/stomp/src/stomp/index.html
angularjs/stomp/src/stomp/workers/shared.js [new file with mode: 0644]

index 7059d83..0af14bd 100644 (file)
@@ -21,7 +21,8 @@
     'app.widgets',
 
     /* Feature areas */
-    'app.example'
+    'app.example',
+    'app.shared-stomp'
   ]);
 
 }());
diff --git a/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.controller.js b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.controller.js
new file mode 100644 (file)
index 0000000..13f7abd
--- /dev/null
@@ -0,0 +1,92 @@
+(function () {
+  'use strict';
+
+  angular
+    .module('app.shared-stomp')
+    .controller('SharedStompController', SharedStompController);
+
+  /**
+   * @ngdoc controller
+   * @name app.shared-stomp.controller:SharedStompController
+   *
+   * @requires $location
+   * @requires app.shared-stomp.sharedWorker
+   *
+   * <p>
+   * <br>
+   * {@link https://docs.angularjs.org/api/ng/service/$location $location}
+   * </p>
+   *
+   * @description
+   * SharedStompController controller.
+   */
+  /* @ngInject */
+  function SharedStompController($location, sharedWorker) {
+    var vm = this;
+
+
+    vm.url = $location.protocol() + '://' + $location.host() + '/spring-stomp-server-full/fullportfolio';
+    vm.clientDestination = '/topic/greeting';
+    vm.serverDestination = '/app/greeting';
+    vm.connectHeaders = JSON.stringify({
+      login: 'mylogin',
+      passcode: 'mypasscode',
+      //  User defined headers
+      'client-id': 'gumartin-id'
+    }, null, 4);
+    //  User defined headers
+    vm.sendHeaders = JSON.stringify({
+      priority: 9
+    }, null, 4);
+    //  User defined headers
+    vm.subscribeHeaders = JSON.stringify({
+      id: 123456
+    }, null, 4);
+
+
+
+    vm.connect = function () {
+      sharedWorker.connect(JSON.parse(connectHeaders), connectSuccessCallback, connectErrorCallback);
+    };
+
+    vm.subscribe = function () {
+      sharedWorker.subscribe(clientDestination, subscribeCallback, JSON.parse(subscribeHeaders));
+    };
+
+    vm.unSubscribe = function () {
+      sharedWorker.unSubscribe();
+    };
+
+    vm.send = function () {
+      sharedWorker.send(vm.serverDestination, JSON.parse(vm.sendHeaders), vm.payload);
+    };
+
+    vm.disconnect = function() {
+      sharedWorker.disconnect(disconnectCallback);
+    };
+
+    function connectSuccessCallback() {
+      // called back after the client is connected and authenticated to the STOMP server
+      alert('got connection');
+    }
+
+    function connectErrorCallback(error) {
+      // display the error's message header:
+      alert(error.headers.message);
+    }
+
+    function subscribeCallback(message) {
+      // called when the client receives a STOMP message from the server
+      if (message.body) {
+        alert('got message with body ' + message.body);
+      } else {
+        alert('got empty message');
+      }
+    }
+
+    function disconnectCallback() {
+      alert('See you next time!');
+    }
+  }
+
+})();
diff --git a/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.html b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.html
new file mode 100644 (file)
index 0000000..1d2c3ea
--- /dev/null
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<div class="container" ng-controller="ExampleController as vm">
+  <div>
+    <span>1. Connect</span><br>
+    <button ng-click="vm.connect()">Connect to Endpoint</button>
+    <br>
+
+    <label>
+      Endpoint:<br>
+      <input value="http://localhost:8080" ng-model="vm.url" placeholder="url">
+    </label>
+    <br>
+    <label>
+      Headers:<br>
+      <textarea style="width: 200%; border: none" auto-height
+                ng-model="vm.connectHeaders" placeholder="headers">
+        {"login":"superadmin","passcode":"12345678"}
+      </textarea>
+    </label>
+  </div>
+
+  <hr>
+
+  <div>
+    <span>2. Disconnect</span><br>
+    <button ng-click="vm.disconnect()">Disconnect from Endpoint</button>
+  </div>
+
+  <hr>
+
+  <div>
+    <span>3. Subscribe</span><br>
+    <button ng-click="vm.subscribe()">Subscribe to destination</button>
+    <br>
+
+    <label>
+      Queue:<br>
+      <input value="/rpc/" ng-model="vm.clientDestination" placeholder="Client-Destination">
+    </label>
+    <br>
+    <label>
+      Headers:<br>
+      <textarea style="width: 200%; border: none" auto-height
+                ng-model="vm.subscribeHeaders" placeholder="headers">
+        {"rid": 1234}
+      </textarea>
+    </label>
+  </div>
+
+  <hr>
+
+  <div>
+    <span>4. Unsubscribe</span><br>
+    <button ng-click="vm.unSubscribe()">Unsubscribe from destination</button>
+  </div>
+
+  <hr>
+
+  <div>
+    <span>5. Send</span><br>
+    <button ng-click="vm.send()">Send message to server</button>
+    <br>
+
+    <label>
+      Server-Destination:<br>
+      <input value="/dest" ng-model="vm.serverDestination" placeholder="channel">
+    </label>
+    <br>
+    <label>
+      Body / Payload:<br>
+      <textarea style="width: 200%; border: none" auto-height
+                ng-model="vm.payload" placeholder="payload">
+        {"key":"value"}
+      </textarea>
+    </label>
+    <br>
+    <label>
+      Headers:<br>
+      <textarea style="width: 200%; border: none" auto-height
+                ng-model="vm.sendHeaders" size="50" placeholder="headers">
+        {"rid": 1234}
+      </textarea>
+    </label>
+  </div>
+
+  <textarea id="log"></textarea>
+
+</div>
diff --git a/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.module.js b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.module.js
new file mode 100644 (file)
index 0000000..54a04d6
--- /dev/null
@@ -0,0 +1,20 @@
+(function() {
+  'use strict';
+
+  /**
+   * @ngdoc overview
+   * @name app.shared-stomp
+   *
+   * @requires app.core
+   *
+   * @description
+   * # app.shared-stomp
+   *
+   * ## Module STOMP Shared Worker example.
+   * STOMP Shared Worker example
+   */
+  angular.module('app.shared-stomp', [
+    'app.core'
+  ]);
+
+})();
diff --git a/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.js b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.js
new file mode 100644 (file)
index 0000000..1e8c8ac
--- /dev/null
@@ -0,0 +1,37 @@
+(function() {
+  'use strict';
+
+  angular
+    .module('app.shared-stomp')
+    .config(route);
+
+  /**
+   * @ngdoc service
+   * @name app.shared-stomp.route
+   *
+   * @requires $stateProvider
+   * @requires $urlRouterProvider
+   *
+   * <p>
+   * <br>
+   * {@link http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider $stateProvider} <br>
+   * {@link http://angular-ui.github.io/ui-router/site/#/api/ui.router.router.$urlRouterProvider $urlRouterProvider}
+   * </p>
+   *
+   *
+   * @description
+   * Router configuration for Shared Worker STOMP application.
+   */
+  /* @ngInject */
+  function route($stateProvider, $urlRouterProvider) {
+    var state = 'shared-stomp';
+    var config = {
+      abstract: false,
+      url: '/shared-stomp',
+      templateUrl: 'app/shared-stomp/shared-stomp.html'
+    };
+
+    $urlRouterProvider.otherwise(state);
+    $stateProvider.state(state, config);
+  }
+}());
diff --git a/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.spec.js b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.spec.js
new file mode 100644 (file)
index 0000000..86c70c6
--- /dev/null
@@ -0,0 +1,24 @@
+describe('app.shared-stomp', function() {
+  'use strict';
+
+  describe('state', function() {
+    var view = {
+      example: 'app/shared-stomp/shared-stomp.html'
+    };
+    var $state;
+
+    beforeEach(function() {
+      module('app.shared-stomp');
+
+      inject(function(_$state_) {
+        $state = _$state_;
+      });
+    });
+
+    it('should map /shared-stomp route to users View template', function() {
+      expect($state.get('shared-stomp').templateUrl).toEqual(view.example);
+    });
+
+  });
+
+});
diff --git a/angularjs/stomp/src/stomp/app/shared-stomp/shared-worker.service.js b/angularjs/stomp/src/stomp/app/shared-stomp/shared-worker.service.js
new file mode 100644 (file)
index 0000000..1727b34
--- /dev/null
@@ -0,0 +1,154 @@
+(function () {
+  'use strict';
+
+  angular
+    .module('app.shared-stomp')
+    .factory('sharedWorker', sharedWorker);
+
+  /**
+   * @ngdoc service
+   * @name app.shared-stomp.sharedWorker
+   *
+   * @requires $window
+   *
+   * <p>
+   * <br>
+   * {@link https://docs.angularjs.org/api/ng/service/$window $window} <br>
+   * </p>
+   *
+   * @description
+   * sharedWorker service.
+   */
+  /* @ngInject */
+  function sharedWorker($window) {
+    var _messagePort;
+    var _connectSuccessCallback;
+    var _connectErrorCallback;
+    var _subscribeCallback;
+    var _disconnectCallback;
+
+    init();
+
+    return {
+      connect: connect,
+      subscribe: subscribe,
+      unSubscribe: unSubscribe,
+      send: send,
+      disconnect: disconnect
+    };
+
+    function init() {
+      if (!!$window.SharedWorker) {
+        var sharedWorker = new $window.SharedWorker('scripts/workers/shared.js');
+        _messagePort = sharedWorker.port;
+        _messagePort.onmessage = onMessage;
+      } else {
+        throw new Error('Shared Web Workers not supported. Try with a modern browser');
+      }
+    }
+
+    /**
+     * @ngdoc method
+     * @name  connect
+     * @methodOf app.shared-stomp.connect
+     *
+     * @description
+     * Connects to back end.
+     *
+     * @param {string} url URL to connect.
+     * @param {string} connectHeaders Connection headers.
+     * @param {function} connectSuccessCallback Connection success call back.
+     * @param {function} connectErrorCallback Connection error call back.
+     *
+     */
+    function connect (url, connectHeaders, connectSuccessCallback, connectErrorCallback) {
+      var message = {
+        command: 'connect',
+        url: url,
+        connectHeaders: connectHeaders
+      };
+
+      _connectSuccessCallback = connectSuccessCallback;
+      _connectErrorCallback = connectErrorCallback;
+      _messagePort.postMessage(message);
+    }
+
+    function subscribe(clientDestination, subscribeCallback, subscribeHeaders) {
+      var message = {
+        command: 'subscribe',
+        clientDestination: clientDestination,
+        subscribeHeaders: subscribeHeaders
+      };
+
+      _subscribeCallback = subscribeCallback;
+      _messagePort.postMessage(message);
+    }
+
+    function unSubscribe() {
+      var message = {
+        command: 'unSubscribe'
+      };
+
+      _messagePort.postMessage(message);
+    }
+
+    function send(serverDestination, sendHeaders, payload) {
+      var message = {
+        command: 'send',
+        serverDestination: serverDestination,
+        sendHeaders: sendHeaders,
+        payload: payload
+      };
+
+      _messagePort.postMessage(message);
+    }
+
+    function disconnect(disconnectCallback) {
+      var message = {
+        command: 'disconnect'
+      };
+
+      _disconnectCallback = disconnectCallback;
+      _messagePort.postMessage(message);
+    }
+
+
+    function onMessage(event) {
+      if (event.data.error) {
+        // Error
+      } else {
+        callBack(event.data);
+      }
+    }
+    // var send {
+    //     command:
+    //     connectionHeaders:
+    // }
+    // var result {
+    //     command:
+    //     connectError:
+    //     message:
+    // };
+    function callBack(data) {
+
+      switch(data.command) {
+        case 'connectSuccessCallback':
+          _connectSuccessCallback();
+          break;
+        case 'connectErrorCallback':
+          _connectErrorCallback(data.connectError);
+          break;
+        case 'subscribeCallback':
+          _subscribeCallback(data.message);
+          break;
+        case 'disconnectCallback':
+          _disconnectCallback();
+          break;
+        default:
+          break;
+      }
+
+    }
+  }
+
+}());
index 3b89ad8..b5609ad 100644 (file)
     <!-- inject:js -->
     <script src="/src/stomp/app/widgets/widgets.module.js"></script>
     <script src="/src/stomp/app/widgets/auto-height.directive.js"></script>
+    <script src="/src/stomp/app/shared-stomp/shared-stomp.module.js"></script>
+    <script src="/src/stomp/app/shared-stomp/shared-worker.service.js"></script>
+    <script src="/src/stomp/app/shared-stomp/shared-stomp.route.js"></script>
+    <script src="/src/stomp/app/shared-stomp/shared-stomp.controller.js"></script>
     <script src="/src/stomp/app/example/example.module.js"></script>
     <script src="/src/stomp/app/example/example.route.js"></script>
     <script src="/src/stomp/app/example/example.controller.js"></script>
diff --git a/angularjs/stomp/src/stomp/workers/shared.js b/angularjs/stomp/src/stomp/workers/shared.js
new file mode 100644 (file)
index 0000000..a56f571
--- /dev/null
@@ -0,0 +1,117 @@
+'use strict';
+
+importScripts('/bower_components/sockjs/sockjs.js');
+importScripts('/bower_components/stomp-websocket/lib/stomp.min.js');
+
+var messagePorts = [];
+var client;
+var subscription;
+
+self.onconnect = function(event) {
+  var messagePort = event.ports[0];
+  messagePort.onmessage = onMessage;
+  // Starts the sending of messages queued on the port
+  // (only needed when using EventTarget.addEventListener; it is implied when using MessagePort.onmessage.)
+  // messagePort.start();
+
+  messagePorts.push(messagePort);
+
+  // When and where should I call close method?
+  // Should I call messagePort.close() or SharedWorkerGlobalScope.close()?
+  // SharedWorker doesn't have close method but SharedWorkerGlobalScope has one :(
+};
+
+self.onerror = function() {
+  self.console.log('SharedWorkerGlobalScope: There is an error with the shared worker!');
+};
+
+function onMessage(event) {
+  callCommand(event.data);
+}
+
+function postMessage(message) {
+  messagePorts.forEach(function (messagePort) {
+    messagePort.postMessage(message);
+  });
+}
+
+function callCommand(data) {
+  switch(data.command) {
+    case 'connect':
+      connect(data.url, data.connectHeaders);
+      break;
+    case 'subscribe':
+      subscribe(data.clientDestination,data.subscribeHeaders);
+      break;
+    case 'unSubscribe':
+      unSubscribe();
+      break;
+    case 'send':
+      send(data.serverDestination, data.sendHeaders, data.payload);
+      break;
+    case 'disconnect':
+      disconnect();
+      break;
+    default:
+      break;
+  }
+}
+
+function connect(url, connectHeaders) {
+  var options = {
+    debug: true,
+    devel: true,
+    //jscs:disable
+    protocols_whitelist: ['websocket', 'xdr-streaming', 'xhr-streaming'],
+    //jscs:enable
+    transports: ['websocket', 'xdr-streaming', 'xhr-streaming']
+  };
+
+  var ws = new SockJS(url, undefined, options);
+  client = Stomp.over(ws);
+  client.heartbeat.outgoing = 20000; // client will send heartbeats every 20000ms
+  client.heartbeat.incoming = 20000;     // client does not want to receive heartbeats from the server
+  client.connect(JSON.parse(connectHeaders), connectSuccessCallback, connectErrorCallback);
+}
+
+function subscribe(clientDestination, subscribeHeaders) {
+  subscription = client.subscribe(clientDestination, subscribeCallback, JSON.parse(subscribeHeaders));
+}
+
+function unSubscribe() {
+  subscription.unsubscribe();
+}
+
+function send(serverDestination, sendHeaders, payload) {
+  client.send(serverDestination, JSON.parse(sendHeaders), payload);
+}
+
+function disconnect() {
+  client.disconnect(disconnectCallback);
+}
+
+function connectSuccessCallback() {
+  postMessage({
+    command: 'connectSuccessCallback'
+  });
+}
+
+function connectErrorCallback(error) {
+  postMessage({
+    command: 'connectErrorCallback',
+    connectError: error
+  });
+}
+
+function subscribeCallback(message) {
+  postMessage({
+    command: 'subscribeCallback',
+    message: message
+  });
+}
+
+function disconnectCallback() {
+  postMessage({
+    command: 'disconnectCallback'
+  });
+}