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)

War es hilfreich?

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);
   }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top