Roblet®-Development-Kit
1.3 (11Sep10)
API für Module

genRob.genControl.modules
Interface Module2


public interface Module2

Um ein Modul für den Roblet®-Server bereitzustellen, muß man diese Schnittstelle implementieren.  Eine Implementierung wird Modulklasse genannt.  Eine Modulklasse stellt Einheiten für Roblets® bereit, wobei der Server dabei als Vermittler auftritt.  Diese Schnittstelle ersetzt in absehbarer Zeit Module.

Beim Start des Servers ist ihm als Kommandozeilenargument u.a. der Name der gewünschten Modulklassen (einschließlich möglicher package-Namen) anzugeben.  Der Server lädt dann diese Klassen und erzeugt über ihren parameterlosen Konstruktor (der auch dann für eine Klasse vom Compiler erzeugt wurde, wenn er nicht explizit definiert wurde) eine Instanz.  Diese Instanz stellt daraufhin das Modul innerhalb des Servers dar.  Es wird zur Laufzeit des Servers nur eine Instanz einer Modulklasse pro angegebenen Modul bei den Startparametern erzeugt.

Der parameterlose Konstruktor der Modulklasse und statische Initialisierer sollten nicht zu komplex sein.  Am besten man verwendet diese Möglichkeiten gar nicht.  Die eigentliche Initialisierung eines Moduls soll in moduleInit(ModuleContext) erfolgen.  Ausgaben kann ein Modul mit dem Logger machen.

Einheiten werden den Roblets® unter Vermittlung des Roblet®-Server vom Modul mit Hilfe von getUnit(Class, RobletHandle) bereitgestellt.  Weiter unten sind mehr Informationen zur Definition, Implementierung und Instanziierung von Einheiten zu finden.

Lebenszyklus

Nach dem Laden der Modulklasse und erzeugen einer Instanz wird (einmal) moduleInit(ModuleContext) aufgerufen.  Wird hier eine Ausnahme geworfen, so wird das Modul nicht verwendet.

Bevor der Server ein Roblet® startet, wird robletInit(RobletHandle) aufgerufen;  nachdem es endete robletDone(RobletHandle).  Ausnahmen, die hierbei geworfen werden, werden nach Möglichkeit vom Server ignoriert.

Fordert ein Roblet® eine Einheiteninstanz an, so wird vom Server dazu die Methode getUnit(Class, RobletHandle) bemüht.

Sind keine Roblets® mehr im Server vorhanden und will der Server enden, so ruft er (einmal) moduleDone() auf.  Ausnahmen, die hier geworfen werden, werden ebenso nach Möglichkeit vom Server ignoriert.

Einheiten

Ein Modul soll zu von ihm verwalteten Einheitendefinitionen auf Anfrage durch den Roblet®-Server aus der zugehörigen Einheitenimplementierung eine Einheiteninstanz erzeugen.  Die Methode getUnit(Class, RobletHandle) legt dabei jeweils den Zusammenhang fest und gibt auf Anfrage Einheiteninstanzen zurück.

Wenn ein Roblet® mit Hilfe einer Einheitendefinition eine Einheiteninstanz anfordert, so ruft der Roblet®-Server die Methode getUnit(Class, RobletHandle) auf und gibt das Resultat (nach Umwandlung in eine Ersatzinstanz) an das Roblet® zurück.

Einheitendefinition und -implementierungen

Einheitendefinitionen müssen Schnittstellen (interface) sein, die Unit erweitern (extends).  Eine Einheitenimplementierung ist eine öffentliche Klasse (public class), die eine Einheitendefinition implementiert (implements).  Damit ist dann auch automatisch die Einheitenimplementierung vom Typ Unit.

Einheiten sind dazu gedacht, vom Modul verwaltete Ressourcen zu manipulieren.  Der Roblet®-Server stellt durch dynamische, für Modul- und Roblet®-Entwickler transparente Erzeugung von Ersatzinstanzen sicher, daß diese Ressource-Manipulation nicht zu Komplikationen führt, wenn der Server den Ablauf des Roblets® beeinflußt.  Die Ersatzinstanzen werden dem Roblet® statt der Einheiteninstanzen des Moduls zur Verfügung gestellt.

Manipulierende Rückgabewerte (und Parameter)

