Pregunta

Tengo dos aplicaciones que se comunican a través de RMI, un servidor esclavo (de los cuales habrá múltiples) y un servidor maestro.

Después de un buen diseño abstracto, me gustaría poner en práctica el esclavo de una manera que no sabe que al hablar con el maestro, se trata de utilizar RMI (de modo que las dos aplicaciones también se pueden ejecutar dentro de la misma JVM, por ejemplo):

public static void main(String[] a) {
     Master ms = magicGetTheMasterFromRMI();
     new Slave(ms);
}

...

class Slave {

   public Slave(Master m) {
       m.registerSlave(this); // PROBLEM LINE   
   }

}

Problema: El marcado PROBLEM LINE línea anterior no funciona, porque no puedo simplemente pasar esta (la Slave sí mismo es un Remote cuales Master hablará de nuevo a). Tengo que hacer explícita una UnicastRemoteObject.exportObject(this, 0) (o toStub(this) si se exportó anteriormente), pero que hace que la clase Slave dependen de RMI, rompiendo el diseño.

Además, me obliga a registerSlave RemoteException captura, lo que también aumenta la dependencia RMI.

¿Qué le sugeriría a resolver estos problemas?

(También me molesta que estas clases deben implementar a distancia, pero supongo que sólo podemos ir tan lejos con la abstracción)

¿Fue útil?

Solución

Bueno, lo he hecho de esta manera:

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);
   }
  }
}

Otros consejos

RMI necesita exportadora explícita de objetos

Sólo si no se extienden UnicastRemoteObject o activable. Si lo hacen, son auto-exportados en construcción.

Tengo que hacer explícita una UnicastRemoteObject.exportObject (esto, 0)

No, véase más arriba.

(o toStub (este) si se exporta antes)

Lo que toStub () es. Hay una RemoteObject.toStub (), pero no se puede estar llamando a eso, y si es que usted está perdiendo el tiempo.

Pero usted no tiene que hacer eso en absoluto. Si 'esto' es un objeto remoto exportados que sólo puede pasar a su alrededor como un parámetro de RMI o resultado. RMI sustituir el talón de forma automática.

Yo sería cuidadoso de esta abstracción - de forma remota las solicitudes atendidas son diferentes de las solicitudes atendidas localmente en muchas maneras -. Latencia, modos de fallo, la semántica de reintento

Podría ser que su abstracción es permeable porque no es realmente válida.

Una parte de su aplicación esclavo va a tener que estar preparado para recibir llamadas a través de RMI, y tratar con RemoteException, etc. ¿Por qué no introducir un proxy de algún tipo entre el esclavo y el maestro que media la comunicación y los cueros de la RMI vs asunto local. Por ejemplo, a lo largo de las líneas de:

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);
   }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top