Eclipse und RMI

Hallo!

Ich beschreibe mal die Vorgehensweise für Eclipse 3.X:
(Meine Umgebung Windows 2000, Java 5.0.1)

Installation:
Man lädt sich im Downloadbereich von http://www.genady.net/rmi/v16/index.html?/rmi/v16/main.html&MAIN16
die Zip-Datei, die den Latest Build enthält, herunter. Danach entpackt man diese Zip-Datei (Verzeichnisstruktur beibehalten) ins gewünschte Eclipse-Root ->(Z.Bsp.: C:\eclipse3.1M4)
Eclipse sollte während dessen NICHT laufen. Danach Eclipse starten und nun sollte man in der Java Perspektive ein neues "RMI"-Icon in der Toolbar sehen.

Nun kanns losgehen:

Wir legen ein neues Java Projekt mit dem Namen "rmitest" an.
Wie klicken mit der rechten Maustaste auf unser Projek und gehen im Kontextmenü auf Properties. Dort wählen wir den Punkt "Buildpath" und anschließend den Reiter "source" aus.
Unter "source" klicken wir nun unser Projekt an und klicken auf "addFolder" -> "newFolder".
Als Namen geben wir dort "src" ein. Die darauffolgende Meldung ob nun alle kompilierten Klassen automatisch in /bin landen sollen (output Folder) bestätigen wir mit "yes".
Wir verlassen die ProjectProperties mit "ok" und beginnen nun mit dem Erstellen der Klassen und Interfaces.

Wir erstellen unterhalb des Packages de.tutorials.service das Interface ITimeService (ja.... schon wieder wirds ein Zeitdienst sein... ;-) )

Code:
/*
 * Created on 16.01.2005@15:17:24
 *
 * TODO Licence info
 */
package de.tutorials.service;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.Date;

/**
 * @author Administrator
 *
 * TODO Explain me
 */
public interface ITimeService extends Remote{
    public Date getCurrentDate() throws RemoteException;
}

Danach erstellen wir im Package
de.tutorials.server die Klasse Server welches unser ITimeService Interface implementiert.
Code:
/*
 * Created on 16.01.2005@15:14:57
 *
 * TODO Licence info
 */
package de.tutorials.server;

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Date;

import de.tutorials.service.ITimeService;

/**
 * @author Administrator
 *
 * TODO Explain me
 */
public class Server implements ITimeService {

    public static void main(String[] args) {
        new Server().start();
    }

