blog.wlami.com

Virtuelles Zuhause von Wladislaw Mitzel

Hello World mit Java RMI

Im Rahmen eines Projekts im Studium habe ich mich mit Java RMI beschäftigt. Zusammengefasst ist dies eine Technologie, um die Kommunikation von Java-Objekten über das Netzwerk zu ermöglichen. Im folgenden soll ein kurzes Beispiel die Benutzung erläutern.

Zunächst definieren wir eine Schnittstelle, die unser Diensterbringer auf dem entfernten Server erfüllen soll:

1
2
3
4
public interface ITimeService extends Remote {
  //Wir wollen eine Methode haben, um die Serverzeit zu ermitteln.
  public String getTime() throws RemoteException;
}

An dieser Stelle ist es wichtig, dass das Interface das Marker-Interface Remote verwendet und unsere Methode eine RemoteException schmeißen können muss. Andernfalls gibt es Probleme beim Ausführen.

Nun implementieren wir unser Interface:

1
2
3
4
5
6
7
public class TimeService implements ITimeService {
  @Override
  public String getTime() {
    //Wir geben die aktuelle Zeit als String zurück
    return (new Date()).toString();
  }
}

Wir haben nun eine schöne Plain-Java Implementierung, die bisher jedoch wenig mit RMI zu tun haben. Als nächstes müssen wir deswegen diesen Service bei einer Registry anmelden. Dazu kommt hier zunächst etwas Hintergrundwissen, wie RMI funktioniert. Es gibt eine Registry. Diese enthält Informationen über alle, per RMI angebotenen, Dienste. Wenn nun ein Client diese Dienste verwenden will, stellt er eine Anfrage an die Registry und bekommt eine Implementierung für das gewünschte Interface.

Als nächstes erstellen wir eine Klasse, die die Anmeldung des Services bei einer neu erstellten Registry erledigt.

1
2
3
4
5
6
7
8
9
10
11
public class RmiServer {
  public static void main(String[] args) throws RemoteException {
    LocateRegistry.createRegistry(Registry.REGISTRY_PORT); //Wir erstellen eine neue Registry und verwenden dabei den default RMI-Registry-Port
    TimeService timeService = new TimeService();           //Wir erstellen eine Instanz der Schnittstellen-Implementierung
    ITimeService iTimeService = (ITimeService)UnicastRemoteObject.exportObject(timeService, 0); //Mit diesem Schritt sorgen wir dafür, dass Objekte für den Remote-Zugriff erstellt werden
    RemoteServer.setLog(System.out);                       //Dieser Schritt ist optional und sorgt dafür, dass unsere Ausgaben auf der Konsole landen
    Registry registry = LocateRegistry.getRegistry();      //Wir holen uns einen Verweis auf die Registry
    registry.rebind("ITimeService", iTimeService);         //Und nun registrieren wir unsere Implementierung in der Registry. Wir verwenden hier rebind: Wenn es den Service bereits gibt, wird er durch diese Version ersetzt.
    System.out.println("ITimeService angemeldet");         //Zuletzt schreiben wir auf der Console, dass unser Service bei RMI angemeldet wurde.
  }
}

Damit hätten wir den Server-Part bereits erledigt. Sobald der RmiServer gestartet wurde, lauscht er auf dem angegebenen Port auf Client-Anfragen.

Jetzt kommt die Client-Implementierung.

1
2
3
4
5
6
7
8
public class TimeConsumer {
  public static void main(String[] args) throws RemoteException, NotBoundException {
    Registry registry = LocateRegistry.getRegistry("rmi://wlami.com");
    ITimeService iTimeService = (ITimeService) registry.lookup("ITimeService");
    String value =  iTimeService.getTime();
    System.out.println("Remote-Zeit: " +  value);
  }
}

In Zeile 3 holen wir uns eine Referenz auf die Registry. Die Registry befindet sich auf einem entfernten Server. Wir können neben dem Host auch einen Port angeben. Danach holen wir uns in Zeile 4 nun die Schnittstellen-Implementierung. Dabei handelt es sich in Wirklichkeit um einen Proxy, der die Methodenaufrufe über das Netzwerk an den Server weiterleitet. Der String muss hier mit dem auf dem Server registriertem Namen für den Service übereinstimmen. In Zeile 5 folgt auch schon die eigentliche Benutzung unseres Remote Services. Im Hintergrund wird der Aufruf magisch übers Netzwerk an die Implementierung auf dem Server weitergeleitet. Zuletzt geben wir das Ergebnis auf der Konsole aus.

Wie ihr seht, erlaubt RMI auf einfachem Wege Dienste auf einem Server bereitzustellen, die dann remote verwendet werden können. Verwendet man Interfaces für die Definition der Services, so wie ich es in diesem Beispiel gemacht habe, ist es auch möglich die Implementierung auf dem Server durch eine andere zu ersetzen, ohne dass der Client das merkt.

Kommentieren

Dieses Blog verwendet statische Kommentare. Kommentare werden also per Mail an mich geschickt und erscheinen anschließend im Blog. Eure E-Mail-Adresse wird nicht veröffentlicht.

Kommentar schreiben