Projektstudium SS98 - distributed computing


vorherige Seite Inhalt nächste Seite

10. Beispiel RMI: Whiteboard

Das Whiteboard ist ein einfaches Zeichenwerkzeug, daß es mehreren Benutzern gestattet eine gemeinsame Zeichenfläche zu benutzen. Der Benutzer beeinflußt das Whiteboard, indem er ein Zeichenwerkzeug auswählt (Rechteck zeichnen oder verschieben). Intern heiß das, die Liste der Elemente wird verändert. Wenn Veränderungen an der Liste gemacht werden, dann werden alle Listener-Objekte, die beteiligt sind, informiert. Listener-Objekte, wie die Darstellungsfläche, aktualisieren sich dann automatisch, um diese Veränderungen sichtbar zu machen.

Darstellung des Whiteboards
Der Whiteboard-Frame

Implementierte Klassen

Für das Whiteboard
  • WBLauncher -- Ein einfaches Applet, daß das Whiteboard startet, wenn auf das Applet geklickt wird.
  • WB -- Die Hauptklasse für das Whiteboard, sie enthält ein Frame, welches alle Komponenten beinhaltet.
  • Tool -- Ein Interface, daß für Zugriff auf die Zeichenwerkzeuge sorgt.
  • Element -- Ein Interface, daß die Elemente die gezeichnet werden können enthält
  • WBContainer -- Ein einfacher Container, der den Inhalt des Whiteboards anzeigt.
  • Rect -- Ein Zeichenwerkzeug, daß es erlaubt, Rechtecke verschiedener Größe und Farbe auf dem Whiteboard zu plazieren.
  • Select -- Ein Zeichenwerkzeug, daß es erlaubt, Elemente auf dem Whiteboard zu verschieben.
  • ObservableList -- Eine Klasse, die eine Liste aller Elemente des Whiteboards verwaltet, und bei Bedarf die Listener bei Veränderungen benachrichtigt.
  • UpdateListener -- Das Interface muß implementiert werden, wenn eine Klasse benachrichtigt werden soll, falls sich die ObservableList ändert.
  • UpdateEvent -- Ein Ereignis, daß benachrichtigt, wenn sich die ObservableList verändert.
  • LWContainer -- Ein generischer, einfacher Container, ähnlich der Panel Klasse.
  • LWImageButton -- Ein generischer Button.

Für das RMI System
  • RList -- Beinhaltet das Remote Interface für die Serverimplementation.
  • RListImpl -- Die Klasse der Serverimplementation, sie beinhaltet eine Liste der IDList-Klasse.
  • RMIList -- Die Klasse des Clients, sie ist eine Unterklasse der ObservableList.
  • RMIWBLauncher -- Eine modifizierte WBLauncher Klasse fur das RMI System.
  • RMIWB -- Eine modifizierte WB Klasse.

Weitere Klassen
IDList -- Die Klasse implementiert eine geordnete Liste ("Vektor") von Elementen und deren IDs ("Hashtable").
RList
Aufbau der RMI-basierten Listenstruktur

Implementationsdetails

Der Server ist in diesem Fall eine Liste (das entfernte Objekt), deren Methoden aufgerufen werden. Wird der Client gestartet macht er zuerst einen entfernten Methodenaufruf an die zentrale Liste, um eine Liste der angezeigten Objekte zu bekommen. Alle Veränderungen auf der Clientseite werden wieder als entfernte Methodenaufrufe an den Server geschickt.

Da es unpraktisch ist, daß der Server alle Clients abfragt, ob sich etwas geändert hat, fragt der Client beim Server auf Veränderungen nach. In diesem Fall fragt der Client alle 10 Sekunden beim Server nach, ob sich die IDList geändert hat oder nicht, und aktualisiert bei Bedarf seine eigene IDList.

Interface RList

Das Remote Interface RList der zentralen Liste hat folgende Methoden:

  • public Object addElement (Object element) throws RemoteException
    - Fügt ein Element in die zentrale Liste, bekommt die ID des Objekts zurück.
  • public Object replaceElement (Object oldOD, Object element) throws RemoteException
    - diese Methode entfernt ein altes Objekt mit gegebener ID und fügt ein neues Element in die Liste ein.
  • public IDList getUpdate (int updateCount) throws RemoteException
    - gibt nur eine aktuelle IDList zurück, wenn sich an der zentralen Liste etwas geändert hat.

