私は現在、自分自身の実装をセットアップしようとしていますManagedServiceFactory
。これが私がやろうとしていることです:構成ごとにいくつかのサービスの複数のインスタンスが必要です。DSを使用すると、コンポーネントは完全に機能しましたが、DSでは不可能な外部リソースの可用性に応じて、これらのサービスが独自のライフサイクル(つまり、サービスレジストリでの(登録解除))を処理する必要があることがわかりました。
したがって、私のアイデアは、を作成することでしたManagedServiceFactory
。これにより、から構成を受け取りConfigurationAdmin
、クラスのインスタンスを作成します。これらもまた、別のスレッドでリソースに接続し、操作の準備ができたらサービスとして登録しようとします。
私はまだこれを実装する運がなかったので、動的な(登録解除)登録を処理することさえせずに、すべてを最も基本的な部分に分解しようとしましたManagedServiceFacotry
。
package my.project.factory;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
public class Factory implements BundleActivator, ManagedServiceFactory {
private ServiceRegistration myReg;
private BundleContext ctx;
private Map<String, ServiceRegistration> services;
@Override
public void start(BundleContext context) throws Exception {
System.out.println("starting factory...");
this.ctx = context;
java.util.Dictionary properties = new Hashtable<String, Object>();
properties.put(Constants.SERVICE_PID, "my.project.servicefactory");
myReg = context.registerService(ManagedServiceFactory.class, this,
properties);
System.out.println("registered as ManagedServiceFactory");
services = new HashMap<String, ServiceRegistration>();
}
@Override
public void stop(BundleContext context) throws Exception {
for(ServiceRegistration reg : services.values()) {
System.out.println("deregister " + reg);
reg.unregister();
}
if(myReg != null) {
myReg.unregister();
} else {
System.out.println("my service registration as already null " +
"(although it shouldn't)!");
}
}
@Override
public String getName() {
System.out.println("returning facotry name");
return "ServiceFactory";
}
@Override
public void updated(String pid, Dictionary properties)
throws ConfigurationException {
System.out.println("retrieved update for pid " + pid);
ServiceRegistration reg = services.get(pid);
if (reg == null) {
services.put(pid, ctx.registerService(ServiceInterface.class,
new Service(), properties));
} else {
// i should do some update here
}
}
@Override
public void deleted(String pid) {
ServiceRegistration reg = services.get(pid);
if (reg != null) {
reg.unregister();
}
}
}
ConfigurationAdmin
これで、 forPIDから構成を受け取る必要がmy.project.servicefactory
ありますね。ただし、から構成を受け取ることはありませんConfigurationAdmin
。バンドルが開始され、サービスが登録され、Webコンソールで、構成管理者がManagedServiceFactoryへの参照を保持していることがわかります。設定すべき特定のプロパティはありますか?インターフェイスの仕様はそれを示唆していません。実際、私の実装は、そこにある例とほぼ同じです。ここで何が間違っているのかわかりません。解決策へのポインタは大歓迎です。
また、当初はそれ自体をDSとして実装することを考えていましたがManagedServiceFactory
、これも可能であるはずですが、同じ時点で失敗しました。構成はによって渡されませんConfigAdmin
。
更新
質問を明確にするために:これは主に構成の問題だと思います。ご覧のとおり、ファクトリに2つのPIDを指定できるはずです。1つはファクトリ自体の構成を識別し(存在する場合)、もう1つはこのファクトリを介してサービスを生成しますfactory.pid
。しかし、フレームワーク定数はこのようなものを保持していません。
update 2
Felix Fileinstallのソースコードを少し検索したところ、ファイル名にが含ま-
れているかどうかに関係なく、構成ファイルの処理が異なることがわかりました。設定ファイルに名前をmy.project.servicefactory.cfg
付けることはできませんでしたが、設定に名前を付けmy.project.servicefactory-foo.cfg
てmy.project.servicefactory-bar.cfg
、期待どおりにManagedServiceFactoryに適切に渡され、複数のサービスServiceInterface
が登録されました。やあ!
update 3 Neilによって提案されたように、私は宣言型サービスの部分を新しい質問に入れて、この質問の範囲を制限しました。