Wilson Mar bio photo

Wilson Mar

Hello!

Calendar YouTube Github

LinkedIn

Here is how your Internet of Things gets massive, fast

US (English)   Norsk (Norwegian)   Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Estonian   اَلْعَرَبِيَّةُ (Egypt Arabic)   Napali   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean

Overview

This tutorial aims to enable someone with minimal tech experience to critically evaluate the internals of swim.it service using its sample code.

Instead of waving confusing marketing hype and technical buzzwords in front of you, this tutorial shows you the technical details in context as we go hands-on through the step-by-step instructions, with commentary NOTEs and PROTIP advice along the way.

1) Use Google Chrome Developer Tools to analyze the use of web sockets by swim.it’s chat demo client public web page connecting to swim.it’s public cloud server

2) Use Linux tree and other commands to analyze the use of Angular and other libraries while installing and invoking locally a swim JavaScript client

3) Analyze the use of Homebrew during the install of a swim server locally.

By carefully sequencing the commentary below, we minimize the “mental gymastics” one has to do to understand the many technologies involved.

To reduce frustration, this tutorial includes common error messages and how to prevent/resolve them.

Explanation of 3rd party utilities such as Homebrew tap, etc. are also included here.

TODO: Make a video based on text on this page.

This article explains these buzzwords in context, listed alphabetically here:

TODO: Add links to explanations of each of the buzzwords above.

Wiki plan

Transparency of progress is presented in the wiki at:
https://github.com/swimit/swim-examples/wiki

Sure, “anyone” can code this library (in a 24 hour hackathon), but this team has done it but putting together all the other many aspects of a software development organization. See my list of what a Developer Evangelist needes to consider.

The SWIM.it organization makes its money (has a “business model”) from charging for traffic on servers the company sets up in its cloud or yours.


Open a chat demo WebSocket client

