2010-09-15 12 views
1

J'ai deux applications communiquant via RMI, un serveur esclave (qui sera multiple) et un serveur maître. Après un bon design abstrait, je voudrais implémenter l'esclave de manière à ce qu'il ne sache pas que lorsqu'il parle au maître, il utilise RMI (pour que les deux applications puissent aussi être exécutées dans la même JVM) , par exemple):Problème de conception: RMI nécessite l'exportation explicite d'objets

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

... 

class Slave { 

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

} 

problème: la ligne marquée PROBLEM LINE ne fonctionne pas, parce que je ne peux pas passer simplement ceci (le Slave lui-même est un Remote qui Master va parler de nouveau à). Je dois explicitement faire un UnicastRemoteObject.exportObject(this, 0) (ou toStub(this) s'il est exporté plus tôt) mais cela fait que la classe Slave dépend de RMI, brisant la conception.

En outre, registerSlave me force à attraper RemoteException, qui ajoute également une dépendance RMI.

Que pourriez-vous suggérer pour résoudre ces problèmes?

(Il m'a aussi des bugs que ces classes doivent mettre en œuvre à distance, mais je suppose que nous ne pouvons aller jusqu'à l'abstraction)

Répondre

1

Eh bien, je l'ai fait comme ça:

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

je serais méfiant de cette abstraction - les demandes à distance desservies sont différentes des demandes servies au niveau local de plusieurs façons - latence, modes de défaillance, réessayer sémantique.

Il se peut que votre abstraction fuit parce que ce n'est pas vraiment valable.

+0

Merci pour votre commentaire, et je le garderai à l'esprit. Personnellement, je pense qu'une abstraction qui fuit est meilleure que pas d'abstraction, aussi longtemps que vous connaissez la fuite. –

0

Une partie de votre application esclave va être prêt à recevoir l'appel via RMI et traiter RemoteException, etc. Pourquoi ne pas introduire une sorte de proxy entre l'esclave et le maître qui médiatise la communication et cache le problème local. Par exemple, le long des lignes 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); 
    } 
} 
1

RMI besoins d'exportation explicite de objets

seulement si elles ne dépassent pas UnicastRemoteObject ou activable. S'ils le font, ils sont auto-exportés en construction.

Je dois faire explicitement une UnicastRemoteObject.exportObject (ce, 0)

Non, voir ci-dessus.

(ou toStub (cela) si elle est exportée plus tôt)

Quelle que soit toStub() est. Il y a un RemoteObject.toStub(), mais vous ne pouvez pas l'appeler, et si vous perdez votre temps.

Mais vous n'avez pas à faire cela du tout. Si 'this' est un objet distant exporté, vous pouvez simplement le passer en paramètre ou en résultat RMI.RMI remplacera le talon automatiquement.

+0

'this' n'est pas un objet exporté, mais l'objet' Remote' source. Je vais regarder dans la première partie de votre réponse si. –

+0

Décidez-vous. Vous avez dit 'si c'est exporté plus tôt'. – EJP