Hi Martin,

I guess you are the developer of this ManagedProperties?  How does it differ in 
capabilities to the configuration-by-annotation that is built into DS 1.3?

thanks
david jencks

> On Jul 12, 2018, at 10:53 AM, Martin Nielsen <mny...@gmail.com> wrote:
> 
> Hello everyone
> 
> I saw ManagedProperties mentioned so now I appear!
> 
> @Philipp.Hoefler if what you mean by complex types is that you want the
> configuration admin to return some more advanced types like URLs Files or
> Dates, then ManagedProperties will handle that for you. If not then stop
> reading:)
> 
> If you want to use ManagedProperties and have questions, you can write me.
> I am very talkative:)
> 
> ManagedProperties is made to handle mapping and propper handling of
> advanced or complex types to the Configuration Admin. It works through the
> java util Proxy as a middle layer, allowing an application to request
> complex types like Dates or URLs while storing them as primitives and
> Strings in the Configuration Admin.
> 
> In order to use a ManagedProperties, you register an annotated interface
> with the ManagedProperties service, like so:
> 
> First you create the interface which will serve as your configuration
> 
> package my.package.config;
> import dk.netdesign.common.osgi.config.annotation.Property;
> import dk.netdesign.common.osgi.config.annotation.PropertyDefinition;
> import dk.netdesign.common.osgi.config.exception.UnknownValueException;
> 
> @PropertyDefinition
> public interface MyConfiguration {
> @Property(type = String.class, typeMapper = ExistingFileFilter.class)
> throws UnknownValueException
> public File getExistingFile();
> 
> @Property(type = String.class, typeMapper = URLMapper.class) throws
> UnknownValueException
> public File getURL();
> @Property
> public String getUsername();
> }
> 
> Then you register it with a bundle, either through an activator or through
> Declarative Services
> 
> @Component
> public class MyComponent {
> ManagedPropertiesService mpRegistration;
> MyConfiguration config;
> @Activate
>    public void register(BundleContext context) throws
> InstantiationException, IllegalAccessException, InvalidSyntaxException {
>     config = mpRegistration.register(MyConfiguration.class, context);
> }
> @Reference(cardinality = ReferenceCardinality.MANDATORY)
> public void setManagedPropertiesService(ManagedPropertiesService
> managedPropertiesService) throws Exception {
>     mpRegistration = managedPropertiesService;
> }
> }
> 
> This will create a configuration in the ConfigurationAdmin with 3
> configurations, ExistingFile, URL and Username. Calling the getter methods
> in the interface will return the current configuration, which means that it
> will update if it gets changed in the WebConsole or anywhere else.
> 
> If you want you can pass a number of defaults with the config registration
> like this:
> config = mpRegistration.register(MyConfiguration.class, new
> MyConfigurationDefaults(), context);
> 
> MyConfigurationDefaults is simply a class that implements the
> MyConfiguration interface. The defaults come into play if no configuration
> is found, for example if no configuration has been set yet, or if a single
> configuration item was not set.
> The Defaults class can do anything basically, if you want configuration
> from a database or a webservice, it is possible.
> 
> This setup has the following advantages:
> 1. Since the Configuration is simply an interface it is easily tested
> outside OSGi, by creating a setter or extra constructor for the interface.
> Then you can simply pass whatever you want to the test, no need for
> configuration admin or anything.
> 2. The defaults can be a powerful fallback for missing configuration.
> 3. When handling complex types, ManagedProperties can test the input and
> fail the configuration update if something doesn't add up. This is very
> useful for handling complex types, as you don't want to acidentally write
> something that won't parse to what you want. For example, say you only want
> to be able to specify files which actually exist.
> 
> public class ExistingFileFilter extends TypeFilter<String, File> {
> 
>    @Override
>    public File parse(String input) throws TypeFilterException {
>        File f = new File(input);
>        try {
>            f.getCanonicalPath();
> 
>        } catch (IOException ex) {
>            throw new TypeFilterException("Could not read the file '" +
> input + "'. Could not resolve path: " + ex.getMessage(), ex);
>        }
>        return f;
>    }
>    @Override
>    public String revert(File input) throws TypeFilterException {
>        try {
>            return input.getCanonicalPath();
>        } catch (IOException ex) {
>            throw new TypeFilterException("Could not parse file", ex);
>        }
>    }
>    @Override
>    public void validate(File toValidate) throws TypeFilterException {
>        try {
>            String path = toValidate.getCanonicalPath();
>            if (!toValidate.exists()) {
>                throw new TypeFilterException("Could not parse file. The
> file " + path + " did not exist");
>            }
>        } catch (IOException ex) {
>            throw new TypeFilterException("Could not read the file '" +
> toValidate + "'. Could not resolve path: " + ex.getMessage(), ex);
>        }
>    }
> }
> 
> If the configuration is updated with a filename that is either not a proper
> filename, or the file does not exist on the system, the entire
> configuration update will throw a ConfigurationUpdate and fail. Other use
> cases could be propper URLS, or defining username/password combinations
> which are actually valid.
> 
> 
> ManagedProperties cannot currently create one return type based of several
> configuration items. For example, say you have 3 configuration items:
> Protocol, Host and Port, and you want that converted to single "getURL"
> method. That is not CURRENTLY possible.
> 
> 
> ManagedProperties has a few other cool features:
> 
> Callbacks:
> You can register callback classes which are triggered when the
> configuration is updated. This is very useful if you have something like a
> Database connection, which only takes its configuration at construction
> time.
> 
> Setters:
> You can define matching setters on the interface getter methods. This will
> allow you to change the configuration in the ConfigAdmin directly though
> the application. This can be really useful if you want to give an
> applcation admin power over the configuration for that application, but
> aren't interested in allowing him full admin access to the container.
> 
> Wicket Integration:
> A special page has been created for Wicket which can present the
> configuration of a select configuration PID, which will make an
> application-specific configuration page that much easier to implement.
> 
> On Thu, Jul 12, 2018 at 6:22 PM, Raymond Auge <raymond.a...@liferay.com>
> wrote:
> 
>> On Thu, Jul 12, 2018 at 11:58 AM, Philipp Höfler <
>> philipp.hoef...@pernexas.com> wrote:
>> 
>>> Right, this is missing.
>>> I added the @RquireConfigurator annotation to the GoGo Command class. Is
>>> that a suitable place for it?
>>> The json is now being loaded. The value is set to false.
>>> 
>>> Could you please explain, how this is working?
>>> 
>> It's not completely clear to me, why the @interface MyConfig is
>>> automatically used to hold the configuration.
>>> 
>> 
>> DS is merely creating a proxy of the annotation type which fronts (or is
>> backed by) the configuration dictionary, using the default values as well,
>> default values if that particular property is not defined or if no
>> configuration is available.
>> 
>> 
>>> In each class, that needs access to the config I've a activate and
>>> modified method with this signature: public void modified(MyConfig
>> config)
>>> 
>>> Is the type resolved based on the pid and the param type of the method?
>>> 
>> 
>> The Component Property Type will be backed by whatever configuration is
>> associated with the component. so if you use the same Component Property
>> Types on two different components which refer to two different pids, the
>> proxies will show different values (based on the backing configuration
>> dictionary of the component).
>> 
>> 
>> 
>>> 
>>> ---
>>> Back to my root problem:
>>> Is it now possible to have the following configuration?
>>> {
>>>        // Resource Format Version
>>>    ":configurator:resource-version" : 1,
>>> 
>>>        // First Configuration
>>>   "my.config":
>>>   {
>>>                "system1":
>>>        {
>>>                        "test.securityEnabled": false,
>>>                        "test.test": false
>>>                },
>>>                "system2":
>>>        {
>>>                        "test.securityEnabled": false,
>>>                        "test.test": false
>>>                }
>>>        }
>>> }
>>> 
>> 
>> Sure in this case the configuration dictionary will hold values:
>> 
>> system1 = {"test.securityEnabled": false, "test.test": false}
>> system2 = {"test.securityEnabled": false, "test.test": false}
>> 
>> which is probably not what you intended.
>> 
>> IF what you want is to create N instances of the component, one per set of
>> configuration properties, you'd want to use Factory Configurations like so:
>> 
>> {
>>>        // Resource Format Version
>>>    ":configurator:resource-version" : 1,
>>> 
>>>        // First Configuration
>>>   "my.config~system1":
>>>   {
>>>                        "test.securityEnabled": false,
>>>                        "test.test": false
>>>                },
>>>        // Second Configuration
>>>   "my.config~system2":
>>>   {
>>>                        "test.securityEnabled": true,
>>>                        "test.test": false
>>>                }
>>>        }
>>> }
>>> 
>> 
>> Then you will have 2 component activations; one for each system1, system2,
>> each with a MyConfig instance backing a different factory configuration
>> instance.
>> 
>> HTH
>> - Ray
>> 
>> 
>>> 
>>> Is it possible to have such a config with n systems?
>>> Meaning, I do not know the amount of systems at compile time.
>>> 
>>> Further, how would the @interface MyConfig annotation look like?
>>> Is it possible to expect an array of MyConfig for the modified(MyConfig[]
>>> configs) method?
>>> 
>>> Thanks for your help,
>>> Philipp
>>> 
>>> -----Ursprüngliche Nachricht-----
>>> Von: Raymond Auge <raymond.a...@liferay.com>
>>> Gesendet: Donnerstag, 12. Juli 2018 16:43
>>> An: felix users <users@felix.apache.org>
>>> Betreff: Re: Configurator R7 example
>>> 
>>> Did you add the requirement to your configuration bundle?
>>> 
>>> Require-Capability: osgi.extender; \
>>>     filter:="(&(osgi.extender=osgi.configurator) \
>>>             (version>=1.0
>>> <https://osgi.org/specification/osgi.cmpn/7.0.0/
>>> service.configurator.html#org.osgi.service.configurator>)(!(
>>> version>=2.0)))"
>>> 
>>> That or on some bit of code in the configuration bundle add the
>> annotation:
>>> 
>>> @org.osgi.service.configurator.annotations.RequireConfigurator
>>> 
>>> - Ray
>>> 
>>> 
>>> On Thu, Jul 12, 2018 at 10:23 AM, Philipp Höfler <
>>> philipp.hoef...@pernexas.com> wrote:
>>> 
>>>> Hallo David,
>>>> 
>>>> thanks for the explanation.
>>>> So, the configurator is just a "wrapper" for the ConfigAdminService to
>>>> read json and transfer it into a key value format, right?
>>>> 
>>>> I still have problems to use the
>>>> I put a test.json file in the OSGI-INF/configurator folder of a bundle
>>>> with the following content:
>>>> {
>>>>  // Resource Format Version
>>>>  ":configurator:resource-version" : 1,
>>>> 
>>>>  // First Configuration
>>>>  "my.config":
>>>>  {
>>>>    "test.securityEnabled": false,
>>>>    "test.test": false
>>>>  }
>>>> }
>>>> 
>>>> In addition, I have an annotation for holding the values:
>>>> public @interface MyConfig
>>>> {
>>>>    boolean test_securityEnabled () default true;
>>>>    boolean test_test() default true;
>>>> }
>>>> 
>>>> Besides that, I've a custom GoGo command for configuration. But I am
>>>> not sure, if this is really needed for loading the json?
>>>> 
>>>> Unfortunately, the json is obviously not loaded.
>>>> Both values are set to true, according to the default value.
>>>> 
>>>> Do I have to do something in addition to load the json file?
>>>> 
>>>> Thanks,
>>>> Philipp
>>>> 
>>>> -----Ursprüngliche Nachricht-----
>>>> Von: David Bosschaert <david.bosscha...@gmail.com>
>>>> Gesendet: Donnerstag, 12. Juli 2018 11:15
>>>> An: users@felix.apache.org
>>>> Betreff: Re: Configurator R7 example
>>>> 
>>>> Hi Philipp,
>>>> 
>>>> In the end the configuration specified with the Configurator will end
>>>> up in OSGi Configuration Admin, so the Configurator is limited to the
>>>> same types as ConfigAdmin. The Configurator allows complex JSON values
>>>> to be specified, they will end up as JSON text in Configuration Admin
>>>> if they go beyond what ConfigAdmin supports natively.
>>>> 
>>>> So to use the Configurator you need the Configurator bundle plus the
>>>> ConfigAdmin bundle.
>>>> 
>>>> The Configurator handles configuration resources in
>>>> OSGI-INF/configurator inside bundles but can also be provided with
>>>> external configuration via the configurator.initial framework/system
>>>> property. This is described in sections 150.4 and 150.5 in [1]. To
>>>> provide Configurator configuration into the system you don't need to
>>>> write any classes, but depending on how you use the configuration you
>>>> may have to add classes that consume it. But again, the consumption
>>>> can be done by anything that understands ConfigAdmin configs, so there
>>> are a lot of options for this.
>>>> 
>>>> I'm not aware of a complete tutorial on this topic yet. I agree it
>>>> would be nice to have that.
>>>> 
>>>> Hope this helps,
>>>> 
>>>> David
>>>> 
>>>> [1] https://osgi.org/specification/osgi.cmpn/7.0.0/
>>>> service.configurator.html
>>>> 
>>>> On Thu, 12 Jul 2018 at 10:55, Philipp Höfler
>>>> <philipp.hoef...@pernexas.com
>>>>> 
>>>> wrote:
>>>> 
>>>>> Hi,
>>>>> 
>>>>> I am searching for a possibility to load complex configurations.
>>>>> I tried the ConfigurationAdminService, but key value pairs are not
>>>>> sufficient as I need complex types.
>>>>> 
>>>>> Raymond pointed out that I should have a look at the Configurator
>>>>> Specification.
>>>>> https://osgi.org/specification/osgi.cmpn/7.0.0/service.configurator.
>>>>> ht
>>>>> ml
>>>>> 
>>>>> I read the specification and it sounds promising.
>>>>> But I am stuck how to use the Configuration in my project.
>>>>> I understand that I've to add the following dependency.
>>>>> org.apache.felix.configurator
>>>>> 
>>>>> But I don't understand if I've to add some classes, where the json
>>>>> file has to be placed and if it's possible to place it outside of
>>>>> the
>>>> bundle?
>>>>> 
>>>>> Is there any tutorial or sample project out there?
>>>>> 
>>>>> Thanks,
>>>>> Philipp
>>>>> 
>>>> 
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
>>>> For additional commands, e-mail: users-h...@felix.apache.org
>>>> 
>>> 
>>> 
>>> 
>>> --
>>> *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
>>> (@rotty3000)
>>> Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
>>> (@Liferay)
>>> Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org>
>>> (@OSGiAlliance)
>>> 
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
>>> For additional commands, e-mail: users-h...@felix.apache.org
>>> 
>> 
>> 
>> 
>> --
>> *Raymond Augé* <http://www.liferay.com/web/raymond.auge/profile>
>> (@rotty3000)
>> Senior Software Architect *Liferay, Inc.* <http://www.liferay.com>
>> (@Liferay)
>> Board Member & EEG Co-Chair, OSGi Alliance <http://osgi.org>
>> (@OSGiAlliance)
>> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@felix.apache.org
For additional commands, e-mail: users-h...@felix.apache.org

Reply via email to