    /**
     * 
     */
    private void start() {
        try {
            ITimeService serviceStub = (ITimeService) UnicastRemoteObject
                    .exportObject(this);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind("timeservice", serviceStub);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /* (non-Javadoc)
     * @see de.tutorials.service.ITimeService#getCurrentDate()
     */
    public Date getCurrentDate() throws RemoteException {
        System.out.println("server received call @"
                + System.currentTimeMillis());
        return new Date();
    }
}

Nun kommt noch der Client den wir im package:
de.tutorials.client in Form der Klasse Client wie folgt realisieren:
Code:
/*
 * Created on 16.01.2005@15:26:18
 *
 * TODO Licence info
 */
package de.tutorials.client;

import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import de.tutorials.service.ITimeService;

/**
 * @author Administrator
 *
 * TODO Explain me
 */
public class Client {

    public static void main(String[] args) {
        try {
            Registry registry = LocateRegistry.getRegistry();
            ITimeService service = (ITimeService)registry.lookup("timeservice");
            System.out.println(service.getCurrentDate());
            
        } catch (AccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NotBoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Nun machen wir uns wieder an die Projekteinstellungen heran. Diesmal wählen wir innerhalb der ProjectProperties den Punkt "RMI-Compiler Properties" und wählen unter "Miscellaneous" die option "-keep" aus (damit können wir uns die generierten RMI-Stubs später ansehen). Wir verlassen wieder die ProjectProperties mit "ok" und klicken wieder mit der rechten Maustaste aufs Projekt und wählen "RMI" aus dem Kontextmenü aus. Dort aktivieren wir die automatische Stubgenerierung und rufen einmal "re-generate RMI-Stubs" auf. Danach klicken wir wieder mit der rechten Maustaste aufs Projekt und wählen im Kontextmenü "refresh" aus (oder wir drücken F5). Nun sieht man das im server Package eine neue Klasse dazu gekommen ist welche den Server-RMI-Stub realisiert.

Nun wollen wir das ganze auch mal laufen lassen.
Dazu wählen wir aus der Toolbar das RMI-Icon aus und sagen "start local Registry".
Nun klicken wir auf die Klasse Server und wählen aus dem Menü (geht auch anders ob so findet's jeder...) "Run" den Punkt "Run..." aus. Im folgenden Fenster wählen wir unter "Configurations" "RMI Application" aus und klicken auf "new". Im folgenden klicken wir auf der rechten Seite den Reiter RMI-Properties an und klicken in der Tabelle auf die "..." der java.rmi.server.codebase-Einstellung.Im folgenden Fenster sagen wir "Compute from Classpath" und bestätigen alle Dialoge mit "ok". Die Warnung über die nicht gesetzte java.security.policy ignorieren wir hier. Nun klicken wir auf "run" und schon läuft unser Server. Nun wollen wir auch noch den Client ausführbar machen. Dazu klicken wir mit der rechten Maustatse auf die Klasse "Client" und wählen "Run-As" -> "Java Application" aus.
In der Konsole solltet ihr nun das aktuelle Datum und die aktuelle Uhrzeit sehen.

HTH,
Gruß Tom
 
es ist nicht immer der Fall, dass ein beispiel auf anhieb tut was es soll. Dies mal hat es. Vielen Dank. Was mich noch allerdings irretirt, das hier wird kein Skeleton erzeug wird. Es fehlte nur eine kleinigkeit bei mir, aber es fehler. :( Noch mal Danke. ;-)
 
Hallo,

ich habe ein Problem. Das Beispiel von Tom funktioniert super, nur wenn der Client auf einem anderen Rechner ist geht nix. Muss man noch welche Einstellungen machen (außer dass man in registry.lookup noch den host uebergibt)? Kann mir jemand ein Beispiel geben wie es in Eclipse funktionieren sollte?

Danke im voraus

Vera
 
Hallo Leute,

der Thread ist zwar schon uralt, aber sowas von passend zu meinem Problem :)

Vielleicht kann mir jemand zu folgender Situation was sagen:

Ich habe in meinem Eclipse 3 Klassen und ein Interface:

rmiRemote (Interface, erweitert Remote)
rmiServer (implementiert rmiRemote, Runnable)
rmiClient (implementiert Runnable)
rmiMain (beinhaltet main-Methode, ruft die Threads rmiServer und rmiClient auf)

Dann starte ich mit

Code:
$ rmiregistry &

die Registry.

Danach starte ich über Eclipse die rmiMain und bekomme folgende Exceptions:

Code:
Client exception: java.rmi.NotBoundException: test
java.rmi.NotBoundException: test
	at sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:106)
	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
	at sun.rmi.transport.Transport$1.run(Transport.java:153)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
	at java.lang.Thread.run(Thread.java:595)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:343)
	at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
	at rmiClient.run(rmiClient.java:18)
	at java.lang.Thread.run(Thread.java:595)
Server error: 
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: rmiRemote
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:385)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
	at sun.rmi.transport.Transport$1.run(Transport.java:153)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
	at java.lang.Thread.run(Thread.java:595)
	at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
	at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
	at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:343)
	at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
	at rmiServer.run(rmiServer.java:25)
	at java.lang.Thread.run(Thread.java:595)
Caused by: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: rmiRemote
	at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
	at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:375)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:240)
	at sun.rmi.transport.Transport$1.run(Transport.java:153)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:466)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:707)
	... 1 more
Caused by: java.lang.ClassNotFoundException: rmiRemote
	at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:242)
	at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:707)
	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:651)
	at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:588)
	at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
	at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
	at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
	at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1500)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1463)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
	... 9 more
 
Hmm, hört für mich auf den ersten flüchtigen Blick danach an, das der Service nicht an RMIRegistry gebunden ist.

Meine Registry starte ich mit
Java:
LocateRegistry.createRegistry(port);

...und der letztendlichen Server dann mit:
Java:
Server ecms = new Server();
Naming.rebind(url, ecms);
 
Ich habe das RMI-Plugin mal installiert und auch alles so konfiguriert wie im ersten Thread angegeben, jetzt bekomme ich wenigstens eine definitive Fehlermeldung, nämlich die, dass der Server sein Objekt nicht registrieren kann weil die Verbindung abgelehnt wird.

Also ne andere Baustelle... ich verstehe es nur nicht, ich hab keine Firewall und kein SELinux oder sowas laufen... strange!
 

Neue Beiträge

Zurück