Ein kleines Beispiel
Das Interface des Servers
Der Fernaufruf basiert auf einem Interface, das Java.rmi.Remote erweitert. Der Server wird es implementieren und der Client aufrufen.import java.rmi.Remote; import java.rmi.RemoteException; public interface ServerInterface extends Remote { public void bitteMeldeDich() throws RemoteException; public int gibZahl() throws RemoteException; }Dieses Interface wird nun vom Server implementiert.
Der RMI-Server
import java.rmi.Naming; import java.rmi.RemoteException; import java.net.MalformedURLException; import java.rmi.registry.Registry; import java.rmi.registry.LocateRegistry; import java.rmi.server.UnicastRemoteObject; public class MeinServer extends UnicastRemoteObject implements ServerInterface { MeinServer() throws RemoteException { super(); } public static void main(String[] args) { try { LocateRegistry.createRegistry(Registry.REGISTRY_PORT); Naming.rebind("MeinServer", new MeinServer()); } catch (MalformedURLException ex) { System.out.println(ex.getMessage()); } catch (RemoteException ex) { System.out.println(ex.getMessage()); } } // Die Remote veröffentlichten Methoden public void bitteMeldeDich() throws RemoteException { System.out.println("Hier MeinServer!"); } public int gibZahl() throws RemoteException { System.out.println("Zahlenabwurf"); return 42; } }Der Server erzeugt eine Registry auf der Standard-Portnummer und bindet sich unter dem Namen MeinServer an diesen Port. Ansonsten fängt er nur die möglichen Exceptions. Die beiden Methoden des Interfaces werden implementiert.
Der Server wird von der Konsole einfach gestartet und blockiert, ohne einen Ton von sich zu geben, sofern alles in Ordnung ist.
Ein RMI-Client
Der Client sucht nun nach dem Namen MeinServer in der lokalen Registry. Dann ruft er die beiden Methoden des Servers nacheinander auf.import java.rmi.Naming; public class MeinClient { public static void main(String[] args) { String url = "rmi://127.0.0.1/MeinServer"; try { ServerInterface server = (ServerInterface) Naming.lookup(url); server.bitteMeldeDich(); int zahl = server.gibZahl(); System.out.println(zahl); } catch (Exception e) { System.err.println("Client Exception: " + e.toString()); e.printStackTrace(); } } }Der URL-String hat den allgemeinen Aufbau:
rmi://host:port/objektWie oben gesehen, kann der Port entfallen.
Vor dem Start des Clients muss der Server natürlich gestartet sein. Der Start des Clients bewirkt, dass der Server auf seiner Konsole anzeigt, dass die beiden Methoden aufgerufen wurden. Der Client zeigt eine 42 als Zeichen, dass er die Zahl vom Server erhalten hat.
Anmerkungen
Komplexe Objekte werden für die Übermittlung serialisiert. Entsprechend müssen übertragbare Objekte die Schnittstelle Serializable implementieren.Der Expert von Remote-Objekten wird durch die Klasse UnicastRemoteObject erreicht. Hier gibt es zwei Vorgehensweisen. Im hier vorgeführten Fall erweitert die Serverklasse die Klasse UnicastRemoteObject. Dann muss sie im Standardkonstruktor mit super() den Konstruktor der Basisklasse aufrufen. Diese muss dann auch die RemoteException werfen.
Alternativ kann auch das Server-Objekt mit der statischen Methode UnicastRemoteObject.exportObject exportiert werden. Der Rückgabewert ist ein Remote-Objekt-Stub, der als Parameter beim bind verwendet werden kann.
Wird die Registry über das Programm rmiregistry gestartet, muss dieser im Verzeichnis der Klassen des Servers gestartet werden oder durch die Option -Djava.rmi.server.codebase=file:/pfad auf dieses Verzeichnis verweisen.