Search code examples
osgiapache-karafkarafblueprint-osgi

Karaf add additional property to existing config file


I have a bundle which uses a configuration file org.jemz.karaf.tutorial.hello.service.config.cfg with one property:

org.jemz.karaf.tutorial.hello.service.msg="I am a HelloServiceConfig!!"

My blueprint for using ConfigAdmin is like:

<cm:property-placeholder persistent-id="org.jemz.karaf.tutorial.hello.service.config" update-strategy="reload" >
    <cm:default-properties>
        <cm:property name="org.jemz.karaf.tutorial.hello.service.msg" value="Hello World!"/>
</cm:default-properties>
</cm:property-placeholder>



<bean   id="hello-service-config"
        class="org.jemz.karaf.tutorial.hello.service.config.internal.HelloServiceConfig"
        init-method="startup"
        destroy-method="shutdown">

    <property name="helloServiceConfiguration">
        <props>
              <prop key="org.jemz.karaf.tutorial.hello.service.msg" value="${org.jemz.karaf.tutorial.hello.service.msg}"/>
        </props>
    </property>
</bean>

<service ref="hello-service-config" interface="org.jemz.karaf.tutorial.hello.service.IHelloService" />

This works fine as long as I can change the value of the property and the bundle automatically updates the property.

I am wondering if there's any way of adding a new property to my config file without having to change the blueprint (which involves compile/package again).Of course my bundle should be ready to handle new properties.

Not sure if this makes sense in OSGi. Can anyone give me a hint of how to dynamically add new properties to an existing configuration file and make them available in ConfigAdmin?


Solution

  • @yodamad showed me that properties were being updated in my ConfigurationAdmin service, but unfortunately my bundel was not receiving the new properties because in the bean definition I was just using a fixed property.

    Finally in order to get new properties from config files I have changed my blueprint definition as follows:

    <cm:property-placeholder persistent-id="org.jemz.karaf.tutorial.hello.service.config" update-strategy="reload" >
    </cm:property-placeholder>
    
    <bean   id="hello-service-config"
            class="org.jemz.karaf.tutorial.hello.service.config.internal.HelloServiceConfig"
            init-method="startup"
            destroy-method="shutdown">
    </bean>
    
    <service ref="hello-service-config" interface="org.jemz.karaf.tutorial.hello.service.IHelloService" />
    
    
    <reference id="hello-service-config-admin" interface="org.osgi.service.cm.ConfigurationAdmin"
               availability="optional">
        <reference-listener bind-method="setConfigAdmin"
                            unbind-method="unsetConfigAdmin">
            <ref component-id="hello-service-config"/>
        </reference-listener>
    </reference>
    

    I have a reference to the ConfigurationAdmin service so, now I can check all properties for my bundle as:

    public void setConfigAdmin(ConfigurationAdmin cfgAdmin) {
        this.cfgAdmin = cfgAdmin;
        try {
            Configuration cfg =   cfgAdmin.getConfiguration("org.jemz.karaf.tutorial.hello.service.config");
            Dictionary<String, Object> properties = cfg.getProperties();
            Enumeration<String> en = properties.keys();
            while(en.hasMoreElements()) {
                String key = en.nextElement();
    
                System.out.println("KEY: " + key + " VAL: " + properties.get(key));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    As my 'update-strategy' is reload I can get updated whenever a new ConfigurationAdmin service is registered.

    Any comment about my approach is welcome!