RMI und Eclipse

Status
Nicht offen für weitere Antworten.

apfelsine

Aktives Mitglied
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:

Code:
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 :D
 

apfelsine

Aktives Mitglied
Also hier ist der Code

IRmiFunctions

Code:
import java.rmi.Remote;
import java.rmi.RemoteException;

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

ClsMain

Code:
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

Code:
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

Top Contributor
Code:
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();
		}
	}
}
Code:
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;
   }
      
}
Code:
import java.rmi.*;

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

foobar

Top Contributor
Hier ist der dazugehörige Client:
Code:
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();
		} 
	}

}
 

Grizzly

Top Contributor
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

Aktives Mitglied
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

Top Contributor
@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:
Code:
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
Ansonsten guck dir mal das Beispiel von oben an.
 

foobar

Top Contributor
Warum benutzt du nicht meinen Server? Der funktioniert wunderbar.
Vielleicht liegt es daran, daß du kein Protocol mit angegeben hast:
Code:
Naming.rebind("rmi://rmidemo", myImpl);
Aber eigentlich braucht man, daß auf der Serverseite nicht.
 

Grizzly

Top Contributor
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:
Code:
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
Ansonsten guck dir mal das Beispiel von oben an.

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

JavaHulk

Mitglied
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

Top Contributor
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

Top Contributor
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
Code:
<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

Mitglied
@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

Mitglied
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:
Code:
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:
Code:
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

Mitglied
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.io_ObjectStreamClass.getDeclaredSUID(Unknown Source)
at java.io_ObjectStreamClass.access$400(Unknown Source)
at java.io_ObjectStreamClass$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.io_ObjectStreamClass.<init>(Unknown Source)
at java.io_ObjectStreamClass.lookup(Unknown Source)
at java.io_ObjectStreamClass.initNonProxy(Unknown Source)
at java.io_ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io_ObjectInputStream.readClassDesc(Unknown Source)
at java.io_ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io_ObjectInputStream.readObject0(Unknown Source)
at java.io_ObjectInputStream.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

Top Contributor
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

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



Code:
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:

Code:
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 :(
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen


Oben