Ik moet binnenkort een presentatie doen over Java RMI.
Om RMI wat beter te proberen begrijpen probeer ik het voorbeeld uit de
RMI Trail van de Java Tutorial te laten werken.
Dit lukt echter niet naar wens:
Ik zal even kort de situatie uitleggen (je kunt ook de pagina's over dit voorbeeld
raadplegen op http://java.sun.com/docs/books/tutorial/rmi/ ):
Het voorbeeld bestaat dus uit een server en een client gedeelte.
- Op de server wordt een remote object ComputeEngine aangemaakt dat de interface Compute implementeert. Deze interface vereist dat het object een methode executeTask(Task t) bezit. De client kan dan deze methode oproepen en een Task meegeven die uitgevoerd moet worden.
- De client contacteert het remote ComputeEngine object dmv de registry,
maakt een instantie van de klasse ComputePi aan die de interface Task implementeert, en roept executeTask() van het remote ComputeEngine object aan met als parameter het ComputeEngine object.
De situatie is als volgt:
- De class files van de interfaces Task en Compute staan zowel aan client als aan serverkant lokaal in het classpath.
- De class files van ComputeEngine staan natuurlijk in het classpath aan serverkant. De class files van de bijhorende stub en skeleton van ComputeEngine staan op de webserver aan de serverkant, zodat ze via het netwerk beschikbaar zijn aan de client.
- De class files van ComputePi en Pi staan natuurlijk in het classpath aan de clientzijde + de class file van Pi staat ook op de webserver aan clientzijde zodat de server de klasse Pi kan ophalen als die de klasse nodig heeft.
Dit is de configuratie die met de stappen in de tutorial wordt bekomen,
en het is ook de configuratie die strookt met mijn idee van de werking van RMI.
Volgens mij zou het volgende moeten gebeuren als de client uitgevoerd wordt:
- De client contacteert de registry en verkrijgt zo 'link' naar het remote ComputeEngine object. Die 'link' bevat het adres van de webserver waar de client de klassen die 'm nodig heeft kan downloaden.
- De client download vervolgens de stub file van de ComputeEngine klasse van de webserver van de remote server.
- Via deze stub roept de client de methode executeTask() van ComputeEngine op,
met als parameter een ComputePi object.
- RMI transporteert het ComputePi object naar de server.
- Bij het verwerken van de execute() methode ComputePi komt de server de Pi klasse tegen, dus downloadt de server deze klasse van de webserver van de client.
- Het resultaat wordt van de server naar de client getransporteert en daar weergegeven.
Ik krijg het voorbeeld echter niet werkend met de configuratie zoals hierboven.
Bij het uitvoeren van de client wordt de volgende exceptie gegenereerd:
Na wat research blijkt dat de client ComputeEngine_Stub.class aanvraagt bij zijn EIGEN
webserver ipv de webserver van de remote server.
Concreet: de client vraagt om ComputeEngine_Stub.class bij de URL die opgegeven werd bij java.rmi.server.codebase bij het starten van de client.
Maar waarom zoekt de client deze stub file in zijn eigen publieke klassen?
Ik kan het voorbeeld WEL laten werken als ik ComputeEngine_Stub.class in het classpath van de client zet. Dan werkt het voorbeeld perfect.
Dit druist echter volledig in tegen mijn begrip van RMI:
het is toch de bedoeling dat de client alleen weet heeft van de Compute interface,
en dat RMI zorgt voor het transport van de stub die communicatie met de implementatie van Compute mogelijk maakt?
Maw: RMI zou er toch moeten voor zorgen dat ComputeEngine_Stub.class bij de client terecht komt?
Begrijp ik de werking van RMI niet goed en moet ik die stub file toch zelf aan de client kant zetten? Maar hoe past dit dan in het concept van RMI, waar zit de fout in mijn redenering?
Nog wat aanvullende informatie:
- Het gebruikte commando om de server op te starten (rmiregistry draait dan al):
(hierbij is http://localhost/server_classes de URL naar de publieke klassen van de server.)
- Het gebruikte commando om de client op te starten:
(hierbij is http://localhost/client_classes de URL naar de publieke klassen van de client.)
- De beide policy files zijn zeker in orde.
De kernvraag van mijn probleem is dus:
Waarom zoekt de client de stub file van het remote object in zijn eigen publieke klassen en niet in de publieke klassen van de remote server, wat een stuk logischer zou zijn imo...
Ik hoop dat er hier iemand is die ervaring heeft met RMI, want ik ben hier nu al een dag of 2 mee bezig en het ziet er nier naar uit dat ik ooit zelf de oplossing zal vinden... (en eerlijk gezegd wordt ik er lichtjes
van.)
Om RMI wat beter te proberen begrijpen probeer ik het voorbeeld uit de
RMI Trail van de Java Tutorial te laten werken.
Dit lukt echter niet naar wens:
Ik zal even kort de situatie uitleggen (je kunt ook de pagina's over dit voorbeeld
raadplegen op http://java.sun.com/docs/books/tutorial/rmi/ ):
Het voorbeeld bestaat dus uit een server en een client gedeelte.
- Op de server wordt een remote object ComputeEngine aangemaakt dat de interface Compute implementeert. Deze interface vereist dat het object een methode executeTask(Task t) bezit. De client kan dan deze methode oproepen en een Task meegeven die uitgevoerd moet worden.
- De client contacteert het remote ComputeEngine object dmv de registry,
maakt een instantie van de klasse ComputePi aan die de interface Task implementeert, en roept executeTask() van het remote ComputeEngine object aan met als parameter het ComputeEngine object.
De situatie is als volgt:
- De class files van de interfaces Task en Compute staan zowel aan client als aan serverkant lokaal in het classpath.
- De class files van ComputeEngine staan natuurlijk in het classpath aan serverkant. De class files van de bijhorende stub en skeleton van ComputeEngine staan op de webserver aan de serverkant, zodat ze via het netwerk beschikbaar zijn aan de client.
- De class files van ComputePi en Pi staan natuurlijk in het classpath aan de clientzijde + de class file van Pi staat ook op de webserver aan clientzijde zodat de server de klasse Pi kan ophalen als die de klasse nodig heeft.
Dit is de configuratie die met de stappen in de tutorial wordt bekomen,
en het is ook de configuratie die strookt met mijn idee van de werking van RMI.
Volgens mij zou het volgende moeten gebeuren als de client uitgevoerd wordt:
- De client contacteert de registry en verkrijgt zo 'link' naar het remote ComputeEngine object. Die 'link' bevat het adres van de webserver waar de client de klassen die 'm nodig heeft kan downloaden.
- De client download vervolgens de stub file van de ComputeEngine klasse van de webserver van de remote server.
- Via deze stub roept de client de methode executeTask() van ComputeEngine op,
met als parameter een ComputePi object.
- RMI transporteert het ComputePi object naar de server.
- Bij het verwerken van de execute() methode ComputePi komt de server de Pi klasse tegen, dus downloadt de server deze klasse van de webserver van de client.
- Het resultaat wordt van de server naar de client getransporteert en daar weergegeven.
Ik krijg het voorbeeld echter niet werkend met de configuratie zoals hierboven.
Bij het uitvoeren van de client wordt de volgende exceptie gegenereerd:
code:
1
| java.lang.ClassNotFoundException: engine.ComputeEngine_Stub |
Na wat research blijkt dat de client ComputeEngine_Stub.class aanvraagt bij zijn EIGEN
webserver ipv de webserver van de remote server.
Concreet: de client vraagt om ComputeEngine_Stub.class bij de URL die opgegeven werd bij java.rmi.server.codebase bij het starten van de client.
Maar waarom zoekt de client deze stub file in zijn eigen publieke klassen?
Ik kan het voorbeeld WEL laten werken als ik ComputeEngine_Stub.class in het classpath van de client zet. Dan werkt het voorbeeld perfect.
Dit druist echter volledig in tegen mijn begrip van RMI:
het is toch de bedoeling dat de client alleen weet heeft van de Compute interface,
en dat RMI zorgt voor het transport van de stub die communicatie met de implementatie van Compute mogelijk maakt?
Maw: RMI zou er toch moeten voor zorgen dat ComputeEngine_Stub.class bij de client terecht komt?
Begrijp ik de werking van RMI niet goed en moet ik die stub file toch zelf aan de client kant zetten? Maar hoe past dit dan in het concept van RMI, waar zit de fout in mijn redenering?
Nog wat aanvullende informatie:
- Het gebruikte commando om de server op te starten (rmiregistry draait dan al):
code:
1
2
3
| java -classpath .;classes\compute.jar
-Djava.rmi.server.codebase=http://localhost/server_classes/
-Djava.security.policy=java.policy engine.ComputeEngine //localhost/Compute |
(hierbij is http://localhost/server_classes de URL naar de publieke klassen van de server.)
- Het gebruikte commando om de client op te starten:
code:
1
2
3
| java -classpath .;classes\compute.jar
-Djava.rmi.server.codebase=http://localhost/client_classes/
-Djava.security.policy=java.policy client.ComputePi localhost 20 |
(hierbij is http://localhost/client_classes de URL naar de publieke klassen van de client.)
- De beide policy files zijn zeker in orde.
De kernvraag van mijn probleem is dus:
Waarom zoekt de client de stub file van het remote object in zijn eigen publieke klassen en niet in de publieke klassen van de remote server, wat een stuk logischer zou zijn imo...
Ik hoop dat er hier iemand is die ervaring heeft met RMI, want ik ben hier nu al een dag of 2 mee bezig en het ziet er nier naar uit dat ik ooit zelf de oplossing zal vinden... (en eerlijk gezegd wordt ik er lichtjes