# RMI und class incompatible



## heidiweber (1. Jan 2007)

Hallo

ich probiere mich seit ein paar Tagen an RMI. Aber ich bekomme (am Client) die folgende Fehlermeldung, sobald ich auf den Server zugreife:

Exception occured: java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
        java.io.InvalidClassException: de.rmiserver.classes.MyRMIImpl_Stub; local class incompatible: stream classdesc serialVersionUID = 7414297561264089241, local class serialVersionUID = -3774921611068175672
BUILD SUCCESSFUL (total time: 0 seconds)

Der Server läuft in Eclipse und ist auch gestartet. Wenn ich dann in Eclipse den Client starte, funktioniert alles. Starte ich den Client aber z.B. von Netbeans aus (auch auf dem selben Rechner) oder direkt auf der Konsole, kommt die obige Fehlermeldung.

Hier mein Server-Code:


```
public class MyRMIServer
{
		/*** Hier wird der Server gestartet ***/
        public static void main(String[] argv)
                {
                System.setSecurityManager(new RMISecurityManager());
                try
                        {
                        MyRMIImpl implementation = new MyRMIImpl("MyRMIImplInstance");
                        }
                catch (Exception e)
                        {
                        System.out.println("Exception occurred: " + e);
                        }
                }
}
```

Das Interface:


```
public interface RMIInterface  extends java.rmi.Remote 
{
        public java.util.Date getDate() throws RemoteException;
        
        public java.util.Date getName() throws RemoteException;
        
        public String getHelloMessage(String name) throws RemoteException;

}
```

Die Methoden am Server:


```
public class MyRMIImpl extends UnicastRemoteObject implements RMIInterface
{

	
        public MyRMIImpl(String name) throws RemoteException
                {
                super();
                try
                        {
                        Naming.rebind(name, this);
                        System.out.println("Server gestartet.");
                        }
                catch(Exception e)
                        {
                        System.out.println("Exception occurred: " + e);
                        }
                }
        public java.util.Date getDate()
                {
                	return new java.util.Date();
                }
        
        
        public java.util.Date getName()
        {
        	return new java.util.Date();
        }
        
        public String getHelloMessage(String name) 
		{
		return "Hallo " + name;
		}       
}
```



Die Stubs-Datei:


```
public class MyRMIImpl_Stub extends RemoteStub implements de.rmiserver.service.RMIInterface {

private static Object ops[] = null;
private static Class remoteClass = null;

static {
	try {
		remoteClass = Class.forName("de.rmiserver.classes.MyRMIImpl");
	} catch (ClassNotFoundException ex) {
	}
		try {
			ops = new Method[]{
				Class.forName("de.rmiserver.service.RMIInterface").getMethod("getDate", new Class[]{}),
				Class.forName("de.rmiserver.service.RMIInterface").getMethod("getHelloMessage", new Class[]{java.lang.String.class}),
				Class.forName("de.rmiserver.service.RMIInterface").getMethod("getName", new Class[]{})
			};
		} catch (NoSuchMethodException ex) {
			throw new RuntimeException("Stub is out of date");
		} catch (ClassNotFoundException ex2) {
			throw new RuntimeException("Unexpected ClassNotFoundException");
		}
}

public MyRMIImpl_Stub(RemoteRef ref) throws java.rmi.RemoteException {
	super(ref);
}

public MyRMIImpl_Stub() throws java.rmi.RemoteException {
	super();
}

public java.util.Date getDate() throws java.rmi.RemoteException{
		try {
			return (java.util.Date)ref.invoke(
				this,(Method)ops[0], new Object[]{}, -1017285815713287420L);
		} catch (java.rmi.RemoteException ex) {
			throw ex;
		} catch (Exception ex) {
			throw new UnexpectedException("Exception invoking method getDate",ex);
		}
}

public java.lang.String getHelloMessage(java.lang.String p0) throws java.rmi.RemoteException{
		try {
			return (java.lang.String)ref.invoke(
				this,(Method)ops[1], new Object[]{p0}, 6857304438814468432L);
		} catch (java.rmi.RemoteException ex) {
			throw ex;
		} catch (Exception ex) {
			throw new UnexpectedException("Exception invoking method getHelloMessage",ex);
		}
}

public java.util.Date getName() throws java.rmi.RemoteException{
		try {
			return (java.util.Date)ref.invoke(
				this,(Method)ops[2], new Object[]{}, -6849492820806235926L);
		} catch (java.rmi.RemoteException ex) {
			throw ex;
		} catch (Exception ex) {
			throw new UnexpectedException("Exception invoking method getName",ex);
		}
}

}
```




