Schreiben eines neuen Dienstes



Ein neuer Dienst sollte von VerySimpleService erben und ein Remote-Interface implementieren. Ein gutes Beispiel ist der photo-Dienst.
Die Basis-Klasse kümmert sich um das Erzeugen eines Proxy-Objektes, registriert den Dienst, Verwaltet die Attribute, besorgt einen eideutigen Identifizierer, authentifiziert und verschlüsselt den Netzwerk-Verkehr, kontrolliert den Zugriff auf die einzelnen Interface-Funktionen um implementiert einen persistenten Zustand.
Dies ist der Code des Dienstes. Er enthält nur minimale funktionalität:


public class PhotoService extends VerySimpleService implements PhotoProxyIF
{
private static final boolean debugThis = true;

public PhotoService() throws java.rmi.RemoteException , java.io.IOException
{
if(debugThis)Logger.debug.println("DEBUG: PhotoService starting up...");
init(this, jaugment2.photo.PhotoProxyIF.class);



}

public static class PhotoCameraFactory implements PhotoProxyIF.PhotoCameraFactory
{
private static PhotoProxyIF.PhotoCameraIF cam = null;
public PhotoProxyIF.PhotoCameraIF createCamera()
{
if(cam!=null)
return(cam);
cam = new PhotoCamera();
return(cam);
}
}

public PhotoProxyIF.PhotoCameraFactory getCameraFactory() throws java.rmi.RemoteException
{
return(new PhotoCameraFactory());
}


public String getComment()
{return("takes photos with optional timestamp+position+orientation");};
public String getCreator()
{return("Marcus Wolschon");};
public UIDescriptor getUIDescriptor()
{
if(debugThis)Logger.debug.println("DEBUG: PhotoService.getUIDescriptor() called...");
//TODO: test return(PhotoSwingRepresentation.getUIDescriptor());
return(PhotoDockin.getUIDescriptor());
};


Das Service-Interface ist PhotoProxyIF und es definiert nur eine einzige Funktion getCameraFactory().
Wie sie sehen, rufen wir im Konstruktor init() auf. Dieser Aufruf ist Pflicht. Das erste Argument sollte fast immer "this" sein.
Das zweite, das Interface. Sie können zusätzliche Attribute und einen ersten LookupLocator üo;bergeben. Es ist eine gute Idee loadme() nach init(...) aufzurufen, falls sie diese Funktion implementiert haben.
Die Funktion getUIDescriptor liefert einen UIDescriptor für eine einzelne, graphishe Representation des Dienstes oder null.
Dies ist normalerweise der Fall, da Represnetationen später angehängt werden und sogar selbst Dienste, welche nach kompaktieblen Diensten suchen, an die sie sich anhängen können, sein können.

Ein Dienst imnplementiert 2 Funktionen loadme() und saveme() welche den über Neustarts hinweg zu rettenden Teil des Zustandes in die/aus der Hashtable namens persistentState  holen.
Die Daten werden serialisiert und in einer Datei bin/dienstname.dat (falls der User diesen Ort nicht anders spezifiziert hat) gespeichert.

Die Logger-Klasse erlaubt es Debug-, Warnungs- Fehler-Meldungen in eine Fehler- und Debug -Log-Datei und die Console zu schreiben. Es wird in Zukunft erweitert, um log4j zu unterstützen.

Die comment und Creator -Strings werden in die entsprechenden Attribute zum ServiceEntry eingetragen.