felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Martin Nielsen <mny...@gmail.com>
Subject Re: Configurator R7 example
Date Fri, 13 Jul 2018 07:09:38 GMT
Hi again David
ManagedProperties uses the Configuration Admin ManagedService and MetaType
service for everything it does. It really is just spice on top, so except
for making the configuration widely available, i don't see how i could
really go against the divisions of resposibility you describe.
I might look into the R7 spec. But i want to be a little cautious here
because another ManagedProperties quirk is that it doesnt only support the
ConfigurationAdmin. Its pluggable, so it could be implemented on top og
normal property files, databases, webservices or what have you.

-Martin

On Fri, 13 Jul 2018, 00:40 David Jencks, <david.a.jencks@gmail.com> wrote:

> Hi Martin,
>
> It’s refreshing to see so much enthusiasm!  I wonder if you might provide
> a valuable service to your current and potential users by providing a
> detailed comparison of capabilities compared with the R6 and R7 specs, and
> possibly also including felix DS extensions such as configuration via
> interfaces rather than annotations and nested configuration objects (I
> don’t know if this last is still present in the R7 code; it worked great in
> the R6 code).
>
> I’m slightly confused by some aspects of your description.  The osgi model
> is that, if you are using config admin, all configuration comes from the
> config admin service, although it might be stored or originated in many
> places such as a file, database, remote rest service, or some combination
> of these.  Also there’s a distinction between consumers of configurations
> such as DS components and and management agents that create, modify, and
> delete configurations in the config admin service.  I can’t tell how your
> system relates to these divisions of responsibility.
>
> I haven’t kept up with the R7 specs for nearly 2 years now but as I recall
> there was a possibility of making the DS implementation use the (R7)
> converter service.  I wonder if you might be able to repackage some of your
> code as a converter service enabling its’ use in more contexts.
>
> thanks!
> David Jencks
>
> > On Jul 12, 2018, at 1:39 PM, Martin Nielsen <mnybon@gmail.com> wrote:
> >
> > Hi David
> >
> > I started managedproperties before tjat specification was finished and i
> > havent really used it, as ManagedProperties has been my goto configadmin
> > communication method. I will highlight the main functions of it, but i
> cant
> > say if DS can do it too now. But the advantages are:
> >
> > The configuration is just an interface, so it can be easily replaced for
> > testing purposes.
> > You can use any class you want for config items, not just primitives.
> URL,
> > file, Datetime, Instant or whatever you can parse to a string os fair
> game.
> > You can write validation logic to check any configuration item before it
> is
> > changed. For example if you have a string that must be valid regex, or an
> > URL that needs to actually resolve, or a filepath where the file must
> > exist. If the validation code fails, the config is not updated. With
> this,
> > a silly spelling mistake will be caught, and you wont stop your
> production
> > server because pf sausage fingers:)
> > You can implement a configuration interface to supply easy and versitile
> > defaults. If you want to do random generatio, get defaults from a
> database,
> > initiate a new selfsigned certificate or whatever, practically anything
> is
> > possible.
> > You can register callbacks so you can take action when the configuration
> is
> > changed, for example if you have a Soap Server that has to reboot to take
> > in  new configuration.
> > You can use the configuration interface to save new configurations simply
> > by adding a matching setter. That means that you can have an application
> > admin change configurations for that specific bundle without letting them
> > loose in the entire app server. Saving in this way is also subject to
> > validation.
> > When a configuration is registered, it will also be availableaa a
> service,
> > so although a specific bundne owns it, other bundles can also read it.
> > Of cause we use MetaType as well, so it is possible to supply defaults,
> > suggested values, cardinalities and so on.
> >
> >
> > I am sorry that i dont really have a good grip on the new standard, so i
> > can't tell you exactly where each one falæs short. But i can say that
> > ManagedProperties can do the things it can because we found out we needed
> > it, especially the validation. You can only kill a production server
> > because you mistyped a file name so many times before do something to fix
> > it:)
> >
> >
> >
> > On 12 Jul 2018 20:11, "Philipp Höfler" <Philipp.Hoefler@pernexas.com>
> wrote:
> >
> > Thanks for your very detailed explanation.
> > If I got you right, with ManagedProperties I am not bound to the
> primitives
> > the default osgi implementation provides, but I can use any Java type.
> >
> > Up to now, I think I am fine with factory configuration, but probably I
> > come back to you in a few weeks, when I realize that the scenario is more
> > complex as I thought
> >
> > Anyhow, thanks for your help.
> > I am quite new to all the osgi stuff, but slowly but surely I am getting
> a
> > picture of it.
> >
> > -----Ursprüngliche Nachricht-----
> > Von: Martin Nielsen <mnybon@gmail.com>
> > Gesendet: Donnerstag, 12. Juli 2018 19:53
> >
> > An: users@felix.apache.org
> > Betreff: Re: Configurator R7 example
> >
> > 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.auge@liferay.com>
> > wrote:
> >
> >> On Thu, Jul 12, 2018 at 11:58 AM, Philipp Höfler <
> >> Philipp.Hoefler@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.auge@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.Hoefler@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.bosschaert@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.Hoefler@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-unsubscribe@felix.apache.org
> >
> >>>> For additional commands, e-mail: users-help@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-unsubscribe@felix.apache.org
> >
> >>> For additional commands, e-mail: users-help@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-unsubscribe@felix.apache.org
> > For additional commands, e-mail: users-help@felix.apache.org
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message