RMI−Server und −Client

Werbung
RMI−Server und −Client
•
•
•
RMI−Server
–
Remote−Objekt(e) bereitstellen
–
Wurzel−Objekt in Verzeichnisdienst anmelden
RMI−Client
–
Wurzel−Objekt in entfernter JVM mittels
Verzeichnisdienst finden
–
Methoden von Remote−Objekten aufrufen
Ein Java−Programm kann gleichzeitig RMI−Client und
RMI−Server sein.
Web−Anwendungen mit Java
551
Beispiel: E−Shop
•
Was passiert, wenn Kunde Artikel kauft?
–
Lieferung der Ware zum Kunden (Logistik)
–
Bezahlen (Rechnung, Lastschrift, Kreditkarte usw.)
•
Typische Aufgaben eines Warenwirtschaftssystems
•
Im E−Shop das Rad nicht neu erfinden, sondern
Anbindung an WWS schaffen
–
WWS präsentiert sich als Remote−Objekt.
–
E−Shop faßt Bestelldaten zu einem Objekt zusammen.
–
E−Shop schickt Bestelldaten−Objekt per RMI an WWS.
–
Lieferstatus vom WWS holen
Web−Anwendungen mit Java
552
Lösungsidee
Remote−
Interface
E−Shop
WWS
Stub
Remote−
Objekt
Kasse
Bestellung
Web−Anwendungen mit Java
Bestellung
553
Lösungsskizze: Remote−Interface
•
E−Shop »sieht« WWS als Remote−Interface
de.rainer_klute.rmi.WWS.
–
Interface erbt von java.rmi.Remote.
–
Spezifiziert die Methoden des WWS, die ein RMI−Client
aufrufen kann.
–
Alle Methoden eines Remote−Objekts können eine
RemoteException werfen.
–
Netzprobleme
–
Server−Probleme
Web−Anwendungen mit Java
554
Lösungsskizze: Remote−Objekt
•
Remote−Objekt implementiert Remote−Interface.
–
Hier: WWSImpl implementiert WWS.
•
Klasse von UnicastRemoteObject ableiten (oder
weitere Möglichkeiten nutzen)
•
Beispiel:
–
import java.rmi.*;
import java.rmi.server.*;
public class WWSImpl extends
UnicastRemoteObject implements WWS
•
Konstruktor des Remote−Objekts macht es im
Netz erreichbar.
Web−Anwendungen mit Java
555
Lösungsskizze: RMI−Server
•
Erzeugt Instanz des Remote−Objekts
–
•
•
Remote−Objekt wird im Netz erreichbar.
Meldet Instanz bei RMI−Registrierung an
–
Ordnet Remote−Objekt einen Namen zu.
–
Remote−Objekt wird im Netz adressierbar.
RMI−Server oft als main()−Methode des Remote−
Objekts realisiert.
Web−Anwendungen mit Java
556
Lösungsskizze: RMI−Client
•
Fordert Remote−Objekt von RMI−Registrierung an.
–
•
Adressierung über den vom RMI−Server festgelegten
Namen
Ruft Methoden des Remote−Objekts auf.
Web−Anwendungen mit Java
557
Beispiel: Remote−Interface
package de.rainer_klute.rmi;
import java.rmi.*;
public interface WWS extends Remote
{
/** <p>Liefert den Status des WWS.</p> */
public String getStatus()
throws RemoteException;
/** <p>Übermittelt eine Bestellung an das
* Warenwirtschaftssystem.</p> */
public String bestellen(Bestellung bestellung)
throws RemoteException;
}
Web−Anwendungen mit Java
558
Beispiel: Remote−Objekt
package de.rainer_klute.rmi.server;
import
import
import
import
java.net.*;
java.rmi.*;
java.rmi.server.*;
de.rainer_klute.rmi.*;
public class WWSImpl extends UnicastRemoteObject
implements WWS
{
/**
* <p>Konstruktor hier nur zur Illustration:
* Konstruktor der Oberklasse
* {@link UnicastRemoteObject} macht Objekt netzweit
* erreichbar.</p>
*/
public WWSImpl() throws RemoteException
{
super();
}
Web−Anwendungen mit Java
559
Beispiel: Remote−Objekt
/**
* <p>Liefert den Status des WWS.</p>
*/
public String getStatus() throws RemoteException
{
System.out.println("getStatus()");
return "All subsystems running.";
}
/**
* <p>Übermittelt eine Bestellung an das
* Warenwirtschaftssystem.</p>
*/
public String bestellen(Bestellung bestellung)
throws RemoteException
{
String s = "Order received: " + bestellung;
System.out.println(s);
return s;
}
Web−Anwendungen mit Java
560
Beispiel: RMI−Server
/**
* <p>Startet den RMI−Server.</p>
*/
public static void main(String args[])
{
/* Security−Manager installieren */
if (System.getSecurityManager() == null)
System.setSecurityManager
(new RMISecurityManager());
try
{
/* Remote−Objekt erzeugen */
WWS wws = new WWSImpl();
Web−Anwendungen mit Java
561
Beispiel: RMI−Server
/* Remote−Objekt in RMI−Registry anmelden.
* Format des Namens: "//host/name" */
String wwsName = "//" +
InetAddress.getLocalHost().
getHostAddress() + "/WWS";
System.out.println
("Versuche, WWS als \"" + wwsName +
"\" zu registrieren.");
Naming.rebind(wwsName, wws);
System.out.println("Okay.");
}
}
}
catch (Exception e)
{
System.out.println
("Fehler: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
Web−Anwendungen mit Java
562
Beispiel: RMI−Client
package de.rainer_klute.rmi.client;
import java.net.*;
import java.rmi.*;
import de.rainer_klute.rmi.WWS;
public class WWSClient
{
public static void main(String args[])
{
/* Security−Manager installieren */
if (System.getSecurityManager() == null)
System.setSecurityManager
(new RMISecurityManager());
String remoteName = args[0];
Web−Anwendungen mit Java
563
Beispiel: RMI−Client
try
{
}
WWS wws = (WWS) Naming.lookup(remoteName);
String status = wws.getStatus();
System.out.println("WWS−Status: " + status);
Bestellung b = new BestellungImpl();
b.setKunde(1234);
Posten p = new PostenImpl();
p.setArtikel(4711);
p.setAnzahl(2);
b.addPosten(p);
p = new PostenImpl();
p.setArtikel(1000);
p.setAnzahl(1);
b.addPosten(p);
String s = wws.bestellen(b);
System.out.println("WWS−Nachricht: " + s);
Web−Anwendungen mit Java
564
Beispiel: RMI−Client
}
catch (Exception e)
{
System.out.println("Fehler: " +
e.getMessage());
e.printStackTrace();
}
}
Web−Anwendungen mit Java
565
RMI−Registrierung
•
Einfacher Verzeichnisdienst für RMI
•
Verwaltet Zuordnungen von Namen (Strings) zu
Remote−Objekten.
•
Notiert zu jedem Remote−Objekt, woher die Klasse
dieses Objekts stammt.
•
Namensformat:
//{hostname|ipaddress}[:port]/objectname
//rmi.rainer−klute.de/WWS
//127.0.0.1:1234/WWS
Web−Anwendungen mit Java
566
RMI−Registrierung
•
Starten der RMI−Registrierung:
–
CLASSPATH darf Anwendungsklassen nicht enthalten.
–
bash: (unset CLASSPATH; rmiregistry &)
–
csh: (unsetenv CLASSPATH; rmiregistry &)
Web−Anwendungen mit Java
567
Getrennte Entwicklung
•
RMI ermöglicht Trennung der Entwicklung von
Server und Client.
•
Beispiel: Web−Anwendung für Kunden einer
Versicherung
–
Kunde kann persönliche Daten aktualisieren.
–
Jeder Interessent kann »seinen« persönlichen Berater anhand
seiner eigenen Adresse ermitteln und kontaktieren.
–
Entwicklung der Web−Anwendung durch Internet−
Agentur
–
Versicherung macht Kundendaten und Vertriebsdaten der
Internet−Agentur nicht zugänglich.
–
Datenschutz, Betriebsgeheimnis
–
Host
Web−Anwendungen mit Java
568
Getrennte Entwicklung
Remote−
Interface
Host−
Daten
RMI−
Server
RMI−
Client
Web−
Oberfläche
–
Versicherung entwickelt RMI−Server mit Zugriff auf die
Host−Daten.
–
Internet−Agentur entwickelt RMI−Client und Web−
Oberfläche (HTML−Generierung mit JSP).
–
Klassen übersetzen
•
•
Gemeinsam genutzte Interfaces
–
de.rainer_klute.rmi.WWS
–
de.rainer_klute.rmi.Bestellung
–
de.rainer_klute.rmi.Posten
Server−Klasse:
–
•
de/rainer_klute/rmi/server/WWSImpl
Client−Klasse:
–
de/rainer_klute/rmi/client/WWSClient
–
de/rainer_klute/rmi/client/BestellungImpl
–
de/rainer_klute/rmi/client/PostenImpl
Web−Anwendungen mit Java
570
Klassen übersetzen
•
Übersetzung durchführen:
– mkdir classes
– javac −d classes src/de/rainer_klute/rmi/WWS.java
src/de/rainer_klute/rmi/Bestellung.java
src/de/rainer_klute/rmi/Posten.java
– javac −d classes
src/de/rainer_klute/rmi/server/WWSImpl.java
– javac −d classes
src/de/rainer_klute/rmi/client/WWSClient.java
src/de/rainer_klute/rmi/client/BestellungImpl.java
src/de/rainer_klute/rmi/client/PostenImpl.java
Web−Anwendungen mit Java
571
Stubs und Skeletons generieren
RMI−Server
RMI−Client
Stub
•
Stub
–
•
Skeleton
Repräsentiert das Remote−Objekt im Client.
Skeleton
–
Netzfähiges Gegenstück im Server
–
Leitet Zugriffe an Remote−Objekt weiter
Web−Anwendungen mit Java
572
Remote−
Objekt
Stubs und Skeletons generieren
•
RMI−Compiler rmic generiert Stubs und Skeletons
aus Remote−Klassen.
•
Beispiel:
–
rmic −classpath classes −d classes
de.rainer_klute.rmi.server.WWSImpl
–
Ergebnis: Klassen
de.rainer_klute.rmi.server.WWSImpl_Stub
de.rainer_klute.rmi.server.WWSImpl_Skel
Web−Anwendungen mit Java
573
JAR−Dateien erzeugen
•
RMI−Client und RMI−Server dürfen nicht den selben
Classpath nutzen.
–
•
Entspräche nicht dem Konzept der getrennten
Entwicklung.
Unterschiedliche JAR−Dateien mit Klassen für Client
und Server erzeugen
–
rmicommon.jar mit gemeinsam genutzten Interfaces:
WWS, Bestellung, Posten
–
rmiserver.jar mit Server−Klassen: WWSImpl,
WWSImpl_Stub, WWSImpl_Skel
–
rmiclient.jar mit Client−Klasse: WWSClient,
BestellungImpl, PostenImpl
Web−Anwendungen mit Java
574
Programme starten
•
RMI−Server:
– java −cp dist/lib/rmicommon.jar:dist/lib/rmiserver.jar
−Djava.rmi.server.codebase=file:///home/.../classes/
−Djava.rmi.server.hostname=mark
−Djava.security.policy=rmiPolicy
de.rainer_klute.rmi.server.WWSImpl
– Versuche, WWS als "//192.168.10.1/WWS" zu registrieren.
Okay.
•
RMI−Client:
– java −cp dist/lib/rmicommon.jar:dist/lib/rmiclient.jar
−Djava.security.policy=rmiPolicy
de.rainer_klute.rmi.client.WWSClient //mark/WWS
– WWS−Status: All subsystems running.
–
Server: getStatus()
Web−Anwendungen mit Java
575
Klassen laden mit RMI
•
•
Wesentlich für das korrekte Funktionieren von RMI ist
das Übertragen von Klassen.
–
RMI−Client benötigt die Stub−Klasse(n).
–
RMI−Server benötigt die Klassen der Objekte, die ihm der
RMI−Client überträgt.
Klassen sollten nicht im Classpath enthalten sein.
–
Getrennte Entwicklung von Client und Server
•
Anbieter des RMI−Servers muß Stub−Klasse(n) zum
Herunterladen verfügbar machen.
•
Property java.rmi.server.codebase teilt
mit, wo die Klassen liegen.
Web−Anwendungen mit Java
576
Risiken bei fremdem Code
•
Das Ausführen heruntergeladener Klassen ist ein
Sicherheitsrisiko.
•
Code kann beliebige Aktionen ausführen, zu denen
der Benutzer berechtigt ist.
–
Daten ausspionieren
–
Daten verändern
–
System schädigen
Web−Anwendungen mit Java
577
Sandkastenmodell
•
•
Java 1.0 und 1.1 unterstützen das Sandkasten−
Modell:
–
Java−Applets dürfen nichts  nur Anzeige im Browser.
–
Java−Applikationen dürfen alles.
Sandkasten−Modell unzureichend:
–
Applets benötigen ggf. Zugriff auf Systemressourcen.
–
–
Beispiel: Texteditor−Applet speichert Text in lokaler Datei.
Einschränkungen für Applikationen erforderlich
–
Beispiel: Vom RMI−Server geladene Klassen dürfen nur in das
Verzeichnis /tmp schreiben.
Web−Anwendungen mit Java
578
Sicherheit
•
Java 2 ermöglicht fein granulierte
Zugriffsberechtigungen.
•
Welche Klasse darf welche Aktion ausführen?
•
–
Von welchem Ort stammt diese Klasse (Codebase)?
–
Von welchem Hersteller stammt diese Klasse
(digitale Signatur)?
Policy−Datei legt Zugriffsberechtigungen fest.
–
•
Beispiel: Klassen von http://rmi.rainer−klute.de:1111/
dürfen in /tmp lesen und schreiben.
Security−Manager führt Zugriffskontrollen durch.
–
Beispiel: Berechtigungsprüfung beim Öffnen
der Datei /tmp/foo
Web−Anwendungen mit Java
579
Beispiel: Policy−Datei
keystore "${user.home}/.keystore", "JKS";
grant {
permission java.net.SocketPermission "*", "resolve";
permission java.net.SocketPermission "for.bar.de:1024−2000",
"connect, accept";
};
grant codeBase "http://rmi:1111/" {
permission java.io.FilePermission "<<ALL FILES>>", "read";
permission java.io.FilePermission "/tmp/−", "read, write";
};
grant signedBy "RainerKlute" {
permission java.security.AllPermission;
};
•
Erzeugen der Policy−Datei: Texteditor oder policytool
•
Verwenden der Policy−Datei mit
−Djava.security.policy=url
Web−Anwendungen mit Java
580
Sicherheitsprüfungen aktivieren
•
Java−Programme laufen normalerweise ohne
Security−Manager.
–
•
Alles ist erlaubt. Kompatibilität zu Java 1.0 und 1.1 ist
gewährleistet.
Standard−Security−Manager aktivieren
–
Beim Start des Java−Programms:
–
–
java −Djava.security.manager
−Djava.security.policy=policy−url MeineKlasse
Programmgesteuert:
if (System.getSecurityManager() == null)
Sicherheitsprüfungen durchführen
•
Viele Methoden der Java−Standardklassen führen
Sicherheitsprüfungen durch.
–
•
Vor einer potentiell gefährlichen Operation
Beispiel: Datei zum Lesen öffnen
– SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkRead(filename);
•
Klasse SecurityManager besitzt zahlreiche
checkXXX−Methoden:
– checkAccept, checkAccess, checkAwtEventQueueAccess, checkConnect,
Sicherheitsgrundeinstellungen
•
JDK−Installation gibt Sicherheitsgrundeinstellungen
vor.
–
•
Dateien in ${java.home}/jre/lib/security,
z.B. /opt/local/jdk1.3/jre/lib/security
Hauptdatei java.security
–
Hier nur einige Einstellungen zum Thema Policy
– # URLs von Policy−Dateien:
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
# −Djava.security.policy=someURL erlaubt?
policy.allowSystemProperty=true
Web−Anwendungen mit Java
583
Einstellungen in java.policy
•
Standarderweiterungen dürfen alles.
– grant codeBase "file:${java.home}/lib/ext/*" {
permission java.security.AllPermission;
};
•
Jeder Code darf den aktuellen Thread stoppen, auf
nichtprivilegierten Ports lauschen und Standard−
Properties lesen.
– grant {
permission java.lang.RuntimePermission "stopThread";
permission java.net.SocketPermission "localhost:1024−",
"listen";
permission java.util.PropertyPermission "java.version",
};
Klassen laden mit RMI
•
RMI−Classloader lädt Klassen nur dann, wenn ein
Security−Manager installiert ist.
–
RMI−Security−Manager in Client und Server installieren
– if (System.getSecurityManager() == null)
System.setSecurityManager
(new RMISecurityManager());
Web−Anwendungen mit Java
585
RMI−Server starten
•
RMI−Server starten (1. Versuch)
– java −cp dist/lib/rmiserver.jar:dist/lib/rmicommon.jar
de.rainer_klute.rmi.server.WWSImpl
•
Fehler:
– java.security.AccessControlException: access denied
(java.net.SocketPermission 127.0.0.1:1099
connect,resolve)
–
Security−Manager verbietet Verbindungsaufbau.
Web−Anwendungen mit Java
586
RMI−Server starten
•
RMI−Server registriert Wurzel−Objekt bei einer
RMI−Registrierung.
– Naming.rebind("//localhost/WWS", new WWSImpl());
•
•
Verbindung zur RMI−Registrierung aufbauen
–
Hier: localhost, Port 1099 (Voreinstellung)
–
Alternativer Port möglich: "//localhost:1234/WWS"
–
Alternativer Rechner möglich: "//other.host.de/WWS"
AccessControlException, weil RMI−Server keine
Netzverbindung zur RMI−Registrierung aufbauen kann
Web−Anwendungen mit Java
587
RMI−Server starten
•
Policy−Datei mit der benötigten Berechtigung erstellen
–
Mit Texteditor oder policytool
– grant {
permission java.net.SocketPermission
"localhost:1099", "connect";
};
•
RMI−Server starten (2. Versuch mit Policy−Datei)
– java −cp dist/lib/rmiserver.jar:dist/lib/rmicommon.jar
−Djava.security.policy=rmiServerPolicy
de.rainer_klute.rmi.server.WWSImpl
•
Fehler:
–
RMI−Server starten
•
RMI−Registrierung starten
– (unset CLASSPATH; rmiregistry &)
•
RMI−Server starten (3. Versuch mit laufender RMI−
Registrierung)
– java −cp dist/lib/rmiserver.jar:dist/lib/rmicommon.jar
−Djava.security.policy=rmiServerPolicy
de.rainer_klute.rmi.server.WWSImpl
•
Fehler
– java.rmi.ServerException: RemoteException occurred in
server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling
arguments; nested exception is:
java.lang.ClassNotFoundException:
de.rainer_klute.rmi.server.WWSImpl_Stub
Web−Anwendungen mit Java
589
RMI−Server starten
•
Fehlerursache finden
– java.rmi.ServerException: RemoteException occurred in
server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling
arguments; nested exception is:
java.lang.ClassNotFoundException:
de.rainer_klute.rmi.server.WWSImpl_Stub
...
at java.rmi.Naming.rebind
at de.rainer_klute.rmi.server.WWSImpl.main
–
RemoteException: Fehler nicht im RMI−Server,
sondern in einer Remote−Methode
–
ClassNotFoundException: Kommunikationspartner
kennt Klasse WWSImpl_Stub nicht.
–
Naming.rebind: Kommunikationspartner ist die
RMI−Registrierung.
Web−Anwendungen mit Java
590
Sag mir, wo die Klassen sind
•
RMI−Registrierung soll Instanz von WWSImpl_Stub
speichern und auf Anforderung an Clients ausliefern.
•
RMI−Registrierung benötigt die Klasse des Objekts.
•
Klasse nicht im Classpath enthalten.
–
•
•
RMI−Registrierung bewußt ohne Classpath gestartet
RMI−Server muß der Registrierung verraten, wo die
Klassen sind.
–
Property java.rmi.server.codebase
–
URL, z.B. file:///home/klute/classes/ oder
http://classes.rainer−klute.de:1111/
RMI−Partner muß Ort der Klassen verraten.
Web−Anwendungen mit Java
591
RMI−Registrierung
Name:
WWS
...
RMI−Registrierung
Objekt: Codebase: Server:
Stub http://cserver/dir/ rserver
...
...
...
RMI−Client
RMI−Server
Stub
Stub
http://cserver/dir/
java.rmi.server.codebase=
http://cserver/dir/
rserver
Class−Server
cserver
Web−Anwendungen mit Java
592
RMI−Server starten
•
RMI−Server starten (4. Versuch mit Codebase)
– java −cp dist/lib/rmiserver.jar:dist/lib/rmicommon.jar
−Djava.rmi.server.codebase=file:///home/klute/classes/
−Djava.security.policy=rmiServerPolicy
de.rainer_klute.rmi.server.WWSImpl
– Ausgabe:
Versuche, WWS als "//127.0.0.1/WWS" zu registrieren.
Okay.
•
Endlich Erfolg!
–
Für’s erste jedenfalls...
Web−Anwendungen mit Java
593
RMI−Client starten
•
RMI−Client starten (1. Versuch)
– java −cp dist/lib/rmiclient.jar:dist/lib/rmicommon.jar
de.rainer_klute.rmi.client.WWSClient //mark/WWS
– java.security.AccessControlException: access denied
(java.net.SocketPermission mark resolve)
•
Client benötigt das Recht, Host−Namen per DNS
aufzulösen, sprich: die IP−Adresse zu ermitteln.
•
Policy−Datei für Client anlegen
– grant {
permission java.net.SocketPermission "*", "resolve";
};
Web−Anwendungen mit Java
594
RMI−Client starten
•
RMI−Client starten (2. Versuch mit Policy)
– java −cp dist/lib/rmiclient.jar:dist/lib/rmicommon.jar
−Djava.security.policy=rmiClientPolicy
de.rainer_klute.rmi.client.WWSClient //mark/WWS
– java.security.AccessControlException: access denied
(java.net.SocketPermission 127.0.0.2:1099
connect,resolve)
•
Client benötigt das Recht, auf die RMI−Registry
zuzugreifen. Hier: Port 1099 auf beliebigem Host
– grant {
};
–
permission java.net.SocketPermission "*", "resolve";
permission java.net.SocketPermission "*:1099", "connect";
Ggf. Hosts einschränken oder Ports erweitern
Web−Anwendungen mit Java
595
RMI−Client starten
•
RMI−Client starten (3. Versuch)
– java −cp dist/lib/rmiclient.jar:dist/lib/rmicommon.jar
−Djava.security.policy=rmiClientPolicy
de.rainer_klute.rmi.client.WWSClient //mark/WWS
– java.lang.ClassNotFoundException:
java.security.AccessControlException: access denied
(java.io.FilePermission /home/klute/classes/− read)
•
Client lernt aus Stub, wo die zugehörige Klasse ist.
•
Client benötigt das Recht, auf das Klassenverzeichnis
zuzugreifen.
– grant {
};
permission java.net.SocketPermission "*", "resolve";
permission java.net.SocketPermission "*:1099", "connect";
permission java.io.FilePermission
"/home/klute/classes/−", "read";
Web−Anwendungen mit Java
596
RMI−Client starten
•
RMI−Client starten (4. Versuch)
– java −cp dist/lib/rmiclient.jar:dist/lib/rmicommon.jar
−Djava.security.policy=rmiClientPolicy
de.rainer_klute.rmi.client.WWSClient //mark/WWS
– java.security.AccessControlException: access denied
(java.net.SocketPermission 127.0.0.1:2833
connect,resolve)
•
Client benötigt das Recht, eine Verbindung zum RMI−
Server aufzubauen (genauer: zum Remote−Objekt).
–
Port−Nummer läßt sich im Konstruktor von
UnicastRemoteObject festlegen.
– grant {
};
permission java.net.SocketPermission "*", "connect";
permission java.io.FilePermission
"/home/klute/classes/−", "read";
Web−Anwendungen mit Java
597
RMI−Client starten
•
RMI−Client starten (5. Versuch)
– java −cp dist/lib/rmiclient.jar:dist/lib/rmicommon.jar
−Djava.security.policy=rmiClientPolicy
de.rainer_klute.rmi.client.WWSClient //mark/WWS
– java.rmi.ConnectException: Connection refused to host:
127.0.0.1; nested exception is:
java.net.ConnectException: Verbindungsaufbau abgelehnt
•
Stub sucht Skeleton auf dem eigenen Rechner
(127.0.0.1 = localhost) statt auf der Server−Maschine.
•
RMI−Server hat sich bei der RMI−Registrierung als
»localhost« registriert. Diesen Rechnernamen gibt die
RMI−Registrierung mit dem Stub an den Client weiter.
Web−Anwendungen mit Java
598
RMI−Server neu starten
•
Property java.rmi.server.hostname legt
Hostnamen oder IP−Adresse für die Registrierung fest.
•
RMI−Server neu starten
– java −cp dist/lib/rmiserver.jar:dist/lib/rmicommon.jar
−Djava.rmi.server.codebase=file:///home/klute/classes/
−Djava.security.policy=rmiServerPolicy
−Djava.rmi.server.hostname=rserver
de.rainer_klute.rmi.server.WWSImpl
•
RMI−Client neu starten
•
Bingo!
Web−Anwendungen mit Java
599
Objekte übertragen
•
•
Client stellt Bestellung zusammen.
–
Interfaces Bestellung, Posten
–
Implementierungen BestellungImpl, PostenImpl
Client schickt Bestellung zum Server.
– Bestellung b = new BestellungImpl();
// ...
b.addPosten(p);
String s = wws.bestellen(b);
System.out.println("WWS−Nachricht: " + s);
–
•
•
Übertragen zweier serialisierter Objekte (Marshalling).
Klassen−Server
•
•
Problem in der Beispielanwendung:
–
Zugriff auf Klassen über das Dateisystem
–
Im allgemeinen nicht möglich
Lösung für produktive Anwendung:
–
Klassendateien auf FTP− oder HTTP−Server legen
•
Immer noch problematisch: Übertragen der Klassen
vom RMI−Client zum RMI−Server
•
Lösung: RMI−Client implementiert eigenen HTTP−
Server.
–
RMI überträgt Objekte.
–
HTTP−Server überträgt Klassen.
Web−Anwendungen mit Java
601
RMIClassServer
•
RMIClassServer: HTTP−Server für Klassen
–
•
Basiert auf Mini−Klassenserver von Sun Microsystems.
Wird in normale RMI−Client− oder RMI−Server−
Anwendung eingebaut.
– RMIClassServer rcs = RMIClassServer.instance();
int port = rcs.run();
•
Classpath der Anwendung in System−Property
de.rainer_klute.rmi.classserver.classpath vorgeben
•
Ermittelt freien Port und startet Server−Thread.
–
RMI: Nicht behandelte Themen
•
•
RMI über Firewalls
–
HTTP−Tunnelling
–
Objekte auf festgelegtem Port exportieren
Eigene Socket−Typen
–
•
Z.B. RMI über SSL
Remote Object Activation
–
Remote−Objekte auf Anforderung erzeugen
•
Marshalling
•
RMI−IIOP
–
RMI−Programm (Java) spricht mit CORBA−
Programm.
Web−Anwendungen mit Java
603
Herunterladen