# RMI und Eclipse



## apfelsine (10. Sep 2004)

Hallo,
ich komme jetzt das erste mal in das Vergnügen RMI zu benötigen
und bin da absolut neu. 
Ich benutze Eclipse 2.1 und die JavaEngine 1.42
Jetzt hab ich grade ein kleines Programm erstellt um überhaupt erstmal
zu sehen wie das funktioniert. Wie das so ist, es funktioniert nicht.
Leider weiß ich nicht, ob bei meinem Compiler noch ein plugin fehlt
oder ob man dafür extra eines braucht.
Ich habe nur die folgende Fehlermeldung:


```
Fehler:java.rmi.StubNotFoundException: Stub class not found: ClsMain_Stub; nested exception is: 
	java.lang.ClassNotFoundException: ClsMain_Stub
```

ClsMain ist die Klasse, die das Remote-Interface implementiert

weiß da jemand was?

Gruß
apfelsine

BTW: Ich find das Forum hier prima. Sehr angenehm


----------



## apfelsine (10. Sep 2004)

Also hier ist der Code

IRmiFunctions


```
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IRmiFunctions extends Remote
{
	public boolean Connect() throws RemoteException;
}
```

ClsMain


```
import java.rmi.server.UnicastRemoteObject; 
import java.rmi.RemoteException;
import java.sql.*;
public class ClsMain extends UnicastRemoteObject implements IRmiFunctions
{

	
	public ClsMain() throws RemoteException
	{
		super();
	}


	
	public boolean Connect() 
	{
		boolean bOk=false;
		System.out.println("test");
		return bOk;
	}
		
}
```

ClsServer


```
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.RMISecurityManager;

public class ClsServer
{
	public ClsMain oRmi;
	public static void main(String[] args)
	{
		ClsServer server= new ClsServer();
		server.register();
	}
	
	void register()
	{
		String sUd = "";
		String sCb = "";
		String sSp = "";
		 
		//create
		try
		{
			oRmi= new ClsMain();
		}
		catch(RemoteException e)
		{ 
			System.err.println("Fehler:"+e);
			return;
		}
		
		/***********************
		 * Security configuration
		 */
		
		sUd=System.getProperty("user.dir");
		sCb=System.getProperty( "java.rmi.serer.codebase");
		
		if (sCb==null)
		{
			System.out.println("Setting java.rmi.server.codebase to"+sUd);
			//Setting java.rmi.server.codebase to sUd
			System.setProperty( "java.rmi.server.codebase", "file:"+sUd+"/");
			sCb=System.getProperty("java.rmi.server.codebase");
			System.out.println(sCb);
		}
		
		sSp=System.getProperty("java.security.policy");
		if (sSp==null)
		{
			System.out.println("Setting 'java.security.policy' to");
			System.setProperty( "java.security.policy",sUd+"/rmipolicy");
			sSp=System.getProperty("java.security.policy");
			System.out.println(sSp);
		}
		
		/**
		 * security manager
		 */
		if(System.getSecurityManager()==null)
		{
			System.setSecurityManager( new RMISecurityManager ());
		}
		
		try
		{
			Naming.rebind( "remote",oRmi);
		}
		catch(RemoteException e)
		{
			System.err.println("Fehler");
			return;
		}
		catch(MalformedURLException e)
		{
			System.err.println("Fehler");
			return;			
		}
		catch(Exception e)
		{
			System.err.println("Fehler");
			return;
		}
		
		System.out.println("Method registered");
	}
}
```

apfelsine


----------



## foobar (10. Sep 2004)

```
import java.net.MalformedURLException;
import java.rmi.*;
import java.rmi.registry.*;
public class ClsServer
{
	public static void main(String[] args)
	{
		try
		{
			LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
			IRmiFunctions oRmi = (IRmiFunctions) new ClsMain();
			Naming.rebind("rmitest", oRmi);
			System.out.println("server running...");
		}
		catch (RemoteException e)
		{
			e.printStackTrace();
		} catch (MalformedURLException e)
		{
			e.printStackTrace();
		}
	}
}
```


```
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class ClsMain extends UnicastRemoteObject implements IRmiFunctions
{
   
   public ClsMain() throws RemoteException
   {
	  super();
   }
   
   public boolean Connect() throws RemoteException
   {
	  boolean bOk=false;
	  System.out.println("test");
	  return bOk;
   }
      
}
```


