Remote Chainlink Demo
Summary
This demo extends the Chainlink Demo so that it runs across several JVMs, and uses this to illustrate Newton's remoting capabilities.
The aim is show how to bootstrap a distributed Newton fabric, and to illustrate how composites deployed in different containers can be dynamically wired up and rewired in response to changes.
Newton remoting makes use of RMI technology. Newton isolates end users from many RMI related concerns. The remaining considerations are highlighted for developers in the following example.
Overview
The structure of the example is almost identical to that for the single JVM Chainlink Demo, so rather than repeat that we'll focus here on the differences.
The bundles used in this demo are analogous to those used in the local demo. The differences are as follows:
1) The bundle names have the form chainlink-rmi-brace-bundle.jar rather than chainlink-brace-bundle.jar.
2) Descriptor names have the form chainlink-rmi-a.xml rather than chainlink-local-a.xml
3) The remote versions of the brace-link, bracket-link and api bundles contain an RMI-Codebase manifest header.
This identifies the code needed to remotely reconstitute the service proxies that are remotely exported by the example.
A publish.xml file is also generated. Publish files are read by Newton as their containing bundles are loaded into CDS. They identify nested content that needs to be added to CDS in its own right. In the current case we are using it to publish the RMI codebase jar to CDS, from where it can be accessed by service clients. Here's the publish.xml file:
<?xml version="1.0"?>
<publish>
<item name="chainlink-brace-dl.jar" path="chainlink-brace-dl.jar">
<attribute name="type" value="rmi.codebase"/>
</item>
</publish>
See RMI in Newton for more information.
4) In the remote version services and references are exposed by RMI rather than via the OSGi registry scope. Here's the Remote version of the brace-link template.
<?xml version="1.0"?>
<composite name="rmiBraceLinkTemplate">
<description>chainlink rmi demo brace link</description>
<reference name="nextLink" multiplicity="0..1">
<interface.java interface="org.cauldron.newton.test.bundles.chainlink.interfaces.Link"/>
<binding.rmi />
</reference>
<service name="brace-link-export">
<interface.java interface="org.cauldron.newton.test.bundles.chainlink.interfaces.Link"/>
<binding.rmi />
</service>
<component name="brace-link">
<description>A brace decorated chain link</description>
<property name="linkName" value="Unnamed" type="string"/>
<reference name="nextLink"/>
<implementation.java.callback impl="org.cauldron.newton.test.bundles.chainlink.brace.BraceLink"/>
</component>
<wire>
<source.uri>brace-link/nextLink</source.uri>
<target.uri>nextLink</target.uri>
</wire>
<wire>
<source.uri>brace-link-export</source.uri>
<target.uri>brace-link</target.uri>
</wire>
</composite>
Note the <binding.rmi ..> elements. The fabric name comes from the container.fabricName system property if this is set, and the user.name property if it is not. This value can be overridden by using a group attribute on the binding.rmi tag. Note that in order for a number of remote services to see each other they should all be using the same fabric name. The standard way to do this in newton is by setting container.fabricName. The scripts which start newton propagate the platform level environment variable NEWTON_FABRIC_NAME to the java system property container.fabricName. The property can also be set on containers as they are started by using the -fabricName flag
The remote chain CLI is interesting because has an RMI scoped reference to a Link, but provides an OSGi scoped ConsoleCommandHandler service. This is because we want to use the command in the console it is launched in! Here's the template XML
<?xml version="1.0"?>
<composite name="rmiChainlinkCli">
<description>chainlink rmi cli</description>
<!-- remote, rmi scoped import -->
<reference name="connection" multiplicity="0..1">
<interface.java interface="org.cauldron.newton.test.bundles.chainlink.interfaces.Link"/>
<binding.rmi/>
</reference>
<!-- local, OSGi scoped export -->
<service name="cli-export">
<interface.java interface="org.cauldron.newton.command.console.ConsoleCommandHandler"/>
<binding.osgi/>
</service>
<component name="cli">
<description>cli for the chainlink demo</description>
<property name="contextName" value="chainlink" type="string"/>
<reference name="connection"/>
<implementation.java.callback impl="org.cauldron.newton.test.bundles.chainlink.cli.Commands"/>
</component>
<wire>
<source.uri>cli/connection</source.uri>
<target.uri>connection</target.uri>
</wire>
<wire>
<source.uri>cli-export</source.uri>
<target.uri>cli</target.uri>
</wire>
</composite>
Running the example.
Prerequisites
Try the local version of the Chainlink Demo before this multi-JVM one, without it this demo may lack context.
Booting the Newton container
In order to run the demo it is first necessary to start two Newton containers. In order to see each other these need to be running as part of the same fabric. To start the two containers on a single machine open two terminals in the Newton bin directory and run
In terminal 1
$ bin/container -fabricName=myfabric -instance=1
In terminal 2
$ bin/container -fabricName=myfabric -instance=2
Note that this demo will also work when running across several machines (firewalls permitting)
The -fabricName flag sets the fabric name. We've used 'myfabric' but you should choose your own name to prevent clashes. Note that if the fabric name is not set it defaults to the current user name. This means that simple tests on a single machine will work without the fabricName being set. However it should always be set when more than one machine is involved
The -instance flag is used to separate the state belonging to the two conatiner instances. This is only necessary because we are running the two instances out of the same Newton install. If the instances were running on different machines there would be no need for this flag
After starting Newton wait for the "Boot complete" message, after which Newton makes a command line available.
Booting the distributed runtime
Newton's distributed infrastructure makes use of multicast, so it is essential that your network and computers are in a configuration that allows multicast traffic. If you are unsure of your setup, or having difficulty running this example the please see Troubleshooting Multicast.
Every instance of Newton starts up with the client side of the distributed infrastructure already installed. At present it is necessary to manually boot the server side infrastructure. To do this enter the following at one of the Newton command lines
> exec etc/scripts/single-jvm-dist-infra
This installs Newtons remote registry, distributed repository, and other distributed runtime components
This remote infrastructure is itself implemented as an SCA system built from Newton composites.
Optionally you can start the jinibrowser composite, a GUI tool for viewing the remote registry. You can use this to see the services that available to your group remotely.
>installer install etc/instances/jinibrowser.composite
The services may take a few seconds to come up - you'll get an error message at the next step if you are too quick.
Loading bundles into CDS
At this point the bundles used by the remote chainlink demo are not present in the CDS repostory, so they must be loaded. Note that this doesn't install anything, it just makes resources available for future composite installations.
To load the demo bundles run the following in one of your Newton instances.
> cds scan remote examples/chainlink/build/lib
This loads all of the bundles in demo/build/lib into the remote zone of CDS, extracting metadata and indexing the bundles as they are loaded. Resources in the remote zone can be seen by all Newton containers in the same Fabric
Creating the Chain
We now create a chain of brace-link composites that is distributed across two JVMs.
In The first Newton container we install the CLI and the first link in the chain as follows.
> installer install examples/chainlink/build/etc/chainlink-rmi-cli-a.composite > installer install examples/chainlink/build/etc/chainlink-rmi-a.composite
In this remote case the command group added by the CLI is called rmiChain-a, so to see the chain so far you can run
> rmiChain-a chain
chain: cli->{A-link} [end of chain]
So far this is all in one JVM. To demonstrate the distributed behaviour we create the rest of the chain in the second JVM
> installer install examples/chainlink/build/etc/chainlink-rmi-b1.composite > installer install examples/chainlink/build/etc/chainlink-rmi-c.composite
then, in the first JVM - i.e. the one you installed the CLI in rerun
> rmiChain-a chain
chain: cli->{A-link}->{B1-link}->{C-link} [end of chain]
to show the distributed chain structure.
Modifying the chain.
So far we've built up a chain of brace-links that spans two Newton containers. Now we'll make add a link in one container and remove one in the other, forcing Newton to rewire the chain.
In container 1 run
> installer install examples/chainlink/build/etc/chainlink-rmi-b2.composite
This adds a new 'b' composite to the container.
And in container 2 run
> installer uninstall examples/chainlink/build/etc/chainlink-rmi-b1.composite
This removes the 'b' composite in container 2. When this happens Newton notices that link a has unbound references and rewires it to the 'b' link in the other container. To see the result run the following in the container you added the CLI to.
> rmiChain-a chain
chain: cli->{A-link}->[B2-link]->{C-link} [end of chain]
Here brace-link B1 which was in container 2 has been replaced by bracket-link B2 in container 1.
Further exercises
Apart from the CLI the different parts of this demo could have been run in either container, or in any additional containers started with the same fabric name.
Try installing links and infrastructure composites in different containers and on different machines. For convenience you can install the CLI in as many containers as you like.
As with the local chainlink demo the bundles that implement these composites will be removed by the Newton's garbage collection mechanism as the composites that need them are removed.
Hard kills of Newton containers may take a little while to spot, although it will ultimately react to the change.


