RMI - UnmarshalException

k0n

Grünschnabel
Hi
wir haben in der Schule gerade mit dem Thema RMI begonnen. Nun schreibe ich gerade die erste Hausübung mit RMI, jedoch bekomme ich immer beim Aufruf des Client Programmes eine Exception. Ich durchsuche jetzt schon seit 5 Stunden das Internet und hab noch immer keine passende Lösung gefunden -.-

Hier der Code der Klassen am RMI Server: (Ich weiß, manche Namen wurden etwas unglücklich gewählt ;) )
DBZugriff.java :
Code:
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


public class DBZugriff extends UnicastRemoteObject implements DBZugriffMethoden{

	public DBZugriff() throws RemoteException{

	}

	private Connection verbindung;

	public Connection connection() throws RemoteException{
		return verbindung;
	}

	public boolean getConnection() throws RemoteException{
		try {
			Class.forName("org.postgresql.Driver");
		} catch (ClassNotFoundException e) {
			System.out.println("Treiber nicht gefunden!");
			System.exit(1);
		}

		try {
			verbindung = DriverManager.getConnection(
					"jdbc:postgresql://localhost:5432/Pizzaservice",
					"postgres", "admin");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		return true;
	}
}

DBZugriffMethoden :
Code:
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.sql.Connection;


public interface DBZugriffMethoden extends Remote{

	public Connection connection() throws RemoteException;
	public boolean getConnection() throws RemoteException;
}

PizzaServiceRegisterMethods :
Code:
import java.rmi.Naming;


public class PizzaServiceRegisterMethods {

	public static void main(String args[]){
		try {
			DBZugriff acct;

			String name = "DBZugriff";

			acct = new DBZugriff();

			Naming.rebind(name, acct);

			System.out.println("Objekte registriert");
		} catch (Exception e) {
			System.err.println("Ausnahme:" + e.getMessage());
			// e.printStackTrace();
		}
	}
}

Die Klasse beim Client Programm:
Code:
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class GUI {

	public static void main(String args[]) {

		try {
			DBZugriff verbindung;

			verbindung = (DBZugriff) Naming.lookup("rmi://localhost/DBZugriff");
			verbindung.getConnection();

Als erstes führe ich in der Konsole (im bin Verzeichniss des Servers) den Befehl "rmic -keep -d . -v1.2 DBZugriff" aus.
Danach starte ich im selben verzeichniss die rmiregistry mit "start rmiregistry" und für die PizzaServiceRegister Klasse aus...
Als letztes hab ich dann die GUI Klasse beim Client Programm ausgeführt.

Beim letzten Punkt bekomm ich dann immer die gleiche Exception:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: DBZugriff_Stub (no security manager: RMI class loader disabled)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at java.rmi.Naming.lookup(Naming.java:84)
at GUI.main(GUI.java:20)
Caused by: java.lang.ClassNotFoundException: DBZugriff_Stub (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:375)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
at java.io_ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
at java.io_ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
at java.io_ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
at java.io_ObjectInputStream.readObject0(ObjectInputStream.java:1329)
at java.io_ObjectInputStream.readObject(ObjectInputStream.java:351)
... 3 more

Da unser Lehrer dieses Thema nur sehr schlecht erklärt hat, habe ich noch ziemlich wenig Ahnung von RMI...
Ich hoffe mal, dass mir jemand von euch helfen kann...

Schon mal danke im Vorraus ;)
Lg K0n
 
Howdie.

Meine RMI-Erfahrungen sind schon ein bisschen her, aber ich versuch dir mal aus dem Kopf zu helfen. Ich übernehme also keine Garantien für fehlerfreie Syntax oder Lauffähigkeit des Codes.

Wie die nested Exception sagt, fehlt vermutlich der RMI Security Manager. D.h., deine Software weiß nicht, welche entfernte Klassen sie laden darf oder nicht.
Erstelle dir eine Datei (z.B. rmi.policy) in deinem Projekt-Ordner - oder auch als temporäre Datei, wie auch immer du willst. Als Inhalt fügst du
Code:
grant {
permission java.security.AllPermission;
};
ein. Ist zwar nicht besonders sicher, aber als Anfang sollte es genügen.

Dann habe ich es immer so gemacht, dass ich mir eine Security Manager-Klasse geschrieben habe:
Java:
public class RMIsecurityManager extends SecurityManager{
	public RMIsecurityManager(){
		System.setProperty("java.security.policy", PFAD_ZU_DEINER_POLICY_DATEI);
	}
}

Nun musst du den Security Manager vor dem Lookup auf die entfernte Klasse noch überprüfen und setzen:
Java:
. . .
if(System.getSecurityManager() == null) {
    System.setSecurityManager(new RMIsecurityManager());
}

// hier nun Registry- und Lookup-Operationen

Gruß und viel Erfolg,
miffi
 
Vielen Dank für die rasche Hilfe! Ich werds gleich ausprobieren ob das hilft.

Irgendwo hab ich gelesen, dass die Stubs eventuell nicht richtig erstellt werden... Könnte das das Problem sein?


Edit:
So, nun hab ich den Securitymanager hinzugefügt, dennnoch treten Exceptions auf:
Code:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
	java.lang.ClassNotFoundException: DBZugriff_Stub
	at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
	at java.rmi.Naming.lookup(Naming.java:84)
	at GUI.main(GUI.java:22)
Caused by: java.lang.ClassNotFoundException: DBZugriff_Stub
	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:247)
	at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:434)
	at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
	at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
	at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
	at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
	... 3 more

Lg
 
Zuletzt bearbeitet:
Howdie.

Ja, dein StackTrace sagt ja bereits aus, dass er die Klasse DBZugriff_Stub nicht finden kann...
Da RMI die Stubs aber selbst erstellt (du brauchst ja nur das Interface und das zugehörige Remote-Objekt), wird der Fehler vermutlich irgendeine falsche Konfiguration sein.

Das Problem ist, dass die Exception nicht sehr aufschlussreich ist. Wenn die Klasse nicht gefunden wurde, kann das ein Fehler beim Server (bind), Client (lookup) oder der Kommunikation selbst sein.

Hast du vielleicht irgendetwas an der Package-Struktur verändert?

Gruß
miffi
 
So, jetzt weiß ich warum dem so war...
Das Programm war auf 2 Projekte aufgeteilt. Eins fürn Server und eins fürn Client. Da uns der Lehrer das ganze so schlecht erklärte, dachte ich mir, dass ich die erstellten Stubs nur beim Server benötige... Dem war leider nicht so...

Ich hab einfach die erstellten Stub Dateien in das Client-Projekt kopiert und schon hats funktioniert :)
 
Zurück