4

私は現在、自分自身の実装をセットアップしようとしています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.cfgmy.project.servicefactory-bar.cfg、期待どおりにManagedServiceFactoryに適切に渡され、複数のサービスServiceInterfaceが登録されました。やあ!

update 3 Neilによって提案されたように、私は宣言型サービスの部分を新しい質問に入れて、この質問の範囲を制限しました。

4

1 に答える 1

4

問題は、ファクトリレコードではなくシングルトン構成レコードがあることだと思いますcreateFactoryConfigurationfactoryPidとしてを使用するメソッドを使用my.project.servicefactoryしてConfigAdminを呼び出す必要があります。

Apache Felix FileInstall(コードを記述せずに構成レコードを作成するための便利な簡単な方法)を使用している場合my.project.servicefactory-1.cfgは、loadディレクトリに呼び出されるファイルを作成する必要があります。my.project.servicefactory-2.cfgそれらを呼び出すなどして、同じfactoryPIDでさらに構成を作成できます。

于 2012-08-07T08:15:52.767 に答える