Проблема проектирования: RMI нуждается в явном экспорте объектов - PullRequest
1 голос
/ 15 сентября 2010

У меня есть два приложения, взаимодействующих через RMI, подчиненный сервер (которых будет несколько) и главный сервер.

Следуя хорошему абстрактному дизайну, я бы хотел реализовать подчиненное устройство таким образом, чтобыон не знает, что при разговоре с мастером он использует RMI (например, два приложения могут быть запущены внутри одной и той же JVM):

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

...

class Slave {

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

}

Проблема: строка, помеченная PROBLEM LINE выше не работает, потому что я не могу просто передать это (само Slave - это Remote, с которым Master будет разговаривать).Я должен явно сделать UnicastRemoteObject.exportObject(this, 0) (или toStub(this), если он экспортируется ранее), но это делает класс Slave зависимым от RMI, нарушая дизайн.

Кроме того, registerSlave заставляет меня ловитьRemoteException, который также добавляет зависимость RMI.

Что бы вы посоветовали для решения этих проблем?

(Мне также жаль, что эти классы должны реализовывать Remote, но я думаю, что мы можем только идтипока что с абстракцией)

Ответы [ 4 ]

1 голос
/ 12 октября 2010

RMI требует явного экспорта объектов

Только если они не расширяют UnicastRemoteObject или Activatable.Если они это делают, они автоматически экспортируются при создании.

Я должен явно сделать UnicastRemoteObject.exportObject (this, 0)

Нет, см. Выше.

(или toStub (this), если он был экспортирован ранее)

Каким бы ни был toStub ().Существует RemoteObject.toStub (), но вы не можете так его называть, и если вы это делаете, вы тратите свое время.

Но вам совсем не обязательно это делать.Если 'this' является экспортированным удаленным объектом, вы можете просто передать его как параметр или результат RMI.RMI автоматически заменит заглушку.

1 голос
/ 22 сентября 2010

Ну, я сделал это так:

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);
   }
  }
}
0 голосов
/ 23 сентября 2010

Некоторая часть вашего ведомого приложения должна быть готова принять вызов через RMI, иметь дело с RemoteException и т. Д. Почему бы не ввести какой-либо прокси-сервер между подчиненным и ведущим, который обеспечивает связь и скрывает RMIпротив местного вопроса.Например, в соответствии с:

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);
   }
}
0 голосов
/ 15 сентября 2010

Я бы с осторожностью отнесся к этой абстракции - удаленно обслуживаемые запросы во многом отличаются от локально обслуживаемых запросов - задержка, режимы сбоя, семантика повторных попыток.

Возможно, ваша абстракция имеет утечку, посколькудействительно действителен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...