設計問題:RMIには、オブジェクトの明示的なエクスポートが必要です
-
02-10-2019 - |
質問
RMIを介して通信する2つのアプリケーション、スレーブサーバー(複数のものがあります)とマスターサーバーがあります。
優れた抽象的なデザインに続いて、マスターと話すときにRMIを使用していることを知らない方法で奴隷を実装したいと思います(たとえば、2つのアプリも同じ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依存関係も追加されます。
これらの問題を解決するために何を提案しますか?
(これらのクラスはリモートを実装する必要があると私は悩ませますが、私たちはこれまでのところ抽象化でしか行けないと思います)
解決
さて、私はこのようにやった:
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);
}
}
}
他のヒント
RMIには、オブジェクトの明示的なエクスポートが必要です
UnicaStremoteObjectまたはactivatableを拡張しない場合のみ。もしそうなら、彼らは建設時に自動輸出されています。
私は明示的にunicastRemoteobject.exportobject(this、0)をしなければなりません
いいえ、上記を参照してください。
(またはTostub(これ)以前にエクスポートした場合)
Tostub()が何であれ。 RemoteObject.tostub()がありますが、それを呼ぶことはできません。あなたが時間を無駄にしている場合。
しかし、あなたはそれをまったくする必要はありません。 「これ」がエクスポートされたリモートオブジェクトである場合、RMIパラメーターまたは結果として渡すことができます。 RMIはスタブを自動的に置き換えます。
私はこの抽象化に警戒するでしょう - リモートで提供されるリクエストは、レイテンシ、障害モード、再試行セマンティクスなど、多くの点でローカルで提供される要求とは異なります。
実際には有効ではないため、抽象化が漏れやすい可能性があります。
スレーブアプリケーションの一部は、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);
}
}