codeCauldron

Feeds

RSS Site
RSS News
Print
Session Table Demo (Smart Proxies)

Summary

This example shows how Newton can be used to wire up Jini based smart proxies.

Smart proxies are written by service providers and transparently downloaded by clients when they start to use the service. They allow service providers to take responsibility for both sides of the remote protocol their service implements, and to present a simplified facade to their clients.

The basic model is shown below.

Note that in this context the emphasis of the term 'remote protocol' isn't so much on the transport level protocol (although it certainly includes this), as on the low level code dealing with error and timeout handling, caching, batching and other remoting details that are best hidden from the client. Without smart proxies each client would have to either manually install a custom client library for each service it used, or handle all of the protocol details itself. Either way the client would be hard wired to a particular set of protocol details and so much less able to live in a dynamic services world full of alternate service implementations and regular service upgrades.

These issues were well understood by Jini's creators, and smart proxies have always been a central Jini theme.

Newton tries to simplify the process of writing and deploying smart proxies so as to make them accessible to developers with no understanding of Jini. A little RMI knowledge is required, but not very much.

Overview

In this demo the Server composite constains two local components:

  • a SessionManager component that provides authenticated users with SessionToken credential objects.
  • a PerUseTable component that allows holders of an authenticated SessionToken to manipulate their private name-value table

It also provides a smart proxy component called SessionTable. This has a single interface that combines both login and table manipulation, simplifying things for the client by hiding the fact that there are two remote interfaces and the details of SessionToken handling.

A CLI based client is used to communicate with this service. It binds to a SessionTable reference, unaware that it is implemented as a smart proxy.

The system we are going to create is shown below.

The CLI descriptor and code is much as in the other examples so we'll only look at the Server composite in detail.

The Server composite creates its SessionManager and PerUserTable components in the usual way. The SessionTable smart proxy component is created in the same way, but uses a special jini-proxy implementation type. It provides a SessionTable service at Jini scope in the usual way. The full server template XML is shown below.

<?xml version="1.0"?>
<composite name="serverTemplate">
	<description>session table service template</description>

	<service name="sessionTable-export">
		<interface.java interface="org.cauldron.newton.test.bundles.sessiontable.proxyapi.SessionTable"/>
		<binding.jini/>
	</service>

	<component name="sessionManager">
		<description>session manager</description>
		<implementation.java.callback impl="org.cauldron.newton.test.bundles.sessiontable.server.SessionManagerImpl"/>
	</component>
	
	<component name="perUserTable">
		<description>session scoped table</description>
		<interface.java name="perUserTable" interface="org.cauldron.newton.test.bundles.sessiontable.serverapi.PerUserTable"/>
		<reference name="sessionManager"/>
		<implementation.java.callback impl="org.cauldron.newton.test.bundles.sessiontable.server.PerUserTableImpl"/>
	</component>
	
	<!-- remote proxy -->
	<component name="sessionTable">
		<description>session scoped table proxy</description>
		<reference name="sessionManager"/>
		<reference name="perUserTable"/>
		<implementation.jini.proxy impl="org.cauldron.newton.test.bundles.sessiontable.proxy.SessionTableProxy"/>
	</component>	
	
	<wire>
		<source.uri>sessionManager</source.uri>
		<target.uri>perUserTable/sessionManager</target.uri>
	</wire>

	<wire>
		<source.uri>perUserTable</source.uri>
		<target.uri>sessionTable/perUserTable</target.uri>
	</wire>
	
	<wire>
		<source.uri>sessionManager</source.uri>
		<target.uri>sessionTable/sessionManager</target.uri>
	</wire>
	
	<wire>
		<source.uri>sessionTable</source.uri>
		<target.uri>sessionTable-export</target.uri>
	</wire>
</composite>

Here the <implementation.jini.proxy ..> tag implies the same lifecycle as in the <implementation.java.callback ..> case, with the following important differences:

  • All of its references must be satisfied by components within its own composite. This is because once a proxy leaves the composite that created it it will no longer be able to receive updates if the composites's external connections change, whereas internal connections are static and thus unaffected by this problem.
  • All of its referenced interfaces are automatically remoted at JVM level, and the proxy is passed these as remote stubs rather than as local references. This is so that the proxy can still communicate with its dependencies after it has left the component that created it.
  • The proxy should not be referred to by any other component in the composite. This is because once it has left the originating JVM the local copy will not be in sync with deserialized remote copies of the service.

