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
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.
Beispiel mit Objekten
Komplexe Objekte werden für die Übermittlung serialisiert. Entsprechend müssen übertragbare Objekte die Schnittstelle Serializable implementieren.import java.io.Serializable; public class Person implements Serializable { private int alter = 0; int getAlter() { return alter; } public void altere() { alter++; } }Das Interface muss für Client und Server gleich sein. Der Server implementiert es, der Client verwendet es, um die Server-Methoden aufzurufen.
import java.rmi.Remote; import java.rmi.RemoteException; public interface RmiInterface extends Remote { static final String servername = "RmiServer"; public String vollerName(String vorname, String nachname) throws RemoteException; public Person altere(Person person) throws RemoteException; }Der RMI-Server implementiert das Interface. Er bindet sich über die lokale Registry an den Namen.
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; public class RmiServer extends UnicastRemoteObject implements RmiInterface { RmiServer() throws RemoteException { super(); } public static void main(String[] args) throws RemoteException, MalformedURLException { LocateRegistry.createRegistry(Registry.REGISTRY_PORT); Naming.rebind(RmiInterface.servername, new RmiServer()); } @Override public String vollerName(String vorname, String nachname) throws RemoteException { return vorname + " " + nachname; } @Override public Person altere(Person person) throws RemoteException { person.altere(); return person; } }Der Client ruft den Server auf. Dazu sucht er auf dem Zielrechner den RMI-Server mit dem passenden Namen und erhält ein RmiInterface, über das er die Methoden aufruft, als seien sie lokal.
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; public class RmiClient { public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException { String url = "rmi://127.0.0.1/" + RmiInterface.servername; RmiInterface server = (RmiInterface) Naming.lookup(url); String name = server.vollerName("Otto", "Muster"); Person person = new Person(); Person altePerson = server.altere(person); System.out.println(name + " " + altePerson.getAlter()); } }