```
import java.rmi.*;

public interface IRmiFunctions extends Remote
{
   public boolean Connect() throws RemoteException;
}
```
[


----------



## foobar (10. Sep 2004)

Hier ist der dazugehörige Client:

```
public class ClsClient
{
	public static void main(String[] args)
	{
		try
		{
			IRmiFunctions remote =  (IRmiFunctions) Naming.lookup("rmi://127.0.0.1/rmitest");
			remote.Connect();
		}
		catch (MalformedURLException e)
		{
			e.printStackTrace();
		}
		catch (RemoteException e)
		{
			e.printStackTrace();
		}
		catch (NotBoundException e)
		{
			e.printStackTrace();
		} 
	}

}
```


----------



## apfelsine (10. Sep 2004)

picture removed


----------



## Grizzly (11. Sep 2004)

BTW: Gibt es eigentlich irgendeine Möglichkeit, Eclipse beizubringen, dass es den Stub generieren, beim Programmstart die RMI Registry starten und beim Beenden wieder stoppen soll?


----------



## apfelsine (11. Sep 2004)

Ich wollt mich nochmal bedanken.
Es funktioniert jetzt. 
Nachdem das Plugin in Eclipse lief gings auf einmal


Jetzt muß ich "nurnoch" rausfinden wo die policy
geändert wird.
 :### 

gruß
apfelsine


----------



## foobar (11. Sep 2004)

@Grizzyl es gibt ein RMI-Plugin für Eclipse, damit kannst du dir die Stubs und Skeletons, automatisch nach jeder Kompilierung, generieren lassen. Die Rmiregistry kannst du hiermit automatisch starten:

```
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
```
Ansonsten guck dir mal das Beispiel von oben an.


----------



## apfelsine (11. Sep 2004)

Hat sich alles erledigt.
Der Mist funktioniert jetzt endlich :!:


----------



## foobar (11. Sep 2004)

Warum benutzt du nicht meinen Server? Der funktioniert wunderbar.
Vielleicht liegt es daran, daß du kein Protocol mit angegeben hast:

```
Naming.rebind("rmi://rmidemo", myImpl);
```
Aber eigentlich braucht man, daß auf der Serverseite nicht.


----------



## apfelsine (11. Sep 2004)

Das hab ich ja erst getan. Aber ich dachte der SecurityManager ist für irgendwas gut oder?


----------



## Grizzly (11. Sep 2004)

foobar hat gesagt.:
			
		

> @Grizzyl es gibt ein RMI-Plugin für Eclipse, damit kannst du dir die Stubs und Skeletons, automatisch nach jeder Kompilierung, generieren lassen. Die Rmiregistry kannst du hiermit automatisch starten:
> 
> ```
> LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
> ...



Cool  , werde ich mir mal morgen im Verlauf des Tages reinziehen.


----------



## JavaHulk (19. Okt 2004)

ich denke mir, emeine frage passt hier ganz gut rein. hoffe mal sie ist nicht total dämlich  :? 

ich hab nen problem den server zum laufen zu kriegen. benutze eclipse3.0
ich denke ich habe eigentlich an alles gedacht...
die rmi registry läuft im hintergrund, ich kann den stub in eclipse anlegen, bloß beim starten des servers findet er den stub einfach nicht:

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
	java.lang.ClassNotFoundException: Serverlein_Stub


....
zusatzinfo
wenn ich per eingabeaufforderung manuell mit rmic die dateien kompilieren will gibts immer den fehler, dass er die datei nicht findet obwohl ich im richtigen verzeichnis bin.

was muss ich noch machen damit er den stub endlich findet  :bahnhof: 
was könnte ich nicht beachtet haben?


----------



## foobar (19. Okt 2004)

> was könnte ich nicht beachtet haben?


Vielleicht rufst du rmic aus dem falschen Verzeichnis aus auf. Du mußt immer vom obersten Verzeichnis aus rmic aufrufen und nicht innerhalb des Packages.  



> wenn ich per eingabeaufforderung manuell mit rmic die dateien kompilieren will gibts immer den fehler, dass er die datei nicht findet obwohl ich im richtigen verzeichnis bin.


Hast du die Klassen auch vorher mit javac kompiliert?


----------



## foobar (19. Okt 2004)

Am einfachsten ist es die Klassen mit Ant zu compilieren. Hier ist ein Buildfile mit dem du die Stubs und Skeletons erstellen kannst. Nachdem du Ant installiert hast genügt ein Aufruf von ant im selben Verzeichnis in dem das Buildfile liegt.

build.xml

```
<project name="myrmic"  default="compile"  basedir="../">
  	<property name="classes" value="classes" /> 
  	<property name="src" value="src" /> 
  	<property name="remoteclass" value="testcenter.rmi.TestCenterImpl" /> 
  	<property name="classpath" value="/opt/tomcat/common/lib/servlet-api.jar:/opt/tomcat/common/lib/jsp-api.jar"/> 
  

	<target name="init">
   		<delete dir="${classes}"/>
	   <mkdir dir="${classes}"/>
	</target>   
	
	<target name="compile" depends="init">
	    <javac srcdir="${src}" destdir="${classes}" classpath="${classpath}"/>
	   <rmic classname="${remoteclass}" base="${classes}"/>
	</target>   
</project>
```
Die Properties mußt du entsprechend an dein Projekt anpassen.


----------



## JavaHulk (19. Okt 2004)

@foobar: erstmal danke für die schnelle antwort!

das ding ist, dass ich das ganze auch ohne Ant zum laufen bringen muss...

wenn ich nun meine dateien mit javac kompilieren will, bekomme ich fehler, weil objekte anderer klassen innerhalb der gerade zu kompilierenden klassen angelegt werden, die zwar im gleichen ordner liegen, aber anscheinend nicht bekannt sind. dabei funktionieren diese klassen innerhalb von eclipse ohne probleme, wenn ich sie starte(sofern sie alleine funktionieren würden) und den server weglasse.  auch andere javaprogramme ohne rmi laufen wie gewohnt.
da komm ich irgendwie nicht ganz mit  ???:L 

ich habe nun zum test einen mini-server(3 klassen, main, serverimpl+stub und interface) geschrieben. auch beim kompilieren dessen dateien mit javac bekomme ich fehler, weil er zum beispiel das interface als nicht bekannt angibt.

ist das für kenner vielleicht ein hinweis auf den fehler, den ich nicht finde?!


----------



## JavaHulk (21. Okt 2004)

so, der server läuft nun, ich hab die class dtaeien im gleichen ordner gehabt, ganz schön dumme sache gewesen!
nun habe ich das problem, dass ich nen securitymanager im client definieren muss, allerdings die anleitungen im netz nicht so wirklich umsetzen kann...

derzeit siehts so bei meinem client aus in sachen securitiy:

```
String codebase = "c:/eclipse/workspace/reversiclient/";
		System.setProperty( "java.rmi.client.codebase", codebase );
		System.setProperty( "java.security.policy", codebase+"rmi.policy" );
		System.setSecurityManager( new RMISecurityManager() );
```

die rmi.policy liegt natürlich in dem verzeichnis des Strings codebase(s.o.).
gefüllt habe ich sie lediglich mit folgendem inhalt:

```
grant
{
  permission java.security.AllPermission;
};
```

trotzdem gibts noch folgende fehlermeldung, dass er den stub nicht findet, der eigentlich da ist...

ich würd gerne wissen, ob das security zeug so richtig definiert ist und ob jemand nen grund weiß warum der stub nicht gefunden wird...


----------



## JavaHulk (21. Okt 2004)

stub findet er nun anscheinend, aber nun kommt dies:
(absturz in dieser zeile: ServerInterface server = (ServerInterface)Naming.lookup( url ))

java.lang.NoSuchMethodError: stub class initialization failed
	at ReversiServerImpl_Stub.<clinit>(Unknown Source)
	at sun.misc.Unsafe.ensureClassInitialized(Native Method)
	at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(Unknown Source)
	at sun.reflect.ReflectionFactory.newFieldAccessor(Unknown Source)
	at java.lang.reflect.Field.acquireFieldAccessor(Unknown Source)
	at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
	at java.lang.reflect.Field.getLong(Unknown Source)
	at java.ibjectStreamClass.getDeclaredSUID(Unknown Source)
	at java.ibjectStreamClass.access$400(Unknown Source)
	at java.ibjectStreamClass$3.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.ibjectStreamClass.<init>(Unknown Source)
	at java.ibjectStreamClass.lookup(Unknown Source)
	at java.ibjectStreamClass.initNonProxy(Unknown Source)
	at java.ibjectInputStream.readNonProxyDesc(Unknown Source)
	at java.ibjectInputStream.readClassDesc(Unknown Source)
	at java.ibjectInputStream.readOrdinaryObject(Unknown Source)
	at java.ibjectInputStream.readObject0(Unknown Source)
	at java.ibjectInputStream.readObject(Unknown Source)
	at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
	at java.rmi.Naming.lookup(Unknown Source)
	at ReversiClientStart.main(ReversiClientStart.java:25)
Exception in thread "main" 




hat das was mit der security zu tun?


----------



## foobar (21. Okt 2004)

Es ist vollkommen ausreichend den Securitymanager zu setzen, die anderen Properties sind nicht umbedingt notwendig.



> (absturz in dieser zeile: ServerInterface server = (ServerInterface)Naming.lookup( url ))


Poste doch mal etwas Code. Wie sieht denn deine RemoteImpl-Klasse aus?


----------



## JavaHulk (22. Okt 2004)

das ganze soll nen reversi über rmi sein...




```
public class ReversiServerImpl extends UnicastRemoteObject implements ServerInterface {

    //Variablen Deklaration
	private Vector Clients;
	private Game[] gamez;
	private String[] stringz;
	private int playercounter, gamenumber;
	private Game game;
	
	//Konstruktor
	public ReversiServerImpl() throws RemoteException{
		super();
		playercounter = 0;
		gamenumber = 0;
		Clients = new Vector();
		gamez = new Game[50];

	}
	
	public void login(ReversiClient client)throws RemoteException{
			Clients.add(client);
			playercounter++;
			System.out.println("Ein neuer Spieler angemeldet");
			check4game();
	}
	public void check4game()throws RemoteException{
		if(gamenumber==50){
			System.out.println("Server full");
			return;
		}
		if(playercounter == 2){
gamez[gamenumber] = new Game((ReversiClient)Clients.elementAt(0),
										 (ReversiClient)Clients.elementAt(1));
			gamenumber++;
		                playercounter = 0;		
			Clients.remove(0);
			Clients.remove(1);
		}
	}
			
		
	public void passzug(int x, int y, int lastTurnPlayer)throws RemoteException{
		game.giveTurnInfo(x,y, lastTurnPlayer);
	}
```

und hier die Clientanmeldung, also die Main des Clients:


```
public class ReversiClientStart {

	//Mainmethode
	public static void main(String[] args){
		
		ReversiClientStart clstart = new ReversiClientStart();
	try{
		//security wird gesetzt, sonst leider Fehlermeldung, dass keine Security da ist.
		clstart.setSecurity();
		//Verbindunsaufbau zum Server und erstellen eines Serverobjektes,
		//das über Naming.lookup und der übergebenen url als Verbindung zum
		//richtigen Server dient
		String host = args[0];
		int port = ServerInterface.PORT_REVERSISERVICE;
		String srv  = ServerInterface.NAME_REVERSISERVICE;
		String url = "rmi://" + host + ":" + port + "/" + srv;
		ServerInterface server = (ServerInterface)Naming.lookup( url ); 
		System.out.println("Connected.");
		//schließlich starten des Clients über RMI
		ReversiClient spieler = new ReversiClient(server);
		} 
	//bei Fehlern des Aufbaus starten des Clients ohne RMI bzw. Server
	catch (Exception e){
		System.out.println(e);
		System.out.println("Fehler beim Verbindungsaufbau, Reversi startet ohne RMI");
		ReversiClient spieler = new ReversiClient();
		}
	
	}
	//Methode um die Security zu setzen und einen SecurityManagaer anzulegen
	public void setSecurity(){
		//hier sollte der Pfad zur rmi.policy-datei, die im sich im Projektornder
		//befindet richtig angegeben werden. 
		String codebase = "c:/eclipse/workspace/reversiclient/";
		System.setProperty( "java.rmi.client.codebase", codebase );
		System.setProperty( "java.security.policy", codebase+"rmi.policy" );
		System.setSecurityManager( new RMISecurityManager() );
		System.out.println("Security set.");
	}
}
```

dazu gehören noch einige andere klassen. wie gesagt sind die stubs alle da wo sie sein sollen. ich habe vorher schon mal was in rmi gemacht, allerdings ging das ohne security manager und hat nicht annähernd so viele fehler gegeben, die nicht am quelltext lagen


----------