Note that if any of the proxies referenced interaces do not implement Remote then they will be transparently wrapped prior to being exported, and throw unchecked ConnectionException instances rather than RemoteException instances to indicate remoting errors.

As in all of the Jini demos an RMI-Codebase manifest attribute must be set so that the proxy can be deserialized. See the ant build.xml file for this demo for more details.

Running the example.

Prerequisites

In order to run the demo you will have to Download and Install Newton. In the case of the source distribution you will also have to Build Newton.

The source code for the demos is in the bundles/components/component-examples directory of the source distribution, and the demo directory of the binary distribution.

Newton requires a Java 1.5. JDK. The pre-release versions of 1.6 are not yet supported

The JAVA_HOME environment variable should be set to point at JVM you want Newton to use.

Try the Local Chainlink Demo and Jini Chainlink Demo before this one. These will introduce you to The Newton Component Model and the basics of Jini in Newton.

Booting two Newton containers

In order to run the demo it is first necessary to start two Newton containers. We need to make sure that both of the containers are using the same Jini group. This will ensure that they can see each other but not Newton containers using different groups. So you'll need to pick a group name. We'll use "paremus" here, but you should pick your own to prevent clashes. Newton picks up this group via an environment variable. To start Newton in your group use.

To do this change to the Newton bin directory and run

//for unix 
export NEWTON_FABRIC_NAME=paremus
$ ./newton.sh

//for windows
set NEWTON_FABRIC_NAME=paremus
> newton.bat 

It is important that you remember to use your own group name, not "paremus".

Start two containers now for use in this demo. If you are doing this on one machine then make sure you have two installs of Newton and aren't just starting the same Newton container twice.

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. In one of the Newton containers run

> installer install ./core/instances/reggie-instance.xml
> installer install ./core/instances/server-cds-instance.xml

This installs the Jini remote services registry, which Newton uses to detect and wire up services in different JVMs. It also starts the remote zone of CDS. All Newton containers share a common view of the content in CDS's remote zone.

Note that this remote infrastructure is itself implemented as a set of 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 ./core/instances/jinibrowser-instance.xml

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 session table demo are not present in the CDS, so they must be loaded. Note that this doesn't install anything, it just makes resources available for future installations.

To load the demo bundles run the following in one of your Newton instances.

> cds scan remote demo/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 Jini group.

Using SessionTable

First create the CLI part on container 1.

> installer install demo/xml/sessiontable/cli-instance.xml

If you now type help you'll see a new command group called sessiontable. This CLI composite has a reference to a SessionTable interface. At the moment there is nothing for it to connect to so lets start the Server composite in container 2.

> installer install demo/xml/sessiontable/server-instance.xml

If you opted to run the jinibrowser composite you'll be able to see the exported proxy there.

Newton detects the presence of the SessionTable export and wires it up to the CLI. This involves downloading the smart proxy into the CLI's JVM and deserializing it. The CLI composite doesn't have to worry about these details, it just references the interface.

We now have the system shown in the diagram above and can run some tests with it. First, in container 1, enter the sessiontable command group as follwos:

> enter sessiontable

You can leave the command group at any time by typing leave

The available commands are login to switch user get to get values in a user's table and put to put values in a user's table. The following session manipulates the private tables of two users.

sessiontable> login fred pass
logged in
sessiontable> put age 51
sessiontable> get age
age->51
sessiontable> put name fred
sessiontable> get name
name->fred
sessiontable> login bill pass
logged in
sessiontable> get age
age->null
sessiontable> get name
name->null
sessiontable> put age 34
sessiontable> put name bill
sessiontable> get age
age->34
sessiontable> get name
name->bill
sessiontable> login fred pass
logged in
sessiontable> get age
age->51
sessiontable> get name
name->fred
Powered by Atlassian Confluence