Wenn Methoden von Einheiten Werte zurückgeben, gilt es eine analoge Problemstellung zu berücksichtigen.  Gibt eine solche Methode eine Instanz zurück, die nichts an den Ressourcen manipuliert, so ist nichts weiter zu beachten.  Gibt aber eine Einheit eine Instanz zurück, die ihrerseits eine Ressource manipulieren kann, so muß die Einheitendefinition als Rückgabetyp der jeweiligen Methode eine Schnittstelle vorsehen, die Unit erweitert - also letztlich auch eine Einheitendefinition.  Auf diese Weise ist der Server in der Lage, auch für die genannten Instanzen Ersatzinstanzen für das Roblet® zu erzeugen und somit Gefahren zu bannen.

Werden derartige Instanzen vom Roblet® wieder an das Modul zurückübergeben, so werden dem Modul jedoch die korrekten Originale überreicht.  Im Modul muß also auch für diesen Fall nichts weiter beachtet werden.

Die eben gemachten Betrachtungen für Rückgabewerte und Parameter, die Ressourcen manipulieren können, gelten dann rekursiv die gleichen Betrachtungen, wie für Einheiten.  Auch aus diesem Grund kann man auch hier der Einfachheit von Einheiten reden.

Einschränkungen

Hash-Wert von Einheiten

Einheitenimplementierungen müssen darauf achten, daß sich der Hash-Wert einer Einheiteninstanz nicht ändert.  Hintergrund ist das o.g. Wandeln von Instanzen in Ersatzinstanzen und umgekehrt.

Ausschließen kann man das, indem eine Einheitenimplementierung keine Klasse erweitert und die eigenen Hash-Methoden nicht überschreibt (vgl. Object.hashCode()).  Denn beispielsweise ändert sich der Hash-Wert einer ArrayList, wenn Einträge hinzugefügt oder weggenommen werden, da die Liste an sich ihren Hash-Wert über die Einträge berechnet.

Daten von Roblets®

Ein Modul muß sicherstellen, daß es keine Instanzen, die in einem Roblet® erzeugt wurden, nach dessen Ende weiter aufbewahrt.  Anderenfalls kann ein Roblet® nicht vollständig aufgeräumt werden, da der zugehörige Klassenlader des Roblets® möglicherweise noch in Verwendung ist.  Gegebenenfalls müssen also nach Ende eines Roblets® Kopien von benötigten Daten im Modul erzeugt werden.

See Also:
Logger, ModuleContext, RobletHandle

Method Summary
 Unit getUnit(Class clazz, RobletHandle handle)
          Muß für ein Roblet® eine Einheiteninstanz passend zur angegebenen Einheitendefinition zurückgeben.
 void moduleDone()
          Ermöglicht ein abschließendes Aufräumen des Moduls.
 void moduleInit(ModuleContext context)
          Initialisiert ein Modul.
 void robletDone(RobletHandle handle)
          Ermöglicht Aufräumarbeiten pro Roblet®.
 void robletInit(RobletHandle handle)
          Ermöglicht Vorbereitungen pro Roblet®.
 

Method Detail

moduleInit

public void moduleInit(ModuleContext context)
                throws Exception
Initialisiert ein Modul.  Diese Methode wird vom Roblet®-Server einmal aufgerufen, nachdem die Modulklasse erfolgreich geladen und instanziiert worden ist.  Bei Aufruf dieser Methode existieren noch keine Roblets®.

Initialisierungen sollten hier erfolgen, anstatt in einem parameterlosen Konstruktor oder in statischen Initialisierern.  In der Praxis hat sich bewährt, daß der Entwickler für die Modulklasse gar keinen Konstruktor definiert und alle zu initialisierenden Instanz-Variablen in hier beschriebenen Methode erzeugt werden.

Wenn die Initialisierung aus irgendeinem Grunde fehlschlägt, sollte eine Ausnahme mit einer informativen Nachricht geworfen werden.  In einem solchen Fall wird der Server das Modul nicht verwenden und die Ausnahme ins Logbuch eintragen.

Die Initialisierung kann prinzipiell beliebig lange erfolgen.  Über den ModuleContext kann auf den Logger zugegriffen werden, um gegebenenfalls Informationen über den Stand der Initialisierung auszugeben.  Der Server wird solange ein Modul für Roblets® nicht verwenden, solange es nicht initialisiert ist.