Hier der Client:


```
public class RMIClient {

    public static void main(String[] argv)
    {

    String serverName = "192.168.0.2";
    
    try
            {
                            //bind server object to object in client
            RMIInterface myServerObject = (RMIInterface) Naming.lookup("rmi://"+serverName+"/MyRMIImplInstance");

                            //invoke method on server object
            Date d = myServerObject.getDate();
            System.out.println("Date on server is " + d);
            }
    catch(Exception e)
            {
            System.out.println("Exception occured: " + e);
            System.exit(0);
            }
    System.out.println("RMI connection successful");
    }
}
```

Am Client ist auch noch das Interface und die selbe STUBS-Datei, wie am Server, eingebunden.

Folgende security.policy ist noch am Server eingebunden:

grant {
permission java.net.SocketPermission "192.168.0.7:1099", "connect, resolve";
permission java.net.SocketPermission "192.168.0.7:1024-", "connect, resolve";
permission java.net.SocketPermission "192.168.0.7:1024-", "accept, resolve";

permission java.net.SocketPermission "localhost:1099", "connect, resolve";
permission java.net.SocketPermission "localhost:1024-", "connect, resolve";
permission java.net.SocketPermission "localhost:1024-", "accept, resolve";

permission java.security.AllPermission;

//permission java.net.SocketPermission "localhost:1099", "connect, resolve";
//permission java.net.SocketPermission "localhost:1024-", "connect, resolve";
//permission java.net.SocketPermission "localhost:1024-", "accept, resolve";
};


An was könnte das liegen? Bei Google und hier im Forum habe ich leider auch nichts dazu gefunden?
Vielen Dank
cu
Heidi


----------



## Guest (1. Jan 2007)

serialVersionUID fehlt
	
	
	
	





```
public class MyRMIImpl extends UnicastRemoteObject implements RMIInterface 
{
   private static final long serialVersionUID = ...

   ...
```
und ich gehe davon aus, dass du die stubs nicht von Hand schreibst.


----------



## heidiweber (1. Jan 2007)

Hallo