Die Klasse RMIList

Die Clientseite, die ObservableList, sie übernimmt den entfernten Methodenaufruf für Updates der lokalen Liste.

	// RList rList;
  	// IDList list;

	public RMIList (String host) throws RemoteException, NotBoundException {
    		Registry remoteRegistry = LocateRegistry.getRegistry (host);
    		rList = (RList) remoteRegistry.lookup (RList.REGISTRY_NAME);
    		list = new IDList ();
    		update ();
   		...
Wenn die RMIList erzeugt wird, bekommt sie zuerst eine Referenz auf die zentrale Liste mit den aktuellen Daten.
 	protected synchronized void update () throws RemoteException {
    		IDList newList = rList.getUpdate (list.getUpdateCount ());
    		if (newList != null) {
      			list = newList;
      			fireUpdate ();
    		}
  	}
Die update()-Methode ruft die getUpdate()-Methode der zentralen Liste auf, ob sie modifiziert wurde. Wenn ja, dann wird die lokale Liste mit der aktuellen ersetzt.
 	public synchronized void addElement (Object element) {
    		try {
      			Object id = rList.addElement (element);
      			list.addElementWithID (id, element);
    		} catch (RemoteException ignored) {
    		}
  	}
Hier wird die entfernte Methode addElement() aufgerufen, um ein neues Element in der zentralen Liste aufzunehmen. Zurückgegeben wird die ID, welche dann in der lokalen Liste eingetragen wird.

Die Klasse RListImpl

Diese Klasse ist die Implementation des RList Interface. Es wird hauptsächlich eine zentrale IDList aller angelegten Elemente verwaltet.

 	// IDList list;

	public Object addElement (Object element) {
    		return list.addElement (element);
  	}
Hier wird einfach die Methode der IDList aufgerufen.
  	public IDList getUpdate (int updateCount) {
    		return (list.getUpdateCount () == updateCount) ? null :
        			(IDList) list.clone ();
  	}
Hier wird null zurückgegeben, wenn der Client bereits eine aktuelle Liste besitzt (d.h. Client und Server, beide denselben updateCount haben), sonst wird eine aktuelle Liste zurückgegeben.
	public static void main (String[] args) throws RemoteException {
    		RListImpl rList = new RListImpl ();
    		Registry localRegistry = LocateRegistry.createRegistry (Registry.REGISTRY_PORT);
    		localRegistry.rebind (REGISTRY_NAME, rList);
  	}
In der main() Methode wird die RListImpl erzeugt und in die lokale Registry aufgenommen

Starten des Beispiels

  1. Wechseln in das Basisverzeichnis <...>\Whiteboard. (Darauf achten, daß dieses Verzeichnis in der CLASSPATH-Variablen steht.)
  2. Übersetzen des Javacodes durch den Aufruf:

    javac   -d   "<...>\Whiteboard"   *.java   rmi\*.java
    (Das <...> durch den Pfad zum Verzeichnis ersetzen, z.B. c:\rmi)

  3. Nun müssen die Stellvertreterklassen erzeugt werden:

    rmic   -d "<...>\Whiteboard"   example.wb.rmi.RListImpl
    Dadurch werden die Dateien RListImpl_Stub.class und RListImpl_Skel.class im Unterverzeichnis, an der richtigen Stelle (...\example\wb\rmi) erstellt.

  4. Als nächstes kann der Server gestartet werden, denn er erzeugt seine eigene Registry (d.h. wir müssen die rmiregistry nicht explizit starten), und meldet die Objekte dort an:

    java   example.wb.rmi.RListImpl

  5. Zuletzt muß nur noch der Client (Applet) gestartet werden:

    appletviewer rmi.html

vorherige Seite Inhalt nach oben nächste Seite
© Copyright 1998 André Möller, Oliver Mentz & Magnus Wiencke