Eclipse RCPでアプリケーションを開発しています。私はサービスの設計に関する設計上の決定に助けが必要です。OSGiサービス・アーキテクチャー:消費者の要求に応じたサービスの作成
他のモジュールにREngine
オブジェクトを提供するために使用されるバンドルがあります。 REngine
は、計算エンジンへのインタフェースであり、複数の方法で実装できます。バンドルは、リモートサーバーに接続するか、ローカル計算スレッドを開始することによって、REngineのインスタンスを提供します。一部のバンドルでは、GUIによる設定が必要です(ヘッドレスプラットフォームでも使用できる必要があります)。クライアントバンドルは、並列計算のために複数のREngine
オブジェクトを要求することがあります。
私は現在REngine
サービスを提供するためにこれらのモジュールを登録しています。このサービスはServiceFactoryによって作成され、ServiceFactoryはローカル計算インスタンスまたはリモート(サーバー)インスタンスを起動します。クライアントは、REngine
クラスのすべてのサービス登録を試して、適切なものを選択する責任があります。次のようにこれを行うには
コードをまとめることができます。
class API.REngine { ... }
class REngineProvider.Activator {
public void start(BundleContext ctx) {
ctx.registerService(REngine.class.getName(), new REngineFactory(), null);
}
}
class REngineProvider.REngineFactory implements ServiceFactory {
public Object getService(Bundle bundle, ServiceReference reference) {
return new MyREngineImplementation();
}
public void ungetService(REngine service) {
service.releaseAssociatedResources();
}
}
class RConsumer.Class {
REngine getREngine() {
ServiceReference[] references = bundleContext.getAllServiceReferences(REngine.class.getName(), null);
for(ServiceReference ref: references) {
try {
return bundleContext.getService(ref);
} catch (Exception e) {} // too bad, try the next one
}
}
}
私はこのモデルを維持したいと思います。 OSGiサービス仕様は、REngineオブジェクトが、もはや必要なくなったときにリリースされるべき生きたオブジェクトであるという私のビジネス要件に合っているのはいいことです。
ただし、登録サービスでは、バンドルごとに1つのサービスインスタンスしか提供できません。 2回目にサービスが要求されると、キャッシュされたインスタンスが返されます(新しいインスタンスを作成するのではなく)。これは私の要求と一致しません。バンドルは同じプロバイダから複数のREngineオブジェクトを取得できる必要があります。
私は既に他のOSGiフレームワーククラスを見てきましたが、何も助けてくれないようです。代替はホワイトボードモデルですが、REngineProviderバンドルで使用されるREngineRequestServiceを登録して、実際のREngineを提供するのは変です。
OSGiでこれを実装するにはどうすればよいですか?ここでは、私の要件リストを示します。
REngineProvider
バンドルを簡単に有効にしたり無効にしたりできます。クライアントコードは代わりに別のプロバイダを使用します。- REngineProviderバンドルの設定。
- クライアントバンドルごとに複数の
REngine
インスタンス。 REngine
インスタンスの明示的なリリースREngine
の作成が失敗する可能性があります。クライアントモジュールはその理由を知ることができるはずです。
ちょうど私が将来の参考として選択したソリューションを追加します。 OSGi Servicesプラットフォームは「サービスを要求する」ためのものではないようです。サービスを作成するプロバイダバンドルと、サービスを検索して使用できるクライアントバンドルです。ユーザーの要求に応じて自動的に「ファクトリ」を提供することはできません。
選択される溶液は、OSGi whiteboard modelを含む。一見すると、これは管理が非常に難しいように見えるかもしれませんが、Blueprint
は多くを助けることができます!
プロバイダ青写真。xmlファイル:
<reference-list interface="org.application.REngineRequest"
availability="optional">
<reference-listener
bind-method="bind" unbind-method="unbind">
<bean class="org.provider.REngineProvider"/>
</reference-listener>
クラスREngineRequest
は、入力に、プロバイダ彼REngineオブジェクト可能共有APIクラスである、または作成が機能しなかった理由を説明する例外を設定します。クライアントの場合
、REngineを使用すると、今やってするのと同じくらい簡単です:
REngineRequest req = new REngineRequest();
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties);
req.getEngine().doSomeStuff();
reg.unregister();
私たちは、クライアントがREngineを使用している間に、プロバイダが停止することはありませんという仮定を作ります。そうであれば、REngine
は無効になります。
DSの代わりにBluePrintとPROTOTYPEアノテーションをお勧めしますか?私は違いを見て苦労している。 – parasietje
私はBlueprintとプロトタイプの範囲を提案しようとしていました。 Blueprintは宣言型サービスよりも多くのノブを持っています。 –
残念ながら、オブジェクトの作成時にコンテキスト(プロパティ)が必要です。単純なファクトリメソッドを指定することはできませんが、インスタンス化されるクラスを指定する必要があります。青写真のようなものがあることを願っています! – parasietje