構成ごとに作成する必要があるサービスがあり、それぞれが外部リソースに依存しているため、独自のライフサイクルを管理する必要があります (つまり、サービスを登録 (登録解除) します)。したがって、これらを DS として実装し、SCR が複数のインスタンスを生成できるようにすることはできません。
このタスクを完全に達成するために、ManagedServiceFactory を登録するバンドルを実装できます (私の以前の投稿を参照してください)。しかし結果として、ファクトリが他のいくつかのサービスに依存している場合は、それらのサービスの追跡を開始し、すべてを実行するために多くのグルー コードを記述する必要があります。ManagedServiceFactory
代わりに、SCRがサービス レジストリに登録する (シングルトンの) 宣言型サービスとしてファクトリを実装したいと考えています。
これが私の試みです:
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.service.component.ComponentContext;
@SuppressWarnings({ "rawtypes", "unchecked" })
public class Factory implements ManagedServiceFactory {
private BundleContext bundleCtxt;
private Map<String, ServiceRegistration> services;
public void activate(ComponentContext context) throws Exception {
System.out.println("actiavting...");
this.bundleCtxt = context.getBundleContext();
services = new HashMap<String, ServiceRegistration>();
}
public void deactivate(ComponentContext context) {
for(ServiceRegistration reg : services.values()) {
System.out.println("deregister " + reg);
reg.unregister();
}
services.clear();
}
@Override
public String getName() {
System.out.println("returning factory name");
return "my.project.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, bundleCtxt.registerService(ServiceInterface.class,
new Service(), properties));
} else {
// i should to some update here
}
}
@Override
public void deleted(String pid) {
ServiceRegistration reg = services.get(pid);
if (reg != null) {
reg.unregister();
services.remove(pid);
}
}
}
およびサービスの説明:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="ignore" name="my.project.servicefactory">
<implementation class="my.project.factory.Factory"/>
<service>
<provide interface="org.osgi.service.cm.ManagedServiceFactory"/>
</service>
<property name="service.pid" type="String" value="my.project.servicefactory"/>
</scr:component>
サービス説明の「factory」プロパティが間違ったパスであることは既にわかりました。この方法では、コンポーネントがManagedServiceFactory
サービス レジストリのように登録されず、代わりにComponentFactory
.
一種のハックとして、コンポーネント プロパティを追加しました。
<property name="service.pid" type="String" value="my.project.servicefactory"/>
と追加しましconfiguration-policy="ignore"
た。これは機能します。指定された構成my.project.servicefactory-foobar.cfg
は私のサービスに渡され、サービス レジストリに登録されます。すべて問題ありません。
しかし、私が気に入らないことが2つあります。
- プロパティを手動で設定すること
service.pid
は、私には汚いハックのように感じます - 設定
configuration-policy="ignore"
すると、それ自体を構成できなくなりますManagedServiceFactory
。このプロパティをエスケープするか、require に設定すると、という名前の構成に対して 1 つ取得ManagedServiceFactory
し、patternでmy.project.servicefactory.cfg
名前を付けた構成ごとに 2 つのサービスを取得します。 . (SCRが工場出荷時の設定のプロパティを上書きするため、少なくともこれは指数関数的に増加していません)my.project.servicefactory-foobar.cfg
ManagedServiceFactory
ServiceInterface
ManagedServiceFactory
service.pid
では、これを適切に設定するにはどうすればよいでしょうか。
PS: ファイル名の構成への私の参照について疑問に思っている人のために: 私は構成に Felix Fileinstall を使用するためfoo.cfg
、 PID の ConfigAdmin に配置され、foo
factory -pidにfoo-bar.cfg
配置されます。foo