Parameters:
context - Kontext des Moduls, der u.a. Zugang auf das Logger ermöglicht
Throws:
Exception - falls das Modul sich nicht korrekt initialisieren konnte
See Also:
moduleDone(), robletInit(RobletHandle)

moduleDone

public void moduleDone()
Ermöglicht ein abschließendes Aufräumen des Moduls.  Diese Methode erlaubt dem Modul benutzte Resourcen freizugeben bzw. in einen guten Zustand zurückzuversetzen.  Bevor ein Server endet, wird diese Methode einmal aufgerufen.  Es existieren zu diesem Zeitpunkt keine Roblets® mehr.

Wenn hier ein Problem auftritt, so sollte dennoch ohne Ausnahme zurückgekehrt werden.  Gegebenenfalls können Informationen über den Fehler über den Logger ausgegeben werden.  Der Server ignoriert nach Möglichkeit geworfene Ausnahmen.

Das Aufräumen kann prinzipiell beliebig lange erfolgen.  Über den ModuleContext kann auf den Logger zugegriffen werden, um gegebenenfalls Informationen über den Stand des Aufräumens auszugeben.  Der Server wird nicht enden, solange ein Modul nicht fertig aufgeräumt ist.

See Also:
moduleInit(ModuleContext)

robletInit

public void robletInit(RobletHandle handle)
Ermöglicht Vorbereitungen pro Roblet®.  Diese Methode wird vom Roblet®-Server einmal aufgerufen, bevor ein Roblet® zum Laufen kommt.  Tritt hier eine Ausnahme auf, so wird der Server sie nach Möglichkeit ignorieren.

ACHTUNG:  Die Aktivitäten in dieser Methode sollten von kurzer Dauer sein, da sie die Startzeit für jedes Roblet® betreffen.  Der Server wird solange ein Roblet® nicht laufenlassen, wie diese Routine nicht beendet ist.

Gewöhnlich wird das übergebene RobletHandle benutzt, um darin per RobletHandle.put(Object, Object) einen Eintrag zu machen, den das Modul dann bei späteren Aurufen für das Roblet® per RobletHandle.get(Object) wiedererkennen kann.

See Also:
robletDone(RobletHandle), moduleInit(ModuleContext)

robletDone

public void robletDone(RobletHandle handle)
Ermöglicht Aufräumarbeiten pro Roblet®.  Diese Methode wird vom Roblet®-Server einmal aufgerufen, nachdem ein Roblet® endete.  Tritt ein Ausnahme auf, so wird der Server sie nach Möglichkeit ignorieren.

ACHTUNG:  Die Aktivitäten in dieser Methode sollten von kurzer Dauer sein, da sie die Startzeit für jedes nachfolgende Roblet® betreffen.  Der Server wird mindestens solange kein neues Roblet® laufenlassen, wie diese Routine nicht beendet ist.

See Also:
robletDone(RobletHandle), moduleInit(ModuleContext)

getUnit

public Unit getUnit(Class clazz,
                    RobletHandle handle)
Muß für ein Roblet® eine Einheiteninstanz passend zur angegebenen Einheitendefinition zurückgeben.  Wird null zurückgegeben, so befragt der Server das nächste Modul.

Diese Methode wird pro Roblet® unter Umständen mehrfach pro Einheitendefinition aufgerufen, jedoch betreibt ein Roblet®-Server pro Roblet® auch Caching.  Fordert ein Roblet® eine Einheit mehrfach an, obwohl noch eine Referenz auf diese existiert, so gibt der Server automatisch die an das Roblet® zurück, die beim letzten Mal zurückgegeben wurde, ohne seinerseits noch einmal das Modul zu konsultieren.

ACHTUNG:  Der übergebene Repräsentant des Roblets® sollte nicht innerhalb des Moduls vermerkt werden.

Parameters:
clazz - Einheitendefinition (Schnittstelle der Einheit)
handle - Repräsentant eines Roblets®
Returns:
Einheiteninstanz oder null, wenn keine Implementierung zur Definition vom Modul zur Verfügung gestellt wird

Roblet®-Development-Kit
1.3 (11Sep10)
API für Module

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