Im folgenden Tutorial ist eine ‘minimale’ Version für RMI unter Java angegeben:
In Eclipse brauchen wir die folgenden drei einfache Java Projekte. Es ist seit Java 5 kein rmic mehr nötig um die Stubs zu generieren. Außerdem werden wir anstatt die Server Implementierung von UnicastRemoteObject abzuleiten, einen dynamischen Proxy erzeugen der dies für uns erledigt. Dadurch wird der auf RMI abhängige Code kleiner.
Dieses Projekt dient nur um das eigentliche Interface zwischen den zwei anderen Projekten zu sharen. Da ja in einer Realen Anwendung Client & Server getrennt entwickelt werden.
package de.inforw.rmi.basic.remote;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface IHelloWorld extends Remote {
public String sayHello(String inValue) throws RemoteException;
}
Solltet ihr im Server später eine Ähnliche Fehlermeldung wie die untenstehende bekommen, dann habt ihr vermutlich das “throws RemoteException” vergessen.
java.rmi.server.ExportException: remote object implements illegal remote interface; nested exception is: java.lang.IllegalArgumentException: illegal remote method encountered: public abstract java.lang.Object de.inforw.rmi.basic.remote.IRecorderController.registerRecorder(java.lang.Object) at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:171) at java.rmi.server.UnicastRemoteObject.exportObject(UnicastRemoteObject.java:293) at java.rmi.server.UnicastRemoteObject.exportObject(UnicastRemoteObject.java:235) at de.inforw.rmi.basic.remote.RmiServer.main(RmiServer.java:17) Caused by: java.lang.IllegalArgumentException: illegal remote method encountered: public abstract java.lang.Object de.inforw.rmi.basic.remote.IHelloWorld2.registerRecorder(java.lang.Object) at sun.rmi.server.Util.checkMethod(Util.java:244) at sun.rmi.server.Util.getRemoteInterfaces(Util.java:223) at sun.rmi.server.Util.getRemoteInterfaces(Util.java:193) at sun.rmi.server.Util.createProxy(Util.java:126) at sun.rmi.server.UnicastServerRef.exportObject(UnicastServerRef.java:169)
Nun wollen wir den Server erstellen. Dazu brauchen wir als erstes einmal eine Implementierung unseres IHelloWorld interfaces. Da das Interface ja im remote Projekt liegt, müssen wir als erstes in den Eigenschaften des Server Projektes unter: Java Build Path/Projects das remote Projekt referenzieren. Eclipse erweitert nun für uns im Hintergrund den classpath des Server Projektes um das remote Projekt. Somit können wir das Interface nutzen und implementieren:
package de.inforw.rmi.basic.server.impl;
import de.inforw.rmi.basic.remote.IHelloWorld;
public class HelloWorldImpl implements IHelloWorld {
public String sayHello(String inValue) {
System.out.println("An cliend called me ... invalue = " + inValue );
return "inValue was : "+inValue;
}
}
Außer der eigentlichen Implementierung müssen wir natürlich auch noch den Server starten und die Implementierung veröffentlichen. Hierzu brauchen wir eine main() die wir also starten können:
package de.inforw.rmi.basic.server;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import de.inforw.rmi.basic.remote.IHelloWorld;
import de.inforw.rmi.basic.server.impl.HelloWorldImpl;
public class ServerMain {
public static void main(String[] args) {
try {
// instanciate implementation
IHelloWorld impl=new HelloWorldImpl();
// Create a UnicastRemoteObject Proxy
IHelloWorld stub=(IHelloWorld) UnicastRemoteObject.exportObject(impl,0);
// Create a local running RMI Registry
Registry reg = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
// (re)bind the implementation under the Name "helloworld"
reg.rebind("helloworld", stub);
System.out.println( "Press any key & Return to stop the Server" );
System.in.read();
System.out.println("Server shuting down.");
System.exit(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Nachdem wir nun den Server implementiert haben, müssen wir nur noch von der Client Seite das Objekt holen und aufrufen.
package de.inforw.rmi.basic.client;
import java.rmi.Naming;
import de.inforw.rmi.basic.remote.IHelloWorld;
public class ClientMain {
public static void main(String[] args) {
try {
// lookup the remote object, it's requested from the local naming service
// use "rmi://bitnoise.de/helloworld" to get it from remote machine.
IHelloWorld hw=(IHelloWorld) Naming.lookup("helloworld");
// Call the remote method.
System.out.println( "calling sayHello ... returned :\t" + hw.sayHello("moin") );
} catch(Exception e) {
e.printStackTrace();
}
}
}
Obriger Code sollte einfach und schnell genutzt werden können. Wer in Eclipse ein SVN Plugin installiert hat, kann die drei Projekte ganz einfach aus dem Repository laden:
svn://bitnoise.de/public/www.inforw.de/tuorials/rmi.basic