Next, let’s look at how the SWIM company’s sample web page interacts with the SWIM cloud.

  1. Land (open) a web page to see what libraries are downloaded and the behavior of WebSocket upgrade
  2. Sign-in and see how WebSocket exchanges information
  3. Add a Chat Channel to see group-level communication among several users
  4. Sign-out

  1. Open a Google Chrome internet browser window
  2. Specify this URL:

    http://chat.swim.it/#/chat/public



    NOTE: This communicates with a SWIM service running within the AWS EC2 public cloud infrastructure.

  3. Open Chrome Developer Tools (“DevTools”) in a new window one of these ways:

    • Click the “hamburger” icon at the upper right, then select More Tools, Developer Tools
    • Press option + command + I on Macs or Ctrl + Shift + I on Windows machines
    • Right-click anywhere on the page and select Inspect Element

  4. Select a window arrangement style for the app and the debugger:



  5. Click Network on the DevTools pane.
  6. Click the filter icon. the traffic shown by the Dev Tools, click WebSockets (all the way on the bottom).

  7. Mouse over the red button at the upper-left of the Debugger pane to make sure it’s recording.

  8. Click Sign In at the lower left.
  9. Select your Google account in the pop-up window that appears.

    We’re assuming that you have a Google account.

  10. Click “messenger.swim.services” in the DevTools window to show the “101 Switching Protocols” HTTP headers.
  11. Click “iframerpc2?” in the DevTools window Preview tab for the OAuth token JSON:

    {"token_type":"Bearer","access_token":"...
    
  12. Click the filter icon at the top of the DevTools window.
  13. Click “WS” to see only WebSocket transmissions.

  14. Click Allow for the app’s client to appear.



    WebSocket open

  15. Switch to the Developer Tool screen. On a Mac, press command + ` (back-tick).

    Waterfall timeline

  16. Click the “Network” tab to see the “waterfall timeline” of network activity.



    NOTE: The length of each line at the right visually illustrates how much time it took to download that file.

    In the case of the WebSocket Type of communication, its Time is “Pending” and the blue line continues far out in time because WebSockets are continuously open connection to “messenger swim services”.

    The definition of the WebSocket protocol by the Internet Engineering Task Force (IETF) as https://tools.ietf.org/html/rfc6455: “The goal of this technology is to provide a mechanism for browser-based applications that need two-way communication with servers that does not rely on opening multiple HTTP connections (e.g., using XMLHttpRequest or <iframe>s and long polling).”

    Push real-time

    When communication lanes are continuosly open, the server can push information to the client rather than waiting for clients to initiate communication.

    This communication is called “asynchronous” because the client does not wait for a request to be returned before sending another request (called “synchronous” behavior).

    Not waiting means server and client are communicating as “peers” (like sibilings). This is why such communication is called “peer-to-peer messaging”.

    This bi-directional initiation of communications of low-latency is crucial for real-time flow of information needed for IoT (Internet of Things).

    Low latency

    In the waterfall timeline, notice the “135 ms” (millseconds) latency time to obtain the “chat.swim.it” document. That’s about a tenth of a second.

    Theis latency is about as good as it gets. 133 milliseconds is the time it takes for light to travel around the earth, in a vacuum.

    One reason for this low latency is that the WebSocket protocol is more compact in its communication. Each communication sent consists of a header and a body. The WebSocket protocol uses a smaller number of bytes than the protocol used by most websites in 2016.

    See https://en.wikipedia.org/wiki/WebSocket

    As can be expected, the larger the file, the more time it takes to download. Here is the general trend, which can vary depending on internet weather between client and server at each paticular point in time:



    The individual files downloaded are discussed in a forthcoming section.

    Status 304 Not Modified

    Incidentally, in the waterfall timeline, the “304” under the “Status” column means, according to those who make browsers and blog, means “Not modified”, or the server’s way of saying that the client can continue to use same cached version of the resource requested again.

    Scalability from statefulness

    HTTP was designed to establish a connection each time it wants to send a message to the server. This enables what is called a “stateless” design that allows a particular client to go to any specific server rather than being “pinned” to a particular server.

    By contrast, a constant connection is called “stateful” because the state or status of communication is maintained. Websockets maintain a constantly open connection, so it has a “stateful” design.

    The advantage of a stateful design for communication is that it doesn’t have the same overhead as stateful designs.

    In this comparative bar chart of the total amount of time spent communicating:

    As the total number of messages between the same client and server increases (such as with many IoT devices), the overhead in use of HTTP REST adds up a lot versus WebSocket communication time with less overhead.

    Additional scalability is provided by execution of Swim services being distributed across several clusters of several servers each.

    Multiplexing

    One of the limiations with HTTP v1 protocol is that there is a limitation on how many connections a server can support.

    The WebSocket procotol makes use of multiplexing techniques that uses a single connection to retrieve multiple files simultaneously.

    Chat client libraries

    If you are curious about how the sample client works:

  17. Alt-click on the demo chat client webpage to View Page Source.

    The source downloaded is (rightly) minified of white space and line breaks for smaller and thus quicker usage, using an on-line tool such as Packer.

    Tools to un-pack include:

    • The Mr. Coles webpage un-minifies CSS (also as npm install cssunminifier)

    • jsbeautifier.org un-minifies JavaScript. PROTIP: Minification may change internal variable names to a single letter and remove code comments. Developers use it with the specific formatting options they individually prefer:



    swim chat chrome menu 20160710-217x482-c64.jpg Minification in external libraries makes it difficult to add break points in the Developer Tools.

    Libraries unique (custom) to the app:

    Angular 1 download

    JavaScript in Angular v1 (from http://angularjs.org) generate and display HTML from this CSS tag:

    <div ui-view="main" class="main-view">
    

    The libraries specified for download:

    The SWIM team defined a library of Angular directives

    https://github.com/swimit/swim-angular-js

    The directives swimMap, swimList, etc. are implemented in https://github.com/swimit/swimjs/blob/master/examples/chat-presence/

Sign-in using Google’s Platform

TODO: Examine the text of traffic between client and server.

We saw in the sample waterfall timeline, the “platform.js” is downloaded from Google’s servers to provide logic to Sign-in by having the site visitor click through Google’s dialog to obtain the name and email address instead of requesting the visitor to type it in.

  1. Click the “Source” tab and click the arrows at the left to expand the code:



Add Channel

  1. Click the “+” at the upper-left next to “EDIT” for this pop-up window:



  2. Type in a new chat channel name and click “Create Channel”.

  3. Click on a topic channel at the left, such as “Public”.

  4. Type a message such as “hello”.

    Because this app is intended for use as a demo for developers, it has a UI feature that is usually not in production apps.

    NEXT: We’ll be examining each of the client code fragments exposed by the sample app as we build our own client app running locally.

Coding the web client demo



  1. Click on each of the “{}” to expose client code for the major functions performed by almost all clients:

    We next examine each below:

Authenticating users

gapi.auth2.currentUser.listen(function (googleUser) {
  if (googleUser.isSignedIn()) {
    var idToken = googleUser.getAuthResponse().id_token;
    swim.authorize('', {googleIdToken: idToken});
  }
});
   

“swim.authorize” stores the {googleIdToken: idToken}.

Notice the “gapi” is for Google API, which returns the “googleUser” object from the JavaScript closure function.

Single-sign-on (SSO) such as GitHub, Facebook, Twitter, etc. are coming soon.

Synchronizing channels

Client:
 
var channels = swim.downlink()
  .node('')
  .lane('group/chats')
  .primaryKey(function (channel) { return channel.chatUri; })
  .onEvent(function (message) {
    // redraw UI with elements of channels.state array
  })
  .sortBy('name') // sort alphabetically by channel name
  .keepAlive(true) // reconnect after network failure
  .syncMap(); // keep state synchronized
 
Server:
 
var groupChats = new service.MapLane().register('group/chats'); // map from chat URIs to channel info
var chatInfo = new service.JoinLane().register('chat/info'); // aggregate chat/info streams
chatInfo.onJoinEvent = function (message, downlink) {
  // called when channel info updates
  var groupChat = groupChats.get(downlink.nodeUri) || {};
  recon.set(groupChat, 'userCount', message.body.userCount); // update present user count
  groupChats.set(downlink.nodeUri, groupChat);
};
chatInfo.onJoinLinked = function (response, downlink) {
  // called when channel added to group
};
chatInfo.onJoinClose = function (downlink) {
  // called when channel removed from group
  groupChats.delete(downlink.nodeUri);
};
   

From https://github.com/swimit/swimjs: A downlink is a subscription to the events published by a lane. Whenever the list changes on the server, the downlink updates the client. In Swim terminology, a node is the URI of a particular Swim service instance.

Streaming messages

Client:
 
var chat = swim.downlink()
  .node('ws://messenger.swim.services/chat/public')
  .lane('chat/room')
  .onEvent(function (message) {
    // redraw UI with elements of chat.state array
  })
  .keepAlive(true) // reconnect after network failure
  .syncList(); // keep state synchronized
 
Server:
 
var chatRoom = new service.ListLane().register('chat/room');
   

The swim.downlink() coding is called “down” because the list of channels is obtained from the server by the code. Downlinks are also called “outbound” from the server.

Communication is kept alive also by the .keepAlive(true) coding to reconnect after network failure and .syncList() coding to keep state (status) synchronized.

Tracking user presence

Client:
 
var users = swim.downlink()
  .node('')
  .lane('chat/users')
  .primaryKey(function (user) { return user.email; })
  .onEvent(function (message) {
    // redraw UI with elements of users.state array
  })
  .keepAlive(true) // reconnect after network failure
  .syncMap(); // keep state synchronized
 
Server:
 
var chatUsers = new service.MapLane().register('chat/users');
var chatRoom = new service.ListLane().register('chat/room');
chatRoom.onEnter = function (user) {
  chatUsers.set(user.email, {email: user.email, name: user.name});
};
chatRoom.onLeave = function (user) {
  chatUsers.delete(user.email);
};
   

The new keyword in coding new service.ListLane().register('chat/room'); registers a new chat/room to the list of lanes within the chatRoom object maintained by the server.

The new keyword in coding new service.MapLane().register('chat/users'); registers a new user to the map of lane users within the chatUsers object maintained by the server.

The email of the user (obtained from Google) is the key to information about each user on the server.

Posting a chat message

Client:
 
var message = {
  body: 'Hello, world!'
}
swim.command('', 'chat/room', message);
 
Server:
 
var chatRoom = new service.ListLane().register('chat/room');
   

The “Hello, world!” text in the sample coding is replaced by whatever is typed in the Message field.

Sign-out

  1. To sign-out, click the icon on the lower-left with an arrow over a door.

    This should cause the connection to close.

    QUESTION: Automatic sign-out should occur upon time-out as well? How long would the server keep a connection open without hearing from a client?


Local swimjs sample

To understand how your own client might work with the SWIM server, let’s start by taking a “deep dive” tracing the operation of a sample client program provided by SWIM developers. The sample chat program has functionality common to most other programs.

We install and run first the local client, then the server.

Local swimjs sample client

  1. In a command-line Terminal, create a folder path into which the sample software will be loaded, such as:

    ~/gits/swim

  2. Install:

    git clone https://github.com/swimit/swimjs.git
    cd swimjs
    tree

    The folder contains this tree:

    |-- API.md
    |-- README.md
    |-- examples
    |   |-- chat
    |   |   |-- chat.html
    |   |   |-- chat.js
    |   |   `-- swim.recon
    |   |-- chat-presence
    |   |   |-- chat.html
    |   |   |-- chat.js
    |   |   `-- swim.recon
    |   `-- todo
    |       |-- swim.recon
    |       |-- todo.html
    |       `-- todo.js
    `-- images
     |-- chat-presence.png
     `-- todo.png
    5 directories, 13 files
    

    You can click on the html and swim.recon files listed above because links have been added so you can click on them to see them formatted page on GitHub.com.

    But we can look at the source in the debugger as well, described next.

    An explanation of the swim.recon files are explained later as well.

    We want to next use the Chrome browser for its Developer Tools.

  3. At the swimjs folder within a Terminal, open one of the sample html file in the default internet browser window:

    cd ~/gits/swim/swimjs/examples/todo
    open ./todo.html

  4. Construct the URL path based on:

    file:///Users/%username%/gits/swim/swimjs/examples/todo/todo.html
    

    The %username% should be substituted with your user name to the operating system.

  5. Copy the URL path into your Clipboard from the path that appears in the browser address field.

  6. To see multiple agents seeing changes in the todo app, open a Chrome internet browser. Install it if you haven’t already.

  7. Paste that path from Clipboard.

  8. Open Chrome Developer Tools (“DevTools”) in a new window one of these ways:

    • Click the “hamburger” icon at the upper right, then select More Tools, Developer Tools
    • Press option + command + I on Macs or Ctrl + Shift + I on Windows machines
    • Right-click anywhere on the page and select Inspect Element

  9. Press command+P and select “todo.html” to load the file.

    If you get this message in the Console pane at the bottom of the Developer Tools window:

    WebSocket connection to 'ws://localhost:5619/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
    

    This is because we haven’t yet setup a local SWIM server (at port 5619).

    QUESTION: How about having the sample chat client point to a server in the cloud?

    Before we build the local server below, let’s look at libraries loaded client side.

  10. Type in something in the To-Do box and press Add.

  11. Press command+tab to switch to the other browser to see it appear.

Build Swim server locally

NEXT: To get a even better understanding of the swim system, let’s construct it on a local machine.

  1. A pre-requisite is to install Node.js and NPM, the Node.js Package Manager.

  2. Install the Swim client using NPM, as described in the README.md at https://github.com/swimit/swim-client-js:

    npm install –save swim-client-js

    The response:

    > websocket@1.0.23 install /usr/local/bin/node_modules/websocket
    > (node-gyp rebuild 2> builderror.log) || (exit 0)
     
      CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
      SOLINK_MODULE(target) Release/bufferutil.node
      CXX(target) Release/obj.target/validation/src/validation.o
      SOLINK_MODULE(target) Release/validation.node
    npm WARN saveError ENOENT: no such file or directory, open '/usr/local/bin/package.json'
    /usr/local/bin
    └─┬ swim-client-js@0.4.6 
      ├── recon-js@0.3.9
      ├── swim-proto-js@0.4.2
      └─┬ websocket@1.0.23
     ├─┬ debug@2.2.0 
     │ └── ms@0.7.1 
     ├── nan@2.3.5 
     ├─┬ typedarray-to-buffer@3.1.2 
     │ └── is-typedarray@1.0.0 
     └── yaeti@0.0.4 
     
    npm WARN enoent ENOENT: no such file or directory, open '/usr/local/bin/package.json'
    npm WARN bin No description
    npm WARN bin No repository field.
    npm WARN bin No README data
    npm WARN bin No license field. 
    

    There are three ├── recon-js@0.3.9 ├── swim-proto-js@0.4.2 └─┬ websocket@1.0.23

  3. To see the contents of WebSocket library installed:

    tree /usr/local/bin/node_modules/websocket

    |-- CHANGELOG.md
    |-- LICENSE
    |-- Makefile
    |-- README.md
    |-- binding.gyp
    |-- build
    |   |-- Makefile
    |   |-- Release
    |   |   |-- bufferutil.node
    |   |   |-- obj.target
    |   |   |   |-- bufferutil
    |   |   |   |   `-- src
    |   |   |   |       `-- bufferutil.o
    |   |   |   `-- validation
    |   |   |       `-- src
    |   |   |           `-- validation.o
    |   |   `-- validation.node
    |   |-- binding.Makefile
    |   |-- bufferutil.target.mk
    |   |-- config.gypi
    |   |-- gyp-mac-tool
    |   `-- validation.target.mk
    |-- builderror.log
    |-- docs
    |   |-- W3CWebSocket.md
    |   |-- WebSocketClient.md
    |   |-- WebSocketConnection.md
    |   |-- WebSocketFrame.md
    |   |-- WebSocketRequest.md
    |   |-- WebSocketServer.md
    |   `-- index.md
    |-- gulpfile.js
    |-- index.js
    |-- lib
    |   |-- BufferUtil.fallback.js
    |   |-- BufferUtil.js
    |   |-- Deprecation.js
    |   |-- Validation.fallback.js
    |   |-- Validation.js
    |   |-- W3CWebSocket.js
    |   |-- WebSocketClient.js
    |   |-- WebSocketConnection.js
    |   |-- WebSocketFrame.js
    |   |-- WebSocketRequest.js
    |   |-- WebSocketRouter.js
    |   |-- WebSocketRouterRequest.js
    |   |-- WebSocketServer.js
    |   |-- browser.js
    |   |-- utils.js
    |   |-- version.js
    |   `-- websocket.js
    |-- package.json
    |-- src
    |   |-- bufferutil.cc
    |   `-- validation.cc
    `-- vendor
     `-- FastBufferList.js
    11 directories, 46 files
    

    You can click on .md (Markdown text) files for formatted GitHub pages because links have been added to its origin at
    https://github.com/theturtle32/WebSocket-Node

  4. On a Mac OSX (MacOS), a pre-requisite is to install Homebrew explained by this tutorial.

    Typically, Homebrew users issue a command on its own such as brew install swimjs. Homebrew would look into its GitHub.com repo for a Ruby-language (.rb) file which specifies the “formula” on how to download and install “swimjs”. This is because the SWIM organization has not populated Homebrew’s GitHub repo with “swimjs.rb”.

    If it had, “swimjs” would also be found in http://brewformulas.org/ and http://braumeister.org/

    Nevertheless, Homebrew provides a mechanism for custom taps which enables the .rb formula file to be housed in a custom GitHub.com repository rather than in the Homebrew GitHub repository.

    An example of this is
    https://github.com/Homebrew/homebrew-games
    which contains several formulae.

    The SWIM organization is using that custom tap mechanism, as described in https://github.com/swimit/swimjs.

  5. Run the command (from any pwd) to position the GitHub repo holding the formula:

    brew tap swimit/swim

    PROTIP: The brew tap command above goes to the user or organization called “swimit” on GitHub.com. The name to the right of the / slash character (“swim”) is the suffix to the Git repository name combining “homebrew-“ plus “swim” from the command, yielding the URL:

    https://github.com/swimit/homebrew-swim.

  6. Click on the link above to see in the GitHub webpage that there is a single brew formula file, swimjs.rb repeated below:

    class Swimjs < Formula
      desc "Swim JavaScript Runtime"
      homepage "http://www.swim.it"
      url "https://raw.githubusercontent.com/swimit/swim/master/repo/swimjs-0.1.0-alpha3.tar.gz"
      version "0.1.0-alpha3"
      sha256 "d77880795f3ab904add10de351cefe6b45fc225a5754ef29c6ce75b7892105e0"
     
      depends_on :java => "1.8+"
     
      def install
        rm_f Dir["bin/*.bat"]
        libexec.install "bin", "lib"
        bin.install_symlink Dir["#{libexec}/bin/*"]
      end
    end
    }
    

    Note about the specification above:

    • The sha256 value was pre-calculated from where the file is stored before upload. The “hash” is based on every byte in the file.
      The same calculation is repeated on the file after download. If the output is the same, no transmission errors occurred.

    • Java 1.8+ is a dependency because when the tar.gz file is expanded, all files in the lib folder are .jar (java archive) files.

    • The url to file swimjs-0.1.0-alpha3.tar.gz in the formula is among a list of files shown on a formatted web page at
      https://github.com/swimit/swim/tree/master/repo

  7. Click on the URL above to see the list of files available.

  8. Press command+tab to select the Terminal shell window.

  9. Obtain the “swimjs” formula from within the custom “swimit” tap repo:

    brew install swimjs

    The response contains the location of files installed:

    ==> Installing swimjs from swimit/swim
    ==> Downloading https://raw.githubusercontent.com/swimit/swim/master/repo/swimjs-0.1.0-alpha3.tar.gz
    Already downloaded: /Users/mac/Library/Caches/Homebrew/swimjs-0.1.0-alpha3.tar.gz
    🍺  /usr/local/Cellar/swimjs/0.1.0-alpha3: 38 files, 17M, built in 0 seconds
    
  10. View the “swimjs” formula among others in “/usr/local/Cellar/”:

    brew list

    .jar files

  11. Construct the path by specifying the version “0.1.0-alpha3” as a folder, then get a tree listing of the folder:

    tree /usr/local/Cellar/swimjs/0.1.0-alpha3

    The response (if you have tree installed):

    |-- INSTALL_RECEIPT.json
    |-- bin
    |   `-- swimjs -> ../libexec/bin/swimjs
    `-- libexec
     |-- bin
     |   `-- swimjs
     `-- lib
         |-- com.fasterxml.jackson.core.jackson-core-2.1.3.jar
         |-- com.google.api-client.google-api-client-1.19.1.jar
         |-- com.google.code.findbugs.jsr305-1.3.9.jar
         |-- com.google.guava.guava-jdk5-13.0.jar
         |-- com.google.http-client.google-http-client-1.19.0.jar
         |-- com.google.http-client.google-http-client-jackson2-1.19.0.jar
         |-- com.google.oauth-client.google-oauth-client-1.19.0.jar
         |-- com.h2database.h2-mvstore-1.4.191.jar
         |-- commons-codec.commons-codec-1.3.jar
         |-- commons-logging.commons-logging-1.1.1.jar
         |-- it.reify.basis-core_2.11-0.2.1.jar
         |-- it.reify.basis-data_2.11-0.2.1.jar
         |-- it.reify.basis-net_2.11-0.2.1.jar
         |-- it.reify.basis-util_2.11-0.2.1.jar
         |-- it.swim.dive-http-scala_2.11-0.1.0-SNAPSHOT.jar
         |-- it.swim.dive-httpsocket-scala_2.11-0.1.0-SNAPSHOT.jar
         |-- it.swim.dive-io-scala_2.11-0.1.0-SNAPSHOT.jar
         |-- it.swim.dive-task-scala_2.11-0.1.0-SNAPSHOT.jar
         |-- it.swim.dive-websocket-scala_2.11-0.1.0-SNAPSHOT.jar
         |-- it.swim.recon-scala_2.11-0.2.0.jar
         |-- it.swim.swim-auth-google-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swim-core-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swim-meta-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swim-network-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swim-proto-scala_2.11-0.3.1.jar
         |-- it.swim.swim-socket-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swim-store-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swim-util-scala_2.11-0.3.2-SNAPSHOT.jar
         |-- it.swim.swimjs-0.1.0-SNAPSHOT.jar
         |-- joda-time.joda-time-2.7.jar
         |-- org.apache.httpcomponents.httpclient-4.0.1.jar
         |-- org.apache.httpcomponents.httpcore-4.0.1.jar
         |-- org.joda.joda-convert-1.7.jar
         |-- org.scala-lang.scala-library-2.11.7.jar
         `-- org.scala-lang.scala-reflect-2.11.7.jar
    4 directories, 38 files
    

This set of .jar files include the most popular technologies in 2016 based on an analysis of GitHub public repositories:

  • Guava Java utility library from https://github.com/google/guava
  • Apache commons-logging for Java from https://commons.apache.org/proper/commons-logging/

This set of .jar files include popular Java libraries:

  • Joda time from http://www.joda.org/joda-time/ a quality replacement for the Java date and time classes.
  • Jackson XML processor from http://wiki.fasterxml.com/JacksonHome

  • Scala programming language
  • Reify.it - A foundation library for Scala focussed on efficiency and clean design

Among the dependencies is an embedded open-source h2 SQL encrypted database first released 2005 (also written in purely Java) that creates in-memory tables as well as disk-based tables.

  • Website http://www.h2database.com, highlights its small footprint compared with other SQL databases.
  • Wikipedia says the name “h2” stands for Hypersonic 2, in reference to work by https://en.wikipedia.org/wiki/HSQLDB

  • As for caching, since that is built into SWIM, use of Redis is not applicable.

QUESTION: Why is that?


Record Notation (recon)

In the course of construction, SWIM developers created a new data format called Record Notation (RECON).

PROTIP: RECON combines the minimalism of JSON (JavaScript Object Notation) with the expressiveness of XML in a human-friendly syntax to provide a “simple grammar and uniform tree model for attributed text markup.”

The use of RECON enables the specification of a text configuration file instead of a lot of code.

An example is associated with the chat.html Swimjs Sample Client installed above:

@server {
  port: 5619
  store: "chat.store"
 
  @route {
    prefix: "/chat/"
    service: "chat"
  }
}
 
@service {
  name: "chat"
  main: "chat.js"
}
   

@event, @server, @service, are datatypes called attributes.

@ack, @auth, @deauth, @event, @link, @unlink, @sync, @command, etc. are datatypes described for humans in
https://github.com/swimit/swim-proto-scala

#### Wide applicability #

This approach has general applicability for other projects. So SWIM has structured its RECON coding to be available in several programming languages:

  • https://github.com/swimit/recon-js for the JavaScript language
  • https://github.com/swimit/recon-scala for the Scala language
  • https://github.com/swimit/recon-java for the Java language
  • https://github.com/swimit/recon-swift for the Swift language used to build iOS running on Apple iPhones and iPad devices

The recon-js library is installed using npm with swim-client-js.

### Swim-protop-js library #

A library of functions to process RECON has been written for each language:

  • https://github.com/swimit/swim-proto-js

  • https://github.com/swimit/swim-proto-scala

  • A proto library for Java is coming

RECON text formatting helpers

To enable the Sublime Text editor to better highlight RECON-format text, SWIM created a file at
https://github.com/swimit/recon-sublime-syntax

  1. Open the Sublime Text editor.
  2. On a Mac, click the “Sublime Text” next to the Apple icon and select Preferences > Browse packages… to open folder:

    ~/Library/Application Support/Sublime Text 3/Packages
    
  3. Open an internet browser instance to:

    https://github.com/swimit/recon-sublime-syntax

  4. Click to download the file.
  5. Unzip the file.
  6. Open the folder.
  7. Drag the Recon.sublime-syntax file to the Packages folder.
  8. Save all files and restart Sublime Text.
  9. View the RECON file again to see the syntax highlighting in different colors.

### Run swimjs #

  1. Set the pwd (present working directory) in a Terminal shell window to the client swim.recon file sits:

    cd ~/gits/swim/swimjs/examples/todo

  2. Run in a Terminal shell window to /usr/local/Cellar/swimjs/0.1.0-alpha3/libexec/bin/swimjs containing 348 lines:

    swimjs

    The expected response is:

    Listening on port 5619...
    

    This occurs if the swim.recon file specified port 5619.

    However, if you get this response instead:

    Exception in thread "main" java.net.BindException: Address already in use
    

    Look through other Terminal windows to find one using prot 5619.

    Press control + C to close.

    Aother error:

    Loading config from /usr/local/bin/swim.recon
    Exception in thread "main" java.nio.file.NoSuchFileException: /usr/local/bin/swim.recon
    at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
     at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
     at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
     at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
     at java.nio.file.Files.newByteChannel(Files.java:361)
     at java.nio.file.Files.newByteChannel(Files.java:407)
     at java.nio.file.Files.readAllBytes(Files.java:3152)
     at swim.js.JavaScriptApp$.main(JavaScriptApp.scala:43)
     at swim.js.JavaScriptApp.main(JavaScriptApp.scala)
    

    If you see this, verify whether you are positioned at the swim.recon file.


TODO: Chat Presence Example

  • /Users/mac/gits/swim/swimjs/examples/chat-presence

iOS App

https://github.com/swimit/swim-todo-ios

The app makes use of Apple’s Swift programming language

https://github.com/swimit/swim-swift

Built by San Francisco based freelance iOS developer Ewan Mellor ( ewanmellor on GitHub)

Server run-time

https://github.com/swimit/swimjs

https://github.com/swimit/swimjs/blob/master/API.md contains the details

Create To Do List client

To-Do application

https://github.com/swimit/swim-todo-services

Java

https://github.com/swimit/swim-util-java

  • https://github.com/swimit/recon-java

Scala

Developer @c9r, Chris Sachs, chris@swim.it https://github.com/c9r https://www.linkedin.com/in/cdsachs has built a Scala system before

Companies

DownlinkBuilder: an object used to constructor outbound links.

URL ???

Services

Messaging

Fine grain control over privacy data

Intra-service and Inter-service introspection

http://enterprise.webaware.com/#/system-stats

https://github.com/swimit/swim-examples/ swim-service-js

### Angular module library #

Notice in the sample chat.html &LT;script code this line:

   var app = angular.module('chat', []);
   

The app object in this code is created using the “angular.module” constructor in the library loaded by this line:

   <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
   

You may click on the file name above to see it on a new browser window. But it is minified. So look at its un-minified version here.

### Angular control of UI #

Functions in the Angular library act on “ng-“ tags in html, such as:

   <html ng-app="chat">
      ...
      <body ng-controller="ChatRoom" class="container">
      ...
         <div ng-repeat="message in messages.state" class="media">
         ...
         ≪form ng-submit="post()" class="input-group">
            <input type="text" ng-model="newMessage" placeholder="Message" class="form-control"/>
   

Handling of these tags is customized by the swim-angular-ui.js library developed by the SWIM team. Examples of its use are in todo and guages.

Custom Angular directives swimMap, swimList, etc. are implemented in sample app
https://github.com/swimit/swimjs/blob/master/examples/chat-presence/

But users of the library only need to code client HTML such as this sample code.html:

      app.controller('ChatRoom', function ($scope) {
        $scope.messages = swim.downlink()
          .node('ws://localhost:5619/chat/public')
          .lane('chat/room')
          .onEvent(function (message) {
            $scope.$apply(); // Update the view.
          })
          .syncList();
        $scope.post = function () {
          $scope.messages.command({text: $scope.newMessage});
          $scope.newMessage = '';
        };
      });
   

### Webservice end-point #

The ws:// in .node('ws://.../chat/public') coding uses the WebSocket protocol instead of HTTP:// protocol currently common on websites.

NOTE: As this is a demo, it is used instead of wss:// – the secure form of communication which makes use of encryption using public and private keys generated by a Certificate Authority (CA) trusted by the client.

### lane chat/room #

The .lane('chat/room') coding specifies the “lane” running in the server named “chat/room”. Each “lane” is also called “event source”.

Several clients can communicate with each named lane.

## Local Swim server #

QUESTION: How?

Benchmarking

Performance and capacity benchmarking is being done with a Webaware.com site
http://enterprise.webaware.com/#/system-stats

http://autobahn.ws/testsuite/usage.html#usage