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