Client - SWIM Client

Swim developer logo developer.

Overview


The Server section described how to create Services, Lanes, DownLinks, and Planes in the Server. This section explains how data ingestion and data subscription to specific Lanes in Services can be implemented from outside the server. The most straight-forward way of implementing this is by using the SWIM-Client library. Data ingestion may also be implemented using raw web-socket messages which is explained in the next section.

The SWIM-Client is analogous to an HTTP Client, where data ingestion is analogous to an HTTP PUT/POST and data subscription is analogous to an HTTP GET. Alternatively, it may also be compared a Message Broker Client, where data ingestion is like publishing to a message queue and data subscription is like subscribing to a message queue. The SWIM-Client is currently available in Java and JavaScript. These are the steps involved in using the SWIM-Client for data ingestion or data subscription.

  1. Instantiate the SWIM-Client.
  2. Use the SWIM-Client instance to get a Downlink reference to the Lane and Service desired. Use the Downlink reference for data ingestion or subscription.
  3. Alternatively use the command API of the SWIM-Client instance to ingest data.

Consider a Swim application running on localhost:5620 with the following Plane and Service definition. The sections below describe how the SWIM-Client can be used to ingest data and subscribe to data from the lanes in a specific PlanetService instance.

Plane

import swim.api.*; class SolarSystem extends AbstractPlane { // e.g. /planet/saturn, /planet/earth @SwimRoute("/planet/:name") final ServiceType<?> planet = serviceClass(PlanetService.class); }
  • HTML
  • recon

Service and Lanes

import recon.*; import swim.api.*; class PlanetService extends AbstractService { @SwimLane("co2") ValueLane<Double> co2 = valueLane() .valueForm(Form.DOUBLE); @SwimLane("co2History") MapLane<Long, Double> history = mapLane() .keyForm(Form.LONG).valueForm(Form.DOUBLE); @SwimLane("addCo2") CommandLane<Double> addCo2 = commandLane().valueForm(Form.DOUBLE) .onCommand(newCo2 -> co2.set(newCo2)); }
  • HTML
  • recon

Client Instantiation


Instantiating the SWIM-Client is outlined below.

Java
final SwimClient swimClient = new SwimClient(); swimClient.start();
  • HTML
  • recon
JavaScript
var swim = require('swim-client-js'); var client = new swim.Client();
  • HTML
  • recon

Data Ingestion to Lanes


Downlinks

The Downlinks section describes Server Downlinks in great detail. Downlinks in the Java SWIM-Client are pretty similar, please refer to that section for more information. Here we outline just the details needed for data ingestion and subscription.

ValueLane

ValueDownlinks are used to send data to ValueLanes defined in a service. A ValueDownlink reference is obtained from the SWIM-Client and the open API on this link reference is called. Subsequently the set API in the Java client and the setValue API in the JavaScript client are invoked to inject data. This is outlined in the code below, here a value of 0.5 is ingested into the ValueLane named co2 of the "Earth" Service whose URI is /planet/earth.

Java
final ValueDownlink<Value> dl = swimClient.downlinkValue() .hostUri("ws://localhost:5620") .nodeUri("/planet/earth") .laneUri("co2") .open(); dl.didLink(() -> { System.out.println("Linked, will set."); dl.set(Value.of(0.5); });
  • HTML
  • recon
JavaScript
client.downlinkValue() .hostUri('ws://localhost:5620') .nodeUri('/planet/earth') .laneUri('co2') .open() .setValue(0.5);
  • HTML
  • recon

MapLane

MapDownlinks are used to send data to MapLanes defined in a service. A MapDownlink reference is obtained from the SWIM-Client and the open API on this link reference is called. Subsequently the put API in the Java client and the set API in the JavaScript client are invoked to inject data. This is outlined in the code below, here a value of 0.4 with a key of 1000 is ingested into the MapLane named co2History of the "Earth" Service whose URI is /planet/earth.

Java
final MapDownlink<Long, Value> dl = swimClient.downlinkMap() .hostUri("ws://localhost:5620") .nodeUri("/planet/earth") .laneUri("co2History") .open(); dl.didLink(() -> { System.out.println("Linked, will set."); dl.put(1000L, Value.of(0.4); });
  • HTML
  • recon
JavaScript
client.downlinkMap() .hostUri('ws://localhost:5620') .nodeUri('/planet/earth') .laneUri('co2History') .open() .set(1000, 0.4);
  • HTML
  • recon

Commands

The command API in the SWIM-Client is used to send data to CommandLanes defined in a service. This is outlined in the code below, here a value of 0.4 is sent to the CommandLane named addCo2 of the "Earth" Service whose URI is /planet/earth.

Java
// node: planet/earth, lane: addCo2 swimClient.command("wss://localhost:5620", "/planet/earth", "addCo2", Value.of(0.4));
  • HTML
  • recon
JavaScript
// node: planet/earth, lane: addCo2 swimClient.command('wss://localhost:5620', '/planet/earth', 'addCo2', 0.4);
  • HTML
  • recon

Subscription to Lane Data


Downlinks

ValueLane

ValueDownlinks are also used to subscribe to data in ValueLanes defined in a service. A ValueDownlink reference is obtained from the SWIM-Client and the open API on this link reference is called. Subsequently the didSet API in both the Java and the JavaScript client are invoked to subscribe to lane data. The didSet API is invoked any time the ValueLane is updated. This is outlined in the code below, here a subscription is made to the ValueLane named co2 of the "Earth" Service whose URI is /planet/earth.

Java
swimClient.downlinkValue() .hostUri("ws://localhost:5620") .nodeUri("/planet/earth") .laneUri("co2") .didSet((Value newCo2Value, Value oldCo2Value) -> { // invoked when the "co2" lane on the service //"/planet/earth" is set. }) .open();
  • HTML
  • recon
JavaScript
client.downlinkValue() .hostUri('ws://localhost:5620') .nodeUri('/planet/earth') .laneUri('co2') .didSet(function (newCo2Value, oldCo2Value, downlink) { // invoked when the "co2" lane on the service //"/planet/earth" is set. )} .open();
  • HTML
  • recon

MapLane

MapDownlinks are also used to subscribe to data in MapLanes defined in a service. A MapDownlink reference is obtained from the SWIM-Client and the open API on this link reference is called. Subsequently the didUpdate API in both the Java and the JavaScript client are invoked to subscribe to lane data. The didUpdate API is invoked any time the MapLane is updated. This is outlined in the code below, here a subscription is made to the MapLane named co2History of the "Earth" Service whose URI is /planet/earth.

Java
swimClient.downlinkMap() .hostUri("ws://localhost:5620") .nodeUri("/planet/earth") .laneUri("co2History") .keyForm(Form.LONG) .didUpdate((Long ts, Value newCo2Value, Value oldCo2Value) -> { // invoked when the "co2History" lane on the service // "/planet/earth" is updated. }) .open();
  • HTML
  • recon
JavaScript
client.downlinkMap() .hostUri('ws://localhost:5620') .nodeUri('/planet/earth') .laneUri('co2History') .didUpdate(function (key, newCo2Value, oldCo2Value, downlink) { // invoked when the "co2History" lane on the service // "/planet/earth" is updated. }) .open();
  • HTML
  • recon

Full Java Example


The Java code snippet outlined below creates a ValueDownlink<Double> that subscribes to a ValueLane, sets its value to 0.4, and closes the Downlink after confirming that the set took place.

// Instantiate a SwimClient final SwimClient sc = new SwimClient(); sc.start(); // Instantiation a downlink final ValueDownlink<Double> link = sc.downlinkValue().valueForm(Form.DOUBLE) .hostUri("wss://localhost:5620") .nodeUri("/planet/earth") .laneUri("co2") .open(); // Subscribe to the value lane using the didSet callback link.didSet((n,o) -> { if (n == 0.4) { // Teardown System.out.println("Set, will close."); link.close(); } }); // Set the value in the didLink callback. link.didLink(() -> { System.out.println("Linked, will set."); link.set(0.4); })
  • HTML
  • recon

Please refer to the basics subproject which has several Downlink examples in Client.java.