X

Pavel Bucek's Weblog

  • December 1, 2014

New Tyrus sample - Shared Collection

Sometime in JavaOne 2014 timeframe colleague came to me and showed me Meteor.js library, which seems to be really nice javascript framework, client and server side (kudos to the authors!). I started looking at the docs and examples and discovered leaderboard sample. In short, it is about having javascript collection backed up by some (persistent) storage on the server side, which is also shared (or replicated, if you wish) to all other clients. Meteor.js does this in Javascript “class” called Mongo.Collection (used to be Meteor.Collection, but it was renamed before 1.0 release). I really liked the idea and dug little bit more into the implementation and saw that they are using Socket.IO for the communication with the server, which is basically websocket (+fallback and other handy features).

Long story short – I wanted to do something similar and ideally publish it as Tyrus sample :-) and it wasn’t that hard! Obviously, this task is more about client javascript implementation than about what is going to happen on the server side, but it was refreshing experience – next step is Tyrus version of  Socket.IO (nah, I’m kidding…).

I don’t really want to go into details in javascript implementation, since I don’t feel very confident about that (and you can check it out in the Tyrus sources), but the goal was to create a java map-like API to store data and have it synchronized using WebSocket with all other client.

1
2
3
4
5
6
7
8
9
10
/**
* Create new Tyrus map.
*
* @param {string} url
* @param {function} updateListener
* @constructor
*/
Tyrus.Collection.Map = function (url, updateListener) {
// …
}

I created Tyrus.Collection namespace and “class” Map in it. The constructor have two arguments – URL of websocket endpoint and update listener. Update listener is invoked whenever the map is changed (this is not optimal, so currently it might be called even when you are putting the key value pair which is already there). Map has following public methods, which should feel familiar for java developers:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* Get size of the map.
*
* @returns {Number} number of records in the map.
*/
self.size = function () { };
/**
* Return {@code true} when the map is empty.
*
* @returns {boolean} {@code true} when the map is empty, {@code false} otherwise.
*/
self.isEmpty = function () { };
/**
* Get value corresponding to provided key from a map.
*
* @param {string} key key.
* @returns {*} value for corresponding key or {@code null} when there is no such key.
*/
self.get = function (key) { };
/**
* Put an item into the map.
*
* @param {string} key key.
* @param {*} value value.
*/
self.put = function (key, value) { };
/**
* Remove key (and corresponding value) from the map.
*
* @param {string} key key to be removed.
*/
self.remove = function (key) { };
/**
* Clear the map.
*/
self.clear = function () { };
/**
* Get the key set.
*
* @returns {Array} array containing all keys from the map (as indexes AND values - TODO).
*/
self.keySet = function () { };

Server side implementation was quite simple and it currently stores the info only in static map. You can easily extend this by persisting the map to file/database/anywhere else. The communication is driven by very simple protocol, which broadcasts mutating messages to other clients. All get operations are handled by client-side javascript, the map on the server side is kept in sync only because it is a source for clients connected later – this is why this is just “shared” map, not “distributed” (which would be more complicated to implement). The source of the sever endpoint can be found on github, in samples directory: SharedCollectionEndpoint.

Instruction how to run this sample are included in README.html in sample root dir.

When you access the front page, you should see something like:

You can add/modify existing items in the map by using the form on the bottom side (it will automatically load an item when you click on it) and you can remove any item by clicking on the red cross on the right side. All changes should be automatically propagated to all other clients (just open the page in another browser window).

Hope you’ll enjoy the new sample and if you have any comments or suggestions, please send us a note to users@tyrus.java.net.

Links

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.