
Das Szenario ist einfach: Drucker kaufen, anschließen und warten. Nach einigen Sekunden erscheint auf dem Desktop ein neues Icon. Auf Mausklick öffnet sich ein Fenster und zeigt den Status des Druckers an: bereit. Sie starten Ihre Textverarbeitung und wollen einen Testausdruck machen. Im Druckerauswahl-Menü findet sich der neue Drucker. Ein Testausdruck gelingt auf Anhieb: Ohne Treiberinstallation, aber dank Jini. Wie das im einzelnen zustande kommen soll, demonstriert dieser Artikel an Beispiellistings.
Von dieser Vision ist Suns Jini (Java Intelligent Network Infrastructure) zwar noch ein gutes Stück entfernt; wirklich bezaubernd ist allerdings, daß der Technik anzumerken ist, welche grundlegenden Gedanken sich die verantwortlichen Entwickler über das System gemacht haben: der Aufbau ist klar und einfach strukturiert. Vergleicht man die Größe der gepackten Datei mit der des JDK 1.2 (knappe 20 MByte), kann man fast enttäuscht sein: magere 2,5 MByte gilt es, über das Netz zu quetschen.
Jini wurde konsequent auf die Verwendung von Java und Netzen hin ausgelegt (siehe als Einführung [1]). Die Annahme dahinter ist, daß das Internet und Java künftig überall zu finden sein werden, in Kühlschränken wie auf Festplatten. Das Projekt verbindet den objektorientierten Ansatz von Java mit den Eigenschaften, die RMI (Remote Method Invocation) für die verteilte Programmierung bietet. Zusammen ergibt es das, was Sun als typed network bezeichnet: Daten und Code werden über das Netz bewegt, alles unter der strengen Typisierung von Java. Konsequenterweise wird dabei alles (also Hard- und Software) als Objekt angesehen und letztendlich gleich behandelt. Jini dient dabei als Abstraktionsstufe und vereinigt die Sichten auf unterschiedliche Komponenten.
Ohne langwierige Konfigurationsorgien soll die Java-Bibliothek eine Infrastruktur für unterschiedliche Hard- und Software bieten. Sun nennt das spontaneous networking. Hardware wird ans Netz angeschlossen und kann ohne Aufwand sofort benutzt werden. Dasselbe gilt auch für Software: Man kann sich leicht die jinifähige Textverarbeitung vorstellen, die zur Rechtschreibprüfung ein jinifähiges Wörterbuch konsultiert. Diese vernetzte Welt kennt nur noch Dienstanbieter und -nutzer. Damit der Drucker ohne Treiberinstallation funktionieren kann, injiziert Jini Code vom Drucker über das Netz zum Dienstnutzer. Der Drucker lädt seinen Proxy (zum Beispiel einen Java-RMI-Stub) zum Klienten und bietet ihm so eine wohldefinierte Schnittstelle an. Der Client ruft Methoden des Proxy auf, und dieser kümmert sich um die korrekte Behandlung der Daten. Wenn der Dienst nicht mehr benötigt wird, wird der Proxy verworfen.
Damit Jini zaubern kann, wurde das Java-Programmiermodell ergänzt: zu Java und RMI kamen einige Infrastrukturkomponenten hinzu. Dienste (eigentlich ist hier alles ein Dienst) können einander und vor allem auch den sogenannten Lookup-Service (LUS) ohne Kenntnis des Netzes finden (bootstrapping). Als Voraussetzung brauchen sie lediglich eine Adresse, damit sie im Netz identifizierbar sind, eine Java-Virtual-Machine (JVM) und etwas Speicher. Den Rest besorgt die Infrastruktur: Dienste melden sich über ein Discovery&Join-Protokoll bei einem (ihnen meist vorher nicht bekannten) LUS an, dieser sorgt nötigenfalls für die Konfiguration, und schon sind die Dienste verwendbar. Dienstnutzer finden -anbieter ebenfalls über den LUS: sie durchsuchen diesen nach einem Interface, das etwa eine Rechtschreibprüfung implementiert (Lookup). Haben sie Erfolg, bekommen sie vom LUS ein Proxy-Objekt, das als Stellvertreter die gesamte Kommunikation mit dem eigentlichen Dienst übernimmt. Deren Realisierung ist Sache des Dienstes. Für den Dienstenutzer scheint alles lokal vorhanden zu sein. Der Lookup-Service ist dabei die zentrale Anlaufstelle, um Anbieter und Nutzer zusammenzuführen.
Zu bekannten Komponenten wie Beans oder Swing gesellen sich programmiertechnisch Leases, Transaktionen und Distributed Events. Die Strukturelemente sind keine festen Klassen, sondern lediglich Interfaces: Dienste implementieren sie nach ihren Bedürfnissen, werden dadurch aber gezwungen, jini enabled zu sein, das heißt die Art der Interaktion zwischen den Diensten wird festgelegt, nicht jedoch deren Implementierung. Das Kommunikationsprotokoll zwischen einem Druckerdienst und dem Drucker selbst kann proprietär sein, für den Benutzer ist das gleichgültig.
Mit etwas Glück ist der Aufwand, Jini lauffähig zu bekommen, relativ gering. Die größte Hürde ist zunächst der Download, denn Sun hat keine europäischen Spiegel dafür eingerichtet, man muß sich das Programmpaket deshalb direkt von developer.java.sun.com/developer/products/jini/index.html laden. Dazu wiederum ist es notwendig, sich als Entwickler bei Sun zu registrieren. Jini wird unter der neuen Sun Community Source License (SCSL) distributiert, man muß einen kostenlosen Lizenzvertrag akzeptieren, hat allerdings dafür die Quellen.
Sun bietet zwei Pakete an: das JiniSystem Software 1.0 Starter Kit besteht aus der Jini Core Platform: der Core-API, den Spezifikationen, der Dokumentation und dem Quellcode. Die JavaSpaces sind separat herunterzuladen.
Vor allem tagsüber kann der Download ein langwieriges Unterfangen sein (zwei bis drei Stunden und mehr). Oftmals hilft nur, den Download zur nächtlichen Stunde zu starten. Die Jini-Version 1.0 benötigt als Java-Umgebung das JDK 1.2. Dies ist leider noch nicht für alle Plattformen erhältlich und schränkt die Benutzer auf Windows 95/ 98/NT und Solaris ab Version 2.5.1 ein (Version 7 empfohlen).
Das ZIP-Archiv installiert sich in ein Unterverzeichnis namens jini1_0. Wenn man zusätzlich JavaSpaces einspielt, darf man dies erst nach Jini tun, da JavaSpaces Teile der HTML-Dokumentation ersetzt und erweitert.
Damit man einen Eindruck von Jini bekommt, liefert Sun für einige Interfaces eine Referenzimplementierung mit. Für diesen Artikel interessant ist davon der Lookup-Service. Da Jini auf RMI aufbaut, muß man als erstes das RMI Activation System (rmid) starten. Dort registriert sich der LUS als aktivierbares Objekt. Im Normalfall reicht zum Start ein einfaches
prompt>rmid -log<Verzeichnis>&
(unter Solaris). Dabei ist darauf zu achten, daß das JDK-1.2-Verzeichnis zuerst im Pfad steht. rmid legt dabei in <Verzeichnis> ein Log-Verzeichnis an oder benutzt das vorhandene, wenn eine frühere Instanz schon eins angelegt hat, was zu unschönen Nebeneffekten führen kann.
Jini beruht unter anderem auf der Fähigkeit von RMI, Klassen über das Netz von einem HTTP-Server zu laden. Dieser wird in der Codebase-Property angegeben. Sun liefert einen einfachen Server mit, der mittels GET auf Port 8080 .jar- oder .class-Files zur Verfügung stellt. Er findet sich in der Tools-Bibliothek von Jini (tools.jar) und wird durch
prompt> java -jar $JHOME/jini1_0/lib/tools.jar
-port 8080 -dir $JHOME/jini1_0/lib/ -verbose
gestartet. Das im Request angegebene File (relative Pfadnamen sind möglich) muß sich im Verzeichnis befinden, das mit der -dir-Option angegeben wurde. Mit der -verbose-Option gestartet gibt der Server bei jedem Request aus, welcher Rechner welche Datei angefordert hat. Das kann praktisch sein, wenn man den Weg von Code durch das Netz verfolgen will. Als letztes wird der Lookup-Service gestartet. Der CLASSPATH sollte dabei Listing 1 entsprechen.
Reggie ist eine Beispiel-Implementierung von Sun und findet sich in reggie.jar. <Pfad>/policy.all enthält eine allgemeine Sicherheits-Policy, die für das Java-Sicherheitsmodell notwendig ist (siehe Stolperfallen). Der Lookup-Service ist selbst als Jini-Dienst implementiert, das heißt er registriert sich bei sich selbst in der public-Gruppe. Der Zustand wird in /tmp/reggie_log festgehalten.
Man sollte darauf achten, daß zwischen den Aufrufen ausreichend viel Zeit liegt, damit sich die Dienste initialisieren können (mehr als 10 Sekunden.)
Im Paket ist auch ein grafischer LUS-Browser enthalten, der über das in Listing 2 enthaltene Kommando zu starten ist.
Die anderen Referenzimplementierungen von Sun (Transaction Manager und JavaSpaces) kann man ähnlich starten, sie sind aber zu diesem Zeitpunkt noch nicht nötig.
Jini soll die zweite Runde der Java-Revolution einläuten. Sie erweitert Java um Konzepte zur Entwicklung verläßlicher verteilter Systeme. Vom write-once, run anywhere gilt hier besonders das run anywhere. Ein Jini-System besteht aus einer Menge von Diensten, die zu Gruppen - sogenannten djinns - organisiert werden. Ein Dienst stellt dabei beliebige Funktionen bereit, die andere Dienste, Anwendungen oder Menschen verwenden können. Er kann in Soft- und/oder Hardware realisiert sein und an beliebigen Stellen im Netz laufen. Beispiele dafür sind ein Service, der EMails abschickt, oder ein Druckdienst, der etwas ausgibt. Eine zentrale Aufgabe der Jini-Infrastruktur ist es, Service-Anbieter und -nutzer zusammenzubringen. Wenn der vielzitierte Drucker an ein Netz angeschlossen wird, soll es den Druckdienst erkennen und dieser ohne weitere Arbeit (Treiberinstallation) für andere Komponenten im Netz verfügbar sein. Jini realisiert dies mit den Discovery-/Join-Protokollen und typischerweise einem Lookup-Service (LUS).
Eine Besonderheit ist, daß jeder Dienst einen sogenannten Proxy besitzt. Dieser besteht aus einem oder mehreren Java-Objekten, die serialisiert inklusive Programmcode an den Dienstnehmer übertragen werden. Der Typ und die Methoden der Objekte stellen die Schnittstelle dar, über die der Dienstnehmer den Dienst bei sich anspricht. Durch diese Form von mobilem Code kann die Funktion des Dienstes teilweise oder ganz beim Dienstnehmer realisiert werden. Als weiterer nützlicher Nebeneffekt ist das Protokoll, über das der Proxy mit seinem Dienst kommuniziert, nicht festgelegt. Dies ist besonders beim Einbinden von Geräten interessant, da der Proxy sich dann bereits bestehender Protokolle bedienen kann. Der Proxy läßt sich als dynamischer Treiber ansehen, den das System bei Bedarf lädt und nach der Verwendung wieder entfernt.
Zentrale Anlaufstelle in einem Jini-System ist der LUS. An ihn wenden sich einerseits Anbieter, um Dienste im Netz zu offerieren, und andererseits Interessenten, um Zugang zu dem gewünschten Dienst zu erlangen. Abbildung 1 und 2 illustrieren das Zusammenspiel dieser im Netz verteilten Komponenten. Die Bootstrap-Phase ([[bild_url1] Abbildung 1]) des Dienstanbieters besteht aus folgenden Schritten:
|
Dienste suchen einen Lookup-Service; sie bekommen dessen Proxy (P) und hinterlegen ihren eigenen (SP). |
Damit ist der Dienst im Netz verfügbar. Zum Auffinden und Benutzen eines Dienstes sind folgende Schritte nötig (siehe [[bild_url4] Abbildung 2]):
|
Interessenten suchen nach einem Lookup-Server und erhalten den Proxy eines oder mehrerer Dienste(s); nun lassen sich dessen Methoden aufrufen (Abb. 2). |
Beginnend auf der Dienstseite, sind für die folgende Umsetzung drei Schritte notwendig:
Als Beispiel dient ein Additions-Dienst, der die Berechnung auf einem anderen Rechner ausführen läßt. Da Jini auf Remote Methode Invocation aufbaut, ist es naheliegend (aber nicht zwingend), die Kommunikation zwischen Proxy und dem eigentlichen Dienst über dieses Protokoll zu realisieren. Jini ermöglicht es, den von RMI erzeugten Server-Stub direkt als Proxy zu benutzen. Das Interface (Listing 3) zwischen Proxy und Dienstnehmer ist ein normales RMI-Interface, das wie üblich von Remote abgeleitet ist und dessen Methoden RemoteExceptions auslösen können.
Im zweiten Schritt ist das Interface zu implementieren (Listing 4). Dazu ist ein RMI-Server erforderlich, der die Methode add zur Verfügung stellt. Nach dem Kompilieren müssen mit rmic die Stub- und Skeleton-Klassen erzeugt werden.
Damit man den Dienst verwenden kann, muß er im LUS registriert werden. Im Beispiel erledigt das ein eigenständiges Java-Programm (Listing 5). Als erstes muß ein RMISecurityManager installiert werden, da der Code des LUS-Proxy über das Netz geladen und dann ausgeführt werden soll. Dies ist mit dem Standard-Security-Manager nicht zulässig. Neben den eigentlichen Jini-Klassen (net.jini-Packages) hat Sun eine Reihe weiterer Wrapper-Klassen mitgeliefert, die Standardaufgaben wie Eintragen im LUS und Verlängern von Leases stark vereinfachen. Diese finden sich in den com.sun.jini-Packages.
Im folgenden wird von der JoinManager- und LeaseRenewalManager-Klasse Gebrauch gemacht. Der JoinManager verbirgt die Arbeit mit den Discovery/Join-Protokollen und stellt eine einfache Möglichkeit zum Eintragen von Diensten in den LUS dar. Er erwartet in seinem Konstruktor eine Instanz des Dienst-Proxy, dessen Attribute (zusätzliche Informationen), einen ServiceIDListener, der die erzeugte Service-ID entgegennimmt, und ein LeaseRenewalManager-Objekt. Letzterer übernimmt dann selbständig die Verlängerung des Lease für den Eintrag im LUS. Im Beispiel wird eine Instanz der AdderInterface_impl-Klasse erzeugt und an den JoinManager übergeben. Dieser ermittelt automatisch die zugehörige Stub-Klasse und hinterlegt sie als Proxy im LUS. Jeder Jini-Dienst wird in den LUS durch einen Universally Unique Identifier (UUID) eindeutig identifiziert. Die Discovery- und Join-Spezifikation fordert von Diensten, daß sie sich in allen LUS mit der gleichen Service-ID registrieren und diese persistent speichern, um sie auch bei einem möglichen Neustart des Dienstes beizubehalten. Im Beispiel läßt der JoinManager die Service-ID von einem LUS generieren und übermittelt sie dann an die ServiceIDNotify-Methode, wo sie ignoriert wird. Das Beispiel ist also nicht ganz Jini-konform.
java -Djava.rmi.server.codebase=http://<host>:<port>/<path>/ -Djava.security.policy=<path>/<policy-file>JiniAddService
startet das Programm. Wichtig ist dabei der abschließende Slash in der Codebase, da sie als Präfix vor Package und Klassennamen steht, um eine URL zu erhalten. Der gibt an, von wo die jeweilige Klassendatei aus Sicht des Client zu finden ist. Der Hostname sollte deshalb immer voll-qualifiziert sein. Die Klasse foo.bar.puh muß sich auf dem HTTP-Server unter http://<host>:<port>/<path>/foo/bar/puh.class befinden, da der RMI-Classloader der Client-JVM über diesen URL ihm unbekannte Klassen nachzuladen versucht.
Um den Dienst zu benutzen, ist - wie in Listing 6 erkennbar - ein wenig mehr Aufwand zu treiben. Die wesentlichen Klassen für diese Aufgabe sind LookupLocator, ServiceRegistrar und ServiceTemplate. Die erstgenannte verbirgt die Discovery-Phase. Verwendet wird dabei das Unicast Discovery Protocol, bei dem die Adresse eines LUS direkt angegeben werden muß. Das von ihm erhaltene ServiceRegistrar-Objekt stellt den LUS-Proxy dar. Die Beschreibung des gesuchten Dienstes erfolgt mittels der ServiceTemplate-Klasse. Sie läßt als Suchkriterien eine Service-ID, Java-Typen und Attribute zu. Service-IDs und Attribute müssen exakt übereinstimmen, bei Java-Typen werden sowohl Klassen gleichen Typs als auch davon abgeleitete gefunden. Der Wert null wird als Wildcard interpretiert.
Im allgemeinen ist es sinnvoll, immer mindestens einen Typ anzugeben, damit es beim Benutzen der gefundenen Objekte nicht zu ClassCastExceptions kommen kann. Attribute können die Suche verfeinern, um die Treffermenge zu reduzieren, und Service-IDs sind nützlich, um einen bestimmten Dienst zu finden. Im Beispiel wird nur ein Java-Typ, nämlich das AddInterface, angegeben. Die lookup-Methode des ServiceRegistrar-Objekts führt die eigentliche Suche aus. Das gefundene Objekt läßt sich nach einem Typecast wie ein lokales ansprechen.
java -Djava.security.policy=/<path>/policy.all JiniAddClient
startet das Programm. Jini sieht vor, daß Dienste in Gruppen organisiert werden können. Jeder kann zu beliebig vielen Gruppen gehören. Beispielsweise könnte ein Drucker sich in den Gruppen Hardware, Drucker und Konferenzraum 2 anmelden, oder verschiedene Dienste werden zusammengefaßt, weil sie gemeinsam eine Aufgabe lösen. Gruppen werden eingerichtet, indem man LUS die entsprechenden Gruppennamen zuweist. Bei Suns Referenzimplementierung müssen sie als Kommandozeilenparameter beim Start des LUS angegeben werden. Der Name public ist als Standard vergeben. Ein Dienstanbieter ist selbst für eine passende Registrierung in den LUS verantwortlich. Er muß seinen Dienst also in jedem ihm bekannten LUS genau dann registrieren, wenn der mindestens eine Gruppe verwaltet, zu der der Dienst gehören soll. Daneben hat Sun auch ein Admin-Interface vorgesehen. Implementiert ein Dienst dies, ist dessen Gruppenzugehörigkeit während der Laufzeit zum Beispiel über den mitgelieferten Browser änderbar. Bei den LUS kann man zusätzlich noch die Gruppen ändern, die sie verwalten sollen. Im Beispiel-Dienst (Listing 5) ist das Gruppenkonzept durch den JoinManager verborgen. Bei dem angebenen Aufruf registriert er den Dienst in allen gefundenen LUS und damit auch in allen Gruppen. Durch Verwendung eines anderen Konstruktors läßt sich die Registrierung des Dienstes auf bestimmte Gruppen einschränken:
new JoinManager(proxy, null,
new String[] {Gruppe1, Gruppe2}, null,
new SL(), new LeaseRenewalManager());
Wie bereits angedeutet, unterstützt der Dienstnehmer in Listing 6 nur das Unicast Discovery Protocol. Daneben bietet Jini noch das Multicast Request und das Multicast Announcement Protocol, um LUS in einem Netz zu finden. Jini bietet eine Infrastruktur auf Dienstebene an, das heißt, sie kann nicht dazu dienen, IP-Adressen und Subnetz-Masken von Rechnern zu konfigurieren, sondern setzt die Konfiguration auf niedriger Ebene voraus.
Voraussetzung beim Unicast Discovery Protocol ist, daß die Adresse des LUS bereits bekannt ist. Er wird über eine TCP-Verbindung zum Port 4160 (ein Scherz der Jini-Entwickler: Ergebnis der hexadezimalen Subtraktion CAFE - BABE) angesprochen. Als Antwort überträgt der LUS sein Proxy-Objekt und seine Gruppenzugehörigkeiten. Der Einsatz von Multicast-IP ermöglicht es, LUS ohne Kenntnis ihrer konkreten IP-Adresse zu finden. Dazu werden UDP-Datagramme an die Multicast-Gruppe 224.0.1.85 und Port 4160 gesendet. Sie enthalten die Gruppennamen, an denen man interessiert ist, und Service-IDs der bereits bekannten LUS. Ein LUS antwortet nur dann, wenn er noch nicht bekannt ist und zu einer der genannten Gruppen gehört. Er baut dazu eine TCP-Verbindung auf und übermittelt die Antwort wie im Unicast Discovery Protocol.
Über das Multicast Announcement Protocol machen sich LUS im Netz bekannt. Dazu schicken sie UDP-Datagramme an die Multicast-Gruppe 224.0.1.84:4160. Sie enthalten die Service-ID, die Netzadresse des LUS und die Gruppenzugehörigkeiten. Falls der LUS noch nicht bekannt ist und eine interessante Gruppe verwaltet, fordern interessierte Teilnehmer den LUS-Proxy über das Unicast Discovery Protocol an.
Normalerweise werden die beiden Multicast-Protokolle verwendet, um LUS im lokalen Netzsegment zu finden. Der Vorteil liegt vor allem im geringeren Konfigurationsaufwand: Der Benutzer muß in seinen Diensten und Anwendungen keine LUS-Adressen eintragen. Die Multicast-Protokolle haben jedoch nur eine begrenzte Reichweite, da die meisten Router so konfiguriert sind, daß sie keine Multicast-Pakete weitergeben. Für Verbindungen über solche Netzsegmente hinaus muß das Unicast Discovery Protocol verwendet werden.
Nach diesem theoretischen Exkurs soll nun auch der Dienstnehmer spontan über die Multicast-Protokolle seinen Additionsdienst finden (Listing 7). Wesentlich für die Implementierung sind die Klasse LookupDiscovery und das DiscoveryListener-Interface. Die Klasse LookupDiscovery benutzt die Multicast-Protokolle, um umliegende LUS zu finden. Welche interessant sind, bestimmen die im Konstruktor angegebenen Gruppen. Die Proxies dieser LUS werden per Event an die registrierten DiscoveryListener übergeben. Das Programm nimmt die Proxies in der discovered-Methode des DiscoveryListener-Interface entgegen. Dessen Methoden sollen keine komplexen Operationen beinhalten, um die Bearbeitung schnell aufeinanderfolgender Events zu ermöglichen. Daher speichert das Programm die Proxies zwischen und weckt den main-Thread zur Bearbeitung. Dort werden die Lookup-Services wie in Listing 6 nach einem AddInterface durchsucht. Sobald dieses gefunden wurde, wird die Berechnung durchgeführt und das Programm beendet. Zur Vervollständigung des DiscoveryListener-Interface muß die Methode discarded implementiert sein.
Bislang waren die Beispiele bewußt einfach gehalten. Dabei ist ein weiteres wichtiges Konzept von Jini vernachlässigt worden: Attribute. Einem Dienst können beim Eintrag in einen LUS Attribute zugeordnet werden, die den Dienst näher beschreiben oder Programmcode enthalten. Beispiele für beschreibende Attribute sind Herstellername, Versionsnummer des Dienstes oder ein Icon zur Darstellung in grafischen Browsern. Neben diesen allgemeinen lassen sich auch spezielle, auf bestimmte Dienstklassen abgestimmte Attribute definieren. Für einen Druckdienst könnte man so zusätzlich angeben, ob es sich um einen Laser- oder Tintenstrahldrucker handelt. Standardisierte Attribute existieren bisher allerdings nicht.
Attribute ermöglichen es, einerseits die Anzahl der Treffer einer Suchanfrage möglichst gering zu halten, andererseits einem menschlichen Benutzer Informationen für die Auswahl des richtigen Dienstes anzubieten. Realisiert werden Attribute durch Java-Objekte. Jedes public-Feld einer Klasse, die von Entry oder AbstractEntry abgeleitet ist, wird dabei als Attribut interpretiert (siehe Listing 8).
Ein Entry-Objekt stellt eine Menge von Attributen dar. Da einem Dienst mehrere solche Objekte zugeordnet sein können, speichert der LUS zu jedem Dienst demnach eine Menge von Attributmengen. Dadurch, daß Attribute in für Menschen verständlicher Form angezeigt werden sollen, entstehen Probleme wie Lokalisierung. Zu deren Lösung soll unter anderem das JavaBeans-Konzept beitragen.
Listing 9 zeigt das Registrieren eines Dienstes mit Attributen. Der attributes-Array wird dann dem JoinManager im Konstruktor übergeben. Das Code-Fragment in Listing 10 setzt zusätzlich zum Typ ein Attribut als Suchkriterium ein. Es wird nach einem Dienst gesucht, dem mindestens ein ServiceInfo-Objekt zugeordnet ist, das genau den Eintrag 1.0beta enthält. Der Wert null fungiert wieder als Wildcard.
Attribute sind auch nach der Registrierung noch modifizierbar, um Zustandsänderungen des Dienstes wiederzugeben. Beispielsweise können Statusinformationen in Attributen in den LUS hinterlegt werden (etwa Fehlerzustände von Geräten). Es wird jedoch davon ausgegangen, daß Attribute eher statischen Charakter haben. Aus Effizienzgründen gilt als Richtschnur, sie nicht öfter als einmal pro Minute zu ändern.
Da die Attribute in normalen Java-Klassen gespeichert werden, lassen sie sich auch mit Programmcode versehen. Damit ergibt sich eine weitere interessante Anwendungsmöglichkeit der Attribute, nämlich das Hinterlegen eines GUI zur Benutzung des Dienstes. Dieser Ansatz erlaubt es, daß andere Dienste und Programme ihn über das Java-Interface ansprechen können. Zusätzlich bringt er für den Fall, daß ein menschlicher Benutzer ihn direkt verwenden will, sein eigenes GUI gleich mit.
Die Beispiele zeigen, wie wenig Aufwand notwendig ist, einen Dienst in ein Jini-System zu integrieren. Der Vorteil liegt in den dynamischen Konfigurationsmöglichkeiten. Weitergehende interessante Aspekte (Transaktionen, verteilte Events, GUIs, JavaSpaces) sollen Artikel in künftigen Heften zeigen.
MARCO GRUTESE
studiert Informatik und arbeitet im Moment an einer Semesterarbeit über praktische Aspekte von Jini.
ANDRES ZEIDLER
ist wissenschaftlicher Mitarbeiter am Fachgebiet Verteilte Systeme der TU-Darmstadt und beschäftigt sich mit Infrastrukturen für Verteilte Systeme.
Literatur
[1] Andreas Dörr; Verteiltes Java; Geist aus dem Netz; Jini: Suns Projekt für Ressourcen-Sharing
| iX-TRACT |
|
Dieser Text ist der Zeitschriften-Ausgabe 04/1999 von iX entnommen.
Parallelprogrammierung - die Kunst der Multi-Core-Nutzung
Agile ALM - agile Praktiken im Application Lifecycle Management
Webentwicklung - Applikationen für mobile Clients