Roblet®-Development-Kit
1.2 (22Jul10)
API für Anwendungen

genRob.genControl.client
Class Client

java.lang.Object
  extended bygenRob.genControl.client.Client

public class Client
extends Object

Eine Instanz dieser Klasse stellt einen Klienten für einen Roblet®-Server dar.

Die Benutzung dieser Klasse in einer Anwendung ist denkbar einfach (Beispiele weiter unten):

Alle von den Klassen der Bibliothek verwalteten Threads sind Dämonen und haben eine Priorität gleich des Klient-initialisierenden Threads.  Allerdings ist es möglich, daß von dieser Bibliothek benutzte fremde Bibliotheken (z.B. RMI) Threads mit anderen Prioritäten und Dämon-Eigenschaften erzeugen.

Beispiel für das Senden eines Roblets® auf einen namentlich bekannten Server

Der Server soll roblet.org sein.  Dort läuft für diese Zwecke ein Test-Server an Standard-Port 2001.
 import  genRob.genControl.client.Client;
 import  java.io.Serializable;
 import  java.util.Date;
 import  org.roblet.Roblet;
 import  org.roblet.Robot;
 
 // Anwendungsimplementierung
 public class  DateApp
 {
 
     // Methode läuft natürlich lokal als Teil der Anwendung
     public static void  main (String[] args)
         throws Exception
     {
         Client  client = new Client ();
 
         String  servername = "roblet.org";
         try
         {
             Roblet  roblet = new DateRoblet ();
             Date  date = (Date) client. getServer (servername).
                                   getSlot (). run (roblet);
 
             System.out.println ("Date"
                                     + " of " + servername
                                     + " is " + date);
         }
         catch (Exception e) {   e. printStackTrace ();  }
 
         client. close ();
     }
 
     // Roblet®-Implementierung
     private static class  DateRoblet
         implements Roblet, Serializable
     {
         // Interface Roblet
         // Methode läuft fern im Server (!)
         public Object  execute (Robot rRobot)
         {
             return new Date ();
         }
     }
 
 }
 
Vorausgesetzt, daß alle Java™-Archive des RDK insbesondere org.roblet.jar im gleichen Verzeichnis wie DateApp.java liegen, kann mit folgendem kompiliert werden (Unix®/MacOS™/Linux, JDK 6):
 javac  -classpath org.roblet.jar:.  DateApp.java
 
Und unter Windows™:
 javac  -classpath org.roblet.jar;.  DateApp.java
 
Will man es nun das Beispiel laufen lassen, gibt man folgendes ein (Unix®/MacOS™/Linux, JDK 6):
 java  -classpath org.roblet.jar:.  DateApp
 
Und unter Windows™:
 java  -classpath org.roblet.jar;.  DateApp
 

Beispiel für das Senden eines Roblets® auf unbekannte Server

 import  genRob.genControl.client.Client;
 import  genRob.genControl.client.Nominee;
 import  genRob.genControl.client.NomineeListener;
 import  java.io.Serializable;
 import  java.util.Date;
 import  org.roblet.Roblet;
 import  org.roblet.Robot;
 
 // Anwendungsimplementierung
 public class  DateAppAll
 {
 
     // Methode läuft natürlich lokal als Teil der Anwendung
     public static void  main (String[] args)
         throws Exception
     {
         Client  client = new Client ();
 
         client. addListener
         (
             new NomineeListener ()
             {
                 public void  addedNominee (Nominee nominee)
                 {
                     try
                     {
                         String  servername = nominee. toString ();
                         Roblet  roblet = new DateRoblet ();
                         Date  date = (Date) nominee. getServer ().
                                             getSlot (). run (roblet);
 
                         System.out.println ("Server date"
                                                 + " of " + servername
                                                 + " is " + date);
                     }
                     catch (Exception e) {   e. printStackTrace ();  }
                 }
                 public void  removedNominee (Nominee nominee)   {}
             }
         );
 
         System.out.println ("<Enter> zum Abbrechen");
         System.in.read ();
 
         client. close ();
     }
 
     // Roblet®-Implementierung
     private static class  DateRoblet
         implements Roblet, Serializable
     {
         // Interface Roblet
         // Methode läuft fern im Server (!)
         public Object  execute (Robot rRobot)
         {
             return new Date ();
         }
     }
 
 }
 
