Design Ausgabe: muss RMI expliziten Export von Objekten
-
02-10-2019 - |
Frage
Ich habe zwei Anwendungen über RMI in Verbindung stehen, ein Slave-Server (von denen es mehrere sein) und einem Master-Server.
Nach gut abstraktem Design, ich mag den Slave in einer Art und Weise implementieren, dass sie nicht wissen, dass, wenn sie den Meister sprechen, es RMI mit (so, dass die beiden Anwendungen können auch innerhalb derselben JVM ausgeführt werden, zum Beispiel):
public static void main(String[] a) {
Master ms = magicGetTheMasterFromRMI();
new Slave(ms);
}
...
class Slave {
public Slave(Master m) {
m.registerSlave(this); // PROBLEM LINE
}
}
Problem: Die Linie markiert PROBLEM LINE
oben nicht funktioniert, weil ich nicht einfach diese (die Slave
selbst ein Remote
ist die Master
zurückhalten wird) übergeben. Ich muss explizit eine UnicastRemoteObject.exportObject(this, 0)
tun (oder toStub(this)
wenn es früher exportiert wird), aber das macht die Slave
Klasse auf RMI abhängen, das Design zu brechen.
Zusätzlich registerSlave
zwingt mich zu fangen RemoteException
, die auch RMI Abhängigkeit erstellt.
Was würden Sie vorschlagen, um diese Probleme zu lösen?
(Es nervt mich auch, dass diese Klassen Fern implementieren müssen, aber ich denke, wir nur so weit mit der Abstraktion gehen können)
Lösung
Nun, ich habe es so gemacht:
interface Service {
void doIt();
}
class ServiceImpl implements Service {
public void doIt() { ... }
}
interface RemoteService extends Remote {
void proxyDoIt() throws RemoteException;
}
class RemoteServiceHost implements RemoteService {
public void proxyDoIt() throws RemoteException {
// serviceImpl is a field, defined in the constructor
serviceImpl.doIt();
}
}
class RemoteServiceClient implements Service {
public void doIt() {
try {
// remoteService is a field, defined in the constructor
remoteService.proxyDoIt();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
}
Andere Tipps
muss RMI expliziten Export von Objekte
Nur wenn sie erstrecken sich nicht UnicastRemoteObject oder Activa. Wenn sie das tun sie Auto-Export auf dem Bau.
Ich muss explizit ein tun UnicastRemoteObject.exportObject (this, 0)
Nein, siehe oben.
(oder toStub (dies), wenn es exportiert wird früher)
Wie auch immer toStub () ist. Es gibt eine RemoteObject.toStub (), aber man kann sie nicht anrufen, und wenn Sie sind Sie verschwenden Ihre Zeit.
Aber Sie müssen das nicht tun überhaupt. Wenn ‚this‘ ist ein exportierte entferntes Objekt können Sie einfach es passieren um als RMI-Parameter oder Ergebnis. RMI automatisch den Stub ersetzen.
Ich würde vorsichtig sein, diese Abstraktion - der Ferne bedient Anfragen sind anders als lokal bedient Anfragen in vielerlei Hinsicht -. Latenz, Ausfallmodi, Wiederholungs Semantik
Es könnte sein, dass Ihre Abstraktion ist undicht, weil es nicht wirklich gültig ist.
Ein Teil Ihrer Slave-Anwendung wird darauf vorbereitet sein haben Anruf über RMI zu empfangen, und befassen sich mit Remote usw. Warum nicht einen Proxy irgendeiner Art zwischen dem Slave und Master vorstellen, dass vermittelt die Kommunikation und Häuten der RMI vs lokales Problem. ZB entlang der Linien von:
public Slave(Master m)
{
new MasterConnection(m, this);
}
class MasterConnection implements Slave extends UnicastRemoteObject
{
Slave s;
public MasterConnection(Master m, Slave s) throws IOException
{
this.slave = s;
try {
exportObject(this);
} catch (RemoteException e){
throw new IOException("Could not communicate with Master etc....");
}
master.registerSlave(this);
}
public void callbackFromMaster(Object arg) // or whatever
{
s.callbackFromMaster(arg);
}
}