ich komme leider nicht weiter. Man braucht jetzt noch eine serialVersionUID ? Lese ich jetzt zum ersten mal (habe ich noch nicht bei sun unter rmi gelesen. Naja ok. Nur wie kann/muss man die generieren? Man braucht dazu serialver. Nur das Programm kann nicht gefunden werden, obwohl das Programm vorhanden ist und der CLASSPATH auch passt? Gibt es dazu ein Tutorial oder wie muss man das machen?

Gebe ich ein von den beiden serialVersionUID an, die bei mir in der Fehlermeldung stehen, kommt beim Compilieren die Fehlermeldung:



> public class MyRMIImpl extends UnicastRemoteObject implements RMIInterface
> {
> private static final long serialVersionUID = 3774921611068175672;
> 
> ...



The literal 3774921611068175672 of type int is out of range

Ich habe auch gelesen, dass man irgendeine Nummer vergeben kann, z.B.:

   private static final long serialVersionUID = 1;

Probiere ich das, kommt aber wieder die im ersten Posting gezeigte Fehlermeldung.

Kann/darf man irgendeine Nummer vergeben?


Die Stub-Dateien generiert das RMI-Plugin von Eclipse. Ist das OK?


Müssen auf dem Server und dem Client die selbe Java-Version installiert sein? Ich habe gelesen, dass das auch zu dieser Fehlermeldung kommen kann? Ist bei mir nicht der Fall. Aber das kann doch nicht sein. Oder?

Vielen Dank für die Hilfe
cu
Heidi


----------



## Guest (1. Jan 2007)

Long-Literale werden mit einem L hintendran gekennzeichnet.
z.B.
	
	
	
	





```
private static final long serialVersionUID = 3774921611068175672L;
```
Wenn du es schon in Eclipse machst, dann lass dir dieserialVersionUID von Eclipse
erstellen. Klicke dazu auf das Warnungsicon links vom Klassennamen und bestätige
"Add generated serial version ID"

Probleme bei unterschiedlichen JRE Versionen kriegst du dann, wenn du die
Stubklassen nicht abwärtskompatibel kompilierst. Das RMI-Plugin kenne ich 
nicht, kann dazu nichs sagen, nehme aber an, dass es einfach nur rmic -keep
aufruft.


----------



## heidiweber (1. Jan 2007)

Hallo

wie kann man die serialVersionUID in Eclipse generieren lassen? Bei mir ist leider kein Warnicon. 

Vielen Dank 
cu
Heidi


----------



## Guest (1. Jan 2007)

Setze den Cursor auf den Klassennamen und drücke mal Ctrl-1
Es sollte so aussehen


----------



## heidiweber (1. Jan 2007)

Vielen Dank für deine Geduld. Aber es kommt nicht mit CTRL-1 das was soll, sondern nur "Rename for File". 

Hast du dazu vielleicht ein Plugin eingebunden?  Muss man erst eine Option setzen?

cu
Heidi


----------



## Guest (1. Jan 2007)

Ich habe hier Eclipse 3.2.x. Du findest die Einstellungen unter 
Window->Preferences->Java->Compiler->Errors/Warnings->"Potential programming problems"
bzw. in den Einstellungen des aktuellen Projekts, wenn du die Workspaceeinstellungen
modifiziert hast.


----------



## heidiweber (1. Jan 2007)

Hallo

ich arbeite mit dem RAD 6 (Eclipse von IBM). Da ist dieses Feature noch nicht dabei. 
Ich habe aber jetzt Eclipse 3.2 installiert, die benötigte Klasse und das Interface (aber nicht die STUBS-Datei) in ein neues Projekt eingebunden. Jetzt kann ich die serialVersionUID  (es kommt auch eine Warnmeldung). Diese generierte ID habe ich jetzt in mein "Hauptprojekt" im RAD in die Klasse kopiert. Ist das OK? Oder darf man das nicht machen? Jetzt hat die Klasse ja eine ID. 

Doch leider kommt immer noch die Fehlermeldung vom Client aus.

Ich schnalls echt bald nicht mehr? Was soll ich noch machen? 

VIelen Dank für deine Geduld

cu
Heidi


----------



## heidiweber (1. Jan 2007)

Hallo

jetzt habe ich den Client auf einem anderen Rechner ausprobiert. Und da kommt jetzt die Fehlermeldung, dass er keinen Connect bekommt. In der Policy Datei am Server ist aber:


permission java.net.SocketPermission "192.168.0.7:1099", "connect, resolve"; 
permission java.net.SocketPermission "192.168.0.7:1024-", "connect, resolve"; 
permission java.net.SocketPermission "192.168.0.7:1024-", "accept, resolve"; 

permission java.net.SocketPermission "localhost:1099", "connect, resolve"; 
permission java.net.SocketPermission "localhost:1024-", "connect, resolve"; 
permission java.net.SocketPermission "localhost:1024-", "accept, resolve"; 

permission java.security.AllPermission; 


Der Rechner des Clients hat die 192.168.0.7. Ich habe gelesen, dass der Client auch eine Policy-Datei braucht. Kann ich da die gleiche nehmen bzw. langt das:

permission java.security.AllPermission; 


Nur wie binde ich die Datei am Client ein? Brauche ich noch irgendwo einen Aufruf des SecurityManagers am Server bzw. am Client? Ist der Beispielcode vom Client korrekt?

Kann sich die Policy-Datei irgendwo im Dateisystem befinden oder muss die im "Arbeitsordner" sein?

Einen schönen Abend und vielen Dank für die Hilfe

cu
Heidi


----------



## Guest (2. Jan 2007)

OK, ich weiss, wie frustierend sowas ist. 
Wenn du den SecurityManager verwendest, musst du auch beim Start 
die Policydatei angeben. Es kann die gleiche sein, wie auf dem Server.


----------



## heidiweber (3. Jan 2007)

Vielen Dank Gast,

leider hat alles nix geholfen. Ich bekomms nicht gebacken. Komme erst nächste Woche wieder zum "herumspielen". Werde mich dann bestimmt nochmals melden müssen

cu
Heidi


----------