Diese Anwendung kompiliert man genauso (s.o.).  Auch die Ausführung sieht gleich aus.  Vor der Ausführung muß allerdings ein Verzeichnis im lokalen Netz laufen (in separatem Terminal;  im RDK-Verzeichnis;  JDK 6):
 java  -jar org.roblet.jar  directory
 
Außerdem sollten in diesem Verzeichnis (lokale) Server sichtbar sein bzw. man muß einen Server starten (in separatem Terminal;  im RDK-Verzeichnis;  JDK 6):
 java  -jar org.roblet.jar  server
 

See Also:
Server, NomineeListener

Constructor Summary
Client()
          Erzeugt einen Klienten, wie er normalerweise benötigt wird - dabei wird kein Logging ermöglicht, aber der Zugriff auf Verzeichnisdienste aktiviert.
Client(Log log)
          Erzeugt einen Klienten, bei dem das Logging über die mitgegebene Instanz ermöglicht und der Zugriff auf Verzeichnisdienste aktiviert wird.
Client(Log log, boolean genMediator)
          Erzeugt einen Klienten, welcher Log-Informationen generieren und auf Verzeichnisdienste vom Typ genRob®-genMediator zugreifen kann.
 
Method Summary
 void addListener(NomineeListener listener)
          Fügt einen Interessenten an Roblet®-Server-Kandidaten (Nominee's) hinzu.
 void close()
          Schließt den Klienten und gibt Hilfsressourcen wieder frei.
protected  void finalize()
          Wird vom "garbage collector" aufgerufen und stellt sicher, für den Klienten sicher, daß close() aufgerufen wird, nachdem die Instanz nicht mehr referenziert wird.
 Server getServer(Identity identity)
          Gibt eine Server-Repräsentanz zur angegebenen Identität zur Benutzung zurück.
 Server getServer(String servername)
          Gibt eine Server-Repräsentanz zum angegebenen Servernamen zur Benutzung zurück.
 void removeListener(NomineeListener listener)
          Entfernt einen Interessenten an Roblet®-Server-Kandidaten (Nominee's).
 Object run(String servername, Roblet roblet)
          Deprecated. Zu ersetzen durch eine Kombination von getServer(String), Server.getSlot() und Slot.run(Roblet).  Diese scheinbar einfache Methode ist zwar für Einsteiger gut, hat aber in der Praxis oft den Blick für ein tieferes Verständnis der Roblet®-Technik versperrt.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Client

public Client()
       throws ClientException
Erzeugt einen Klienten, wie er normalerweise benötigt wird - dabei wird kein Logging ermöglicht, aber der Zugriff auf Verzeichnisdienste aktiviert.  Ein Klient sollte mit close() geschlossen werden, wenn er nicht mehr benötigt wird.

Ein Aufruf entspricht

  Client(null,true)
 

Throws:
ClientException - Fehler beim Erzeugen der RMI-Requisiten oder Hinzufügen des Verzeichnisdienstes
See Also:
Client(Log,boolean)

Client

public Client(Log log)
       throws ClientException
Erzeugt einen Klienten, bei dem das Logging über die mitgegebene Instanz ermöglicht und der Zugriff auf Verzeichnisdienste aktiviert wird.  Ein Klient sollte mit close() geschlossen werden, wenn er nicht mehr benötigt wird.

Ein Aufruf entspricht

  Client(log,true)
 

Parameters:
log - Instanz zur Verarbeitung von Log-Informationen oder null, wenn keine solche Information erzeugt werden soll
Throws:
ClientException - Fehler beim Erzeugen der RMI-Requisiten oder Hinzufügen des Verzeichnisdienstes
See Also:
Client(Log,boolean)

Client

public Client(Log log,
              boolean genMediator)
       throws ClientException
Erzeugt einen Klienten, welcher Log-Informationen generieren und auf Verzeichnisdienste vom Typ genRob®-genMediator zugreifen kann.  Wurde für einen Klienten der Zugriff auf den Verzeichnisdienst aktiviert, so muß er close() geschlossen werden, um alle verwendeten Ressourcen wieder freizugeben.

Wird der Zugriff auf Verzeichnisdienst nicht aktiviert, so werden auch keine RMI-Requisiten initialisiert.  In diesem Fall können daher keine (alten) Roblet®-Server, die nur per RMI mit den Klienten kommunizieren, vom Klienten benutzt werden.

Beim Zugriff auf Verzeichnisdienste bekommen alle im folgenden von der Bibliothek intern gestarteten Threads die gleiche Priorität, wie die des aufrufenden Threads.  Ebenso wird die zugehörige ThreadGroup benutzt, um darin eine ebensolche mit Namen client#x (x laufende Nummer) für die zu startenen Threads zu erzeugen.  Für den Zugriff auf Verzeichnisdienste werden einige RMI-Requisiten initialisiert.  Zu beachten ist, daß RMI seine Threads an anderer Stelle einhängt und die Prioritäten nach eigenen Regeln setzt.  Alle gestarteten Threads des Klienten sind als Dämon gekennzeichnet;  RMI hier wieder mit Ausnahmen.

Als Teil der RMI-Requisiten wird ein eigener SecurityManager gesetzt, sofern in der Anwendung noch keiner gesetzt war.  Dieser erlaubt alles.  Wenn das nicht gewünscht ist, so muß vor der Erzeugung eines Klienten ein eigener SecurityManager gesetzt werden.

Weiterhin wird zur Unterstützung von RMI ein HTTP-Server gestartet, der am nächsten freien Port lauscht.  Anfragen werden über den bei Aufruf dieses Konstruktors gesetzten Kontext-Klassenladers (Thread.getContextClassLoader()) befriedigt.  Ist keiner gesetzt, so wird der Klassenlader der Klasse desselben Threads und sofern dieser null ist, der System-Klassenlader (ClassLoader.getSystemClassLoader()) eingesetzt. Für RMI wird passend die Java™-Eigenschaft java.rmi.server.codebase gesetzt.

Parameters:
log - Instanz zur Verarbeitung von Log-Informationen oder null, wenn keine solche Information erzeugt werden soll
genMediator - Wenn true wird der Verzeichnisdienst genRob®-genMediator verwendet, um Roblet®-Server aufzufinden.  Ansonsten wird der Dienst nicht kontaktiert und gleichzeitig auch keine RMI-Umgebung initialisiert.
Throws:
ClientException - Fehler beim Erzeugen der RMI-Requisiten oder Hinzufügen des Verzeichnisdienstes
See Also:
Client()
Method Detail

close

public void close()
Schließt den Klienten und gibt Hilfsressourcen wieder frei.  Laufende Hilfsthreads werden angehalten.  Der Sicherheitsverwalter wird zurückgesetzt, sofern er von dieser Instanz eingangs gesetzt war und ungeändert gesetzt ist.

Ein mehrfacher Aufruf dieser Methode ist ungefährlich.

Schließt man den Klienten nicht, so endet die JVM solange nicht, bis explizit ein Aufruf von System.exit(int) erfolgt.

See Also:
finalize()

run

public Object run(String servername,
                  Roblet roblet)
           throws InterruptedException,
                  ClientException,
                  Exception
Deprecated. Zu ersetzen durch eine Kombination von getServer(String), Server.getSlot() und Slot.run(Roblet).  Diese scheinbar einfache Methode ist zwar für Einsteiger gut, hat aber in der Praxis oft den Blick für ein tieferes Verständnis der Roblet®-Technik versperrt.

Platziert ein Roblet® auf dem zugehörigen Roblet®-Server, der es dann laufen läßt.  Diese Aktion ist mit Netzwerkaktivität verbunden und kann daher unbestimmte Zeit in Anspruch nehmen.

Zur Ausführung wird ein neues Fach auf dem Server eingerichtet und das Roblet® kommt darin zum Laufen - dessen Ausführung beendet also keine Roblets® aus früheren Aufrufen dieser Methode (anders als bei Slot.run(Roblet)).

Das Roblet® wird für den Transport serialisiert und zum Server geschickt.  Aus diesem Grund muß das Roblet den Typ Serializable implementierten.

Wird statt eines Roblets® null übergeben, so wird auch null zurückgegeben.  Es wird kein Roblet beendet, da sowieso ein neues Fach für null benutzt würde (anders als bei Slot.run(Roblet)).

Ist das Roblet® nicht null, so wird vom Roblet®-Server dessen Methode Roblet.execute(org.roblet.Robot) ausgeführt.  Nach deren Ende wird ihr Rückgabewert hier zurückgegeben.  Es wird kein Roblet beendet, da sowieso ein neues Fach für null benutzt würde (anders als bei Slot.run(Roblet)).

Wird im Hauptthread, welcher Roblet.execute(org.roblet.Robot) ausführt, eine Ausnahme, abgeleitet von Exception, geworfen, so wird sie an dieser Stelle auch geworfen.  Schließt man diese Methode demnach in einen try-Block ein, so kann man im catch-Block direkt die selbst erzeugten Ausnahmen abfangen.

Wurde eine Ausnahme, abgeleitet von Exception, in einem beliebigen anderen Thread des Roblets® erzeugt (und nicht abgefangen) während der Hauptthread des Roblets® noch lief, so wird auch diese entsprechend hier geworfen (während das Roblet® bereits vom Server beendet wurde).

Entsteht im Hauptthread oder einem beliebigen anderen eine Ausnahme, welche nicht von Exception abgeleitet ist, so wird der Server nach Möglichkeit trotzdem Informationen schicken, die vom Roblet®-Klienten dann jedoch in eine ClientException gepackt werden.

Sollte die Verbindung unbrauchbar werden, so wird eine ClientException geworfen.  Es bleibt in diesem Fall offen, ob das Roblet® erfolgreich ankam und lief oder nicht.  Ein erneuter Aufruf der Methode baut eine neue Verbindung auf und hat keinen Bezug zu vorhergehenden Aufrufen.

Wird der diese Methode aufrufende Thread unterbrochen, so wird entweder eine Ausnahme vom Typ InterruptedException geworfen oder das Unterbrechungssignal (interrupt flag) des Threads gesetzt.  Ersteres wird gemacht, wenn die Netzwerkaktivität noch nicht oder gerade ausgelöst wurde.  Letzteres geschieht, wenn die Aktivität bereits abgeschlossen ist.  Im letzteren Fall sind die Ergebnisse zwar normal verwendbar, aber es ist auch zu beachten, daß der Thread natürlich beim nächsten Object.wait(), Thread.sleep(long) o.ä. eine Ausnahme obigen Typs erzeugen wird.

Mehrmalige Aufrufe dieser Methode mit den gleichen Parametern kann in bestimmten Fällen verschiedene Server ansprechen.  Gründe dafür können Load-Balancer und Änderungen im DNS sein, welches andere Server sichtbar werden läßt.

Anfragen nach Klassen und Ressourcen für bzw. durch das Roblet® werden über den bei Aufruf dieser Methode gesetzten Kontext-Klassenladers (Thread.getContextClassLoader()) befriedigt.  Ist keiner gesetzt, so wird der Klassenlader der Klasse des Roblets® verwendet.  Ist dieser null, so wird der der Klasse des diese Methode aufrufenden Threads benutzt.  Ist auch dieser null, so wird der System-Klassenlader (ClassLoader.getSystemClassLoader()) eingesetzt.

Parameters:
servername - Name des Roblet®-Servers in der Form host:port, wobei host ein DNS-Name oder direkt eine IP-Adresse sein kann und port im Bereich von 1 bis 65535 liegen muß
roblet - Roblet®, welches auf dem Server zum Laufen gebracht wird
Returns:
Resultat, welches vom Roblet® kommt
Throws:
InterruptedException - falls der aufrufende Thread beim Warten auf das Resultat durch die Anwendung zum Unterbrechen aufgefordert wird oder bereits vorher sein Unterbrechungssignal (interrupt flag) gesetzt war
ClientException - falls die Verbindung nicht funktioniert, der Servername eine inkorrekte Syntax hat oder sonstige Probleme auftraten - verkettet ist die Ursache
Exception - falls im Roblet® ein Fehler auftrat
See Also:
getServer(String), getServer(Identity), addListener(NomineeListener)

getServer

public Server getServer(String servername)
                 throws InterruptedException,
                        ClientException
Gibt eine Server-Repräsentanz zum angegebenen Servernamen zur Benutzung zurück.  Diese Aktion ist mit Netzwerkaktivität verbunden und kann daher unbestimmte Zeit in Anspruch nehmen.  Es wird also nicht mit einem timeout gearbeitet, jedoch der Thread, der diese Methode aufruft, kann jederzeit unterbrochen werden.

Es wird eine Verbindung zum Roblet®-Server aufgebaut, um dessen Identität festzustellen, da möglicherweise bereits eine Verbindung unter einem anderen Namen besteht.  Ist letzteres der Fall, so wird die bereits bekannte Repräsentanz zurückgegeben.  Pro Klient (Client) wird für einen Server immer die gleiche Repräsentanz (Instanz) zurückgegeben.  Man kann also bei Bedarf direkt auf Gleichheit prüfen.

Mehrmalige Aufrufe dieser Methode kann in bestimmten Fällen die Rückgabe verschiedener Server-Repräsentanzen zur Folge haben.  Gründe dafür können Load-Balancer und Änderungen im DNS sein, welches andere Server sichtbar werden läßt.

Parameters:
servername - Name des Roblet®-Servers in der Form host:port oder host, wobei host ein DNS-Name oder direkt eine IP-Adresse sein kann und port im Bereich von 1 bis 65535 liegen muß; ohne Port-Angabe wird Standard-Port 2001 angenommen
Returns:
zugehörige Server-Repräsentanz
Throws:
InterruptedException - falls der aufrufende Thread beim Warten auf den Roblet®-Server durch die Anwendung zum Unterbrechen aufgefordert wird oder bereits vorher sein Unterbrechungssignal (interrupt flag) gesetzt war
ClientException - falls der Servername eine inkorrekte Syntax hat oder sonstige Probleme auftraten - verkettet ist die Ursache
See Also:
getServer(Identity), run(String,Roblet), addListener(NomineeListener)

getServer

public Server getServer(Identity identity)
                 throws InterruptedException,
                        ClientException
Gibt eine Server-Repräsentanz zur angegebenen Identität zur Benutzung zurück.  Diese Aktion ist mit Netzwerkaktivität verbunden und kann daher unbestimmte Zeit in Anspruch nehmen.  Es wird also nicht mit einem timeout gearbeitet, jedoch der Thread, der diese Methode aufruft, kann jederzeit unterbrochen werden.

Es wird eine Verbindung zum Roblet®-Server aufgebaut, um dessen Identität festzustellen, da möglicherweise bereits eine Verbindung unter einem anderen Namen besteht.  Ist letzteres der Fall, so wird die bereits bekannte Repräsentanz zurückgegeben.  Pro Klient (Client) wird für einen Server immer die gleiche Repräsentanz (Instanz) zurückgegeben.  Man kann also bei Bedarf direkt auf Gleichheit prüfen.

Parameters:
identity - Identität des Roblet®-Servers
Returns:
zugehörige Server-Repräsentanz
Throws:
InterruptedException - falls der aufrufende Thread beim Warten auf den Roblet®-Server durch die Anwendung zum Unterbrechen aufgefordert wird oder bereits vorher sein Unterbrechungssignal (interrupt flag) gesetzt war
ClientException - falls sonstige Probleme auftraten - verkettet ist die Ursache
See Also:
getServer(String), run(String,Roblet), addListener(NomineeListener)

addListener

public void addListener(NomineeListener listener)
Fügt einen Interessenten an Roblet®-Server-Kandidaten (Nominee's) hinzu.  Dieser Interessent wird über alle bereits gefundenen und zukünftige Server-Kandidaten informiert.

Parameters:
listener - Interessent an Roblet®-Server-Kandidaten
See Also:
removeListener(NomineeListener), getServer(String), run(String,Roblet)

removeListener

public void removeListener(NomineeListener listener)
Entfernt einen Interessenten an Roblet®-Server-Kandidaten (Nominee's).  Fortan erhält er keine Informationen mehr.

Ist der angegebene Interessent gar nicht eingemeldet gewesen, so passiert nichts.

Parameters:
listener - Interessent an Roblet®-Server-Kandidaten
See Also:
addListener(NomineeListener)

finalize

protected void finalize()
Wird vom "garbage collector" aufgerufen und stellt sicher, für den Klienten sicher, daß close() aufgerufen wird, nachdem die Instanz nicht mehr referenziert wird.


Roblet®-Development-Kit
1.2 (22Jul10)
API für Anwendungen

Copyright © 2001-2010, roblet®.org, Hagen Stanek, http://roblet.org/rdk