From fb6fbea49f4d1f31109537b5ade92c0c860c875b Mon Sep 17 00:00:00 2001 From: gustavo Date: Sun, 22 May 2016 13:14:26 +0200 Subject: [PATCH] STOMP with shared workers --- angularjs/stomp/src/stomp/app/app.module.js | 3 +- .../app/shared-stomp/shared-stomp.controller.js | 92 ++++++++++++ .../src/stomp/app/shared-stomp/shared-stomp.html | 88 ++++++++++++ .../stomp/app/shared-stomp/shared-stomp.module.js | 20 +++ .../stomp/app/shared-stomp/shared-stomp.route.js | 37 +++++ .../app/shared-stomp/shared-stomp.route.spec.js | 24 ++++ .../app/shared-stomp/shared-worker.service.js | 154 +++++++++++++++++++++ angularjs/stomp/src/stomp/index.html | 4 + angularjs/stomp/src/stomp/workers/shared.js | 117 ++++++++++++++++ 9 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.controller.js create mode 100644 angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.html create mode 100644 angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.module.js create mode 100644 angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.js create mode 100644 angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.spec.js create mode 100644 angularjs/stomp/src/stomp/app/shared-stomp/shared-worker.service.js create mode 100644 angularjs/stomp/src/stomp/workers/shared.js diff --git a/angularjs/stomp/src/stomp/app/app.module.js b/angularjs/stomp/src/stomp/app/app.module.js index 7059d83..0af14bd 100644 --- a/angularjs/stomp/src/stomp/app/app.module.js +++ b/angularjs/stomp/src/stomp/app/app.module.js @@ -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 index 0000000..13f7abd --- /dev/null +++ b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.controller.js @@ -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 + * + *

+ *
+ * {@link https://docs.angularjs.org/api/ng/service/$location $location} + *

+ * + * @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 index 0000000..1d2c3ea --- /dev/null +++ b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.html @@ -0,0 +1,88 @@ + +
+
+ 1. Connect
+ +
+ + +
+ +
+ +
+ +
+ 2. Disconnect
+ +
+ +
+ +
+ 3. Subscribe
+ +
+ + +
+ +
+ +
+ +
+ 4. Unsubscribe
+ +
+ +
+ +
+ 5. Send
+ +
+ + +
+ +
+ +
+ + + +
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 index 0000000..54a04d6 --- /dev/null +++ b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.module.js @@ -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 index 0000000..1e8c8ac --- /dev/null +++ b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.js @@ -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 + * + *

+ *
+ * {@link http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider $stateProvider}
+ * {@link http://angular-ui.github.io/ui-router/site/#/api/ui.router.router.$urlRouterProvider $urlRouterProvider} + *

+ * + * + * @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 index 0000000..86c70c6 --- /dev/null +++ b/angularjs/stomp/src/stomp/app/shared-stomp/shared-stomp.route.spec.js @@ -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 index 0000000..1727b34 --- /dev/null +++ b/angularjs/stomp/src/stomp/app/shared-stomp/shared-worker.service.js @@ -0,0 +1,154 @@ +(function () { + 'use strict'; + + angular + .module('app.shared-stomp') + .factory('sharedWorker', sharedWorker); + + /** + * @ngdoc service + * @name app.shared-stomp.sharedWorker + * + * @requires $window + * + *

+ *
+ * {@link https://docs.angularjs.org/api/ng/service/$window $window}
+ *

+ * + * @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; + } + + } + } + +}()); diff --git a/angularjs/stomp/src/stomp/index.html b/angularjs/stomp/src/stomp/index.html index 3b89ad8..b5609ad 100644 --- a/angularjs/stomp/src/stomp/index.html +++ b/angularjs/stomp/src/stomp/index.html @@ -57,6 +57,10 @@ + + + + diff --git a/angularjs/stomp/src/stomp/workers/shared.js b/angularjs/stomp/src/stomp/workers/shared.js new file mode 100644 index 0000000..a56f571 --- /dev/null +++ b/angularjs/stomp/src/stomp/workers/shared.js @@ -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' + }); +} -- 2.1.4