2017-11-29 7 views
0

私はManagedServiceFactoryを使用して、設定ファイルに含まれるパラメータで新しいインスタンスを作成します。私はApache Felix Web Consoleでそれをやりたいのですが、新しい設定を追加するためのプラスボタンはありません。
私は何かが足りないと思う。手伝っていただけませんか?
これはこれはあり、私が知らない何かかもしれないが、私の知る限り、新しいインスタンスを作成することはできませんManagedServiceFactoryOSGi Apache Felix Web Consoleにプラスボタンを追加して新しい設定インスタンスを作成することはできません

@org.osgi.service.component.annotations.Component(
     name = "camel_config", 
     property = { 
       "service.pid=camel", 
       "factory=true" 
     }, 
     configurationPolicy = ConfigurationPolicy.IGNORE 
) 
public class ConfigReaderFactory implements ManagedServiceFactory { 
    private static final String DELETE_CONDITIONS = "readLock=changed&idempotent=false&noop=true&delete=true"; 
    private static final String NON_DELETE_CONDITIONS = "noop=true"; 
    private volatile DependencyManager dependencyManager; 
    private final Map<String, Component> components = new HashMap<>(); 
    private List<String> attributes; 
    private List<String> csvTypes; 
    private CamelService camel; 
    private TypeConverter converter; 
    private EventPublisher publisher; 
    private String url; 
    private String name; 
    private int confLine; 
    private String endpointType; 
    private String ip; 
    private String username; 
    private String password; 
    private String folder; 
    private boolean delete; 

    private Double latitude; 
    private Double longitude; 
    private String email; 

    @Override 
    public String getName() { 
     return this.getClass().getName(); 
    } 

    @Override 
    public void updated(String pid, @SuppressWarnings("rawtypes") Dictionary props) throws ConfigurationException { 
     if (components.containsKey(pid)) { 
      return; 
     } 
     if (props != null) { 
      attributes = new ArrayList<>(); 
      csvTypes = new ArrayList<>(); 

      int count = 1; 
      String configurationLine; 
      while ((configurationLine = (String) props.get(Integer.toString(count++))) != null) { 
       List<String> values = Utils.getValuesFromLine(configurationLine); 
       attributes.add(values.size() >= 1 ? values.get(0) : TypeConverter.NAMELESS); 
       csvTypes.add(values.size() >= 2 ? values.get(1) : TypeConverter.NAMELESS); 
      } 
      confLine = Integer.parseInt((String) props.get(Config.CONFIG_LINE)); 
      name = (String) props.get(Config.NAME); 

      initConfigParameters(pid, props); 
      buildURL(); 
      System.out.println("[URL] " + url); 

      try { 
       Map<String, Object> params = new HashMap<>(); 
       putParameters(params); 
       camel.start(params); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    @Override 
    public void deleted(String pid) { 
     Component component = components.remove(pid); 
     dependencyManager.remove(component); 
     component.stop(); 
    } 

    private void buildURL() { 
     url = ""; 
     switch(endpointType) { 
     case Constants.FTP: 
      url += "ftp://" + username + "@" + ip + "/" + folder + "?"; 
      if(!password.equals("")) { 
       url += "password=" + password + "&"; 
      } 
      break; 
     case Constants.FILE: 
      url += "file://" + folder + "?"; 
      break; 
     case Constants.EMAIL: 
      url += "imaps://imap.gmail.com?username="+email+"&password="+password 
        +"&delete=false&unseen=false"; 
     } 
     if(endpointType.equals(Constants.FTP) || endpointType.equals(Constants.FILE)) { 
      if (delete) { 
       url += DELETE_CONDITIONS; 
      } else { 
       url += NON_DELETE_CONDITIONS; 
      } 
     } 
    } 

    private void initConfigParameters(String pid, @SuppressWarnings("rawtypes") Dictionary props) { 
     confLine = Integer.parseInt((String) props.get(Config.CONFIG_LINE)); 
     name = (String) props.get(Config.NAME); 
     endpointType = (String) props.get(Config.ENDPOINT_TYPE); 
     ip = (String) props.get(Config.IP_ADDRESS); 
     username = (String) props.get(Config.USERNAME); 
     password = (String) props.get(Config.PASSWORD); 
     folder = (String) props.get(Config.FOLDER); 
     email = (String) props.get(Config.EMAIL); 
     delete = ((String) props.get(Config.DELETE)).equals("true"); 
     if((String) props.get(Config.LATITUDE)!=null) { 
      latitude = Double.parseDouble((String) props.get(Config.LATITUDE)); 
     } 
     if((String) props.get(Config.LONGITUDE)!=null) { 
      longitude = Double.parseDouble((String) props.get(Config.LONGITUDE)); 
     } 

     printParameters(pid); 
    } 
    private void putParameters(Map<String, Object> params) { 
     params.put(Constants.ATTRIBUTES, attributes); 
     params.put(Constants.TYPES, csvTypes); 
     params.put(Constants.CONF_LINE, confLine); 
     params.put(Constants.SOURCE, name); 
     params.put(Constants.PUBLISHER, publisher); 
     params.put(Constants.CONVERTER, converter); 
     params.put(Constants.LATITUDE, latitude); 
     params.put(Constants.LONGITUDE, longitude); 
     params.put(Constants.ENDPOINT_TYPE, endpointType); 
     params.put(Constants.EMAIL, email); 
     params.put(Constants.CONTEXT, FrameworkUtil.getBundle(this.getClass()).getBundleContext()); 
     Processor processor = new CSVProcessor(params); 
     params.put(Constants.PROCESSOR, processor); 
     params.put(Constants.URL, url); 
    } 
    private void printParameters(String pid) { 
     System.out.println("\nStarting camel with parameters:"); 
     System.out.println("Config file name "+pid); 
     System.out.println("[sensor_name]::" + name); 
     if(latitude!=null && longitude!=null) { 
      System.out.println("[latitude]::" + latitude); 
      System.out.println("[longitude]::" + longitude); 
     } 
     System.out.println("[endpoint_type]::" + endpointType); 
     if(endpointType.equals("ftp")) { 
      System.out.println("[ip_address]::" + ip); 
      System.out.println("[folder]::" + folder); 
      System.out.println("[user]::" + username); 
      System.out.println("[password]::" + password); 
     } else if(endpointType.equals("file")) { 
      System.out.println("[folder]::" + folder); 
     } else if(endpointType.equals("email")) { 
      System.out.println("[email]::" + email); 
      System.out.println("[password]::" + password); 
     } 
     System.out.println("[delete]::" + delete); 
    } 

    @Reference(service = TypeConverter.class) 
    public void setTypeConverter(TypeConverter converter) { 
     this.converter = converter; 
    } 

    public void unsetTypeConverter(TypeConverter converter) { 
     this.converter = null; 
    } 

    @Reference(service = EventPublisher.class) 
    public void setEventPublisher(EventPublisher publisher) { 
     this.publisher = publisher; 
    } 

    public void unsetEventPublisher(EventPublisher publisher) { 
     this.publisher = null; 
    } 

    @Reference(service = CamelService.class) 
    public void setCamelService(CamelService camel) { 
     this.camel = camel; 
    } 

    public void unsetCamelService(CamelService camel) { 
     this.camel = null; 
    } 
} 

答えて

1

私はManagedServiceFactoryを使用して、設定ファイルに含まれるパラメータで新しいインスタンスを作成します。

宣言型サービス(クラスは注釈付き@Component)を使用していますが、ManagedServiceFactoryも実装しています。他の人が言ったように、これは悪い習慣であり、あなたはそれをしてはいけません。さらに、コードはスレッドセーフではなく、Map<String, Component> componentsが壊れる可能性があります。

コンポーネントをconfigurationPolicy=ConfigurationPolicy.REQUIREに、コンフィグレーションを受け取るために@Activateメソッドを使用し、削除を処理するという方法を推奨します。それで、マップはまったく必要ありません。

私はApache Felix Web Consoleでやりたいと思っていますが、新しい設定を追加するためのプラスボタンはありません。

Felix Webコンソールは、このユーザーインターフェイスを生成するためにMetatypeを使用しています。メタタイプのXMLを書くことは恐ろしいことですが、人間が試みるべきではありませんが、幸いにもorg.osgi.service.metatype.annotationsを使用してメタタイプを定義することができます。これらの注釈は、設定のレイアウトを説明するインタフェースまたは注釈に適用されます。たとえば:

@ObjectClassDefinition 
public @interface MyConfig { 

    // This defines the property key "myProp" with 
    // a default value of "foo" and it will show 
    // up in the UI with the name "My Prop" 
    String myProp() default "foo"; 

    // This defines the property key "my.prop" 
    // with a default value of 42. The @AD 
    // allows customisation of the UI 
    @AD(description="Something descriptive") 
    int my_num() default 42; 
} 

あなたのコンポーネントが@Designateアノテーションを使用して、この構成プロパティのタイプをリンク:

@org.osgi.service.component.annotations.Component(
    name = "camel_config", configurationPid=camel", 
    configurationPolicy = ConfigurationPolicy.REQUIRE 
) 
@Designate(ocd=MyConfig.class) 
public class ConfigReaderFactory { 
    ... 
} 

DS 1.3を使用して、あなたもあなたのactivateメソッドに直接この構成タイプを注入することができます。あなたが好きな場合は、また、同様に地図を注入することができ

@Activate 
void activate(MyConfig config) { 
    // process config... 
} 

:あなたのメタタイプが定義されると

@Activate 
void activate(MyConfig config, Map<String, Object> rawConfig) { 
    // process config... 
} 

+アイコンは、コンポーネントを構成するためのカスタムUIと一緒に、表示されます。

+0

それは私の問題を解決しました。私は本当にありがとう、私はDSの注釈に関する私の混乱をすぐに解決すると思います – Spronghi

0

を実装するクラスである私のApache FelixのWebコンソール

imageですConfiguration Admin Service(これはWebコンソールの設定が使用するものです)を介して管理されるサービスです。

ManagedServiceFactoryは、オンデマンドでサービスを作成するためにあなた(またはあなたの代わりにフレームワーク)が呼び出すファクトリです。構成管理サービスを使用してファクトリ自体を構成できますが、作成するサービスインスタンスの構成はファクトリです。

一方、Metatype serviceを使用して、非管理サービスの構成を記述することができます。これを行うと、Felix Web ConsoleやApache File Installなどのツールは、新しい設定が提供されたときにその情報を使用してサービスの新しいインスタンスを作成できます。これは、Felix Web Console設定画面でプラスボタンが表示されたときです。

0

ManagedServiceFactoryを実装する必要はありません。複数回作成された コンポーネントを取得するには、コンフィグ管理ごとに1つのインスタンス レコードを取得します。 configurationPolicyが "require"のプレーンコンポーネントを作成する必要があります。たとえば:

@Component(name = "camel, configurationPolicy=ConfigurationPolicy.REQUIRE) 
public class ConfigReaderComponent { 

    @Activate 
    void activate(Map<String, Object> configProps) { 
     // process config... 
    } 
} 

このクラス全体ではcamelの 工場のPIDと、各設定レコードに対して一度インスタンス化されます。また、WebConsoleはファクトリであることを認識し、プラスボタンを有効にします。

関連する問題