felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Philipp Höfler <Philipp.Hoef...@pernexas.com>
Subject AW: Configurator R7 example
Date Tue, 17 Jul 2018 14:18:56 GMT
Hallo Ray,

I am sorry, I do not understand your pseudo code example.
I've modified my test project to show you my current structure.

From my point of view, I would need something like a "Router" to route the Requests to the
right instance of the controller. According to my current understanding, I will have several
controllers for each configuration due to the configuration factory, right?

Would you mind looking over my example and guide me through?

This is the RestController:
https://github.com/phhoef/osgi-test/blob/master/rest-service/src/main/java/com/my/app/rest/rest/ServerInfoControllerImpl.java

Thanks,
Philipp

-----Ursprüngliche Nachricht-----
Von: Raymond Auge <raymond.auge@liferay.com> 
Gesendet: Montag, 16. Juli 2018 16:48
An: felix users <users@felix.apache.org>
Betreff: Re: Configurator R7 example

On Mon, Jul 16, 2018 at 10:42 AM, David Jencks <david.a.jencks@gmail.com>
wrote:

> Inline...
>
> Sent from my iPhone
>
> > On Jul 16, 2018, at 6:34 AM, Raymond Auge <raymond.auge@liferay.com>
> wrote:
> >
> > On Mon, Jul 16, 2018 at 6:16 AM, Philipp Höfler < 
> > Philipp.Hoefler@pernexas.com> wrote:
> >
> >> Hallo Ray,
> >>
> >> thanks for your detailed explanation. You're right, I think one can 
> >> consider this scenario as multi-tenant.
> >> This sounds pretty promising.
> >>
> >> The following points are unclear to me:
> >> * Even if I decouple the configuration from the endpoint, the 
> >> security check has to be done in the endpoint, as it depends on the 
> >> function
> that is
> >> invoked.
> >> I've several classes / endpoints for handling different functions.
> >> Basically, it is about the CRUD functions, but there are also some 
> >> additional ones.
> >> Is it still possible to handle the security check based on the 
> >> configuration in the endpoint itself, but "route" the call to the 
> >> right instance of the endpoint based on the ID coming from the rest call?
> >>
> >
> > First off let me answer your second bullet, the two interfaces I 
> > used
> were
> > just "mock" types based on your example. The Endpoint is whatever 
> > you endpoint object was. The Tenant was just an object I made up 
> > which should encompass the instance of your configuration with which 
> > you can make security checks.
> >
> >
> >> * I was trying to implement your suggestion, but I am facing problems.
> >> What is Endpoint and Tenant for interfaces? Are they part of the 
> >> JAX-RS framework or osgi or are they custom interfaces?
> >>
> >
> > See above, they are just pseudo code of your design.
> >
> >
> >> * Can I still use endpoints with the annotations (@Path, @Get, etc)?
> >>
> >
> > Yeah! this is what Endpoint was suppose to represent, again in 
> > pseudo
> code.
> >
> >
> >> * You have a map of tenants in the endpoint A. How do you create 
> >> and
> fill
> >> these tenants? Is this done automagically be the factory configuration?
> >>
> >
> > DS supports tuples of services (as in my example), and it's 
> > maintained
> for
> > you. Then you have each "Tenant" created for you by configuration 
> > admin from a component that requires factory configuration, 
> > automagically ;)
> >
> Don’t you mean something like...
> Specify the “Require” configuration policy for your DS tenant component.
> Then, when a management agent creates a factory configuration for each 
> tenant, DS will create a corresponding instance of the tenant component.
> ?
> Config admin isn’t going to create component instances for you. This 
> is close to nitpicking, but if you aren’t familiar with who does what 
> even a little imprecision can be very confusing, at least to me.
>

Of course you're right David. I was trying to describe effects rather than exact mechanics
:)
- Ray


> Thanks
> David Jencks
> > Sincerely,
> > - Ray
> >
> >
> >> Again, thanks for your help.
> >> Philipp
> >>
> >>
> >> -----Ursprüngliche Nachricht-----
> >> Von: Raymond Auge <raymond.auge@liferay.com>
> >> Gesendet: Freitag, 13. Juli 2018 16:01
> >> An: felix users <users@felix.apache.org>
> >> Betreff: Re: Configurator R7 example
> >>
> >> On Fri, Jul 13, 2018 at 4:37 AM, Philipp Höfler < 
> >> Philipp.Hoefler@pernexas.com> wrote:
> >>
> >>> I've tested the factory configuration and I am afraid that my 
> >>> problem is not being solved with this approach.
> >>>
> >>> I think I might have to explain the problem in more detail, that 
> >>> you'll get a better understanding.
> >>> I am implementing a REST service using the HTTP Whiteboard mechanism.
> >>> This interface is described in a quite old standard.
> >>> Each call contains an identifier. I would like to configure my 
> >>> service based on this identifier.
> >>> Meaning, depending on this identifier I would like to use 
> >>> different configuration.
> >>>
> >>> Example:
> >>> I am receiving a call with identifier for S1 (System 1).
> >>> {
> >>>        // 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, I would like to disable the security when the call comes 
> >>> from System 1.
> >>> But when the call comes from System 2 the security should be enabled.
> >>>
> >>> Maybe I am still misunderstanding the factory configuration.
> >>>
> >>
> >> No I think you have understood it well. However I think what you 
> >> need is to break up the concerns a little.
> >>
> >> If if were me building your system, I would:
> >>
> >> - decouple the configuration from the rest endpoint. Let's call the 
> >> endpoint A and the configuration Tenants (because it sounds like 
> >> you are building a multi-tenant system):
> >>    @Component
> >>    class A implements Endpoint {
> >>        @Reference(
> >>            policy = ReferencePolicy.DYNAMIC,
> >>            policyOption = ReferencePolicyOption.GREEDY
> >>        )
> >>        private volatile Map<Map<String, Object>, Tenant> _tenants;
> >>
> >>        String handleRequest(String tenantId) {
> >>            try {
> >>                Filter filter = FrameworkUtil.createFilter("(tenantId="
> +
> >> tenantId + ")");
> >>                return _tenants.entrySet().stream().filter(
> >>                    e -> filter.matches(e.getKey())
> >>                ).map(
> >>                    Map.Entry::getValue
> >>                ).findFirst().orElse("Not Found");
> >>            }
> >>            catch (InvalidSyntaxException e1) {
> >>                // ignore
> >>            }
> >>            return "Not Found";
> >>        }
> >>    }
> >>
> >> - create a component managed through factory configuration as above
> >>   @Component(
> >>        configurationPid = "my.config",
> >>        configurationPolicy = ConfigurationPolicy.REQUIRE
> >>   )
> >>   class TenantImpl implements Tenant {
> >>       private TenantConfig config;
> >>       @Activate
> >>       void activate(TenantConfig config) {
> >>          this.config = config;
> >>       }
> >>   }
> >> this becomes a "service" for every factory configuration instance 
> >> which is then tracked by A
> >>
> >> Create new tenants as needed.
> >>
> >> I hope that illustrates the model a little better.
> >>
> >> - Ray
> >>
> >>
> >>
> >>> But according to my current understanding, osgi will create two 
> >>> rest endpoints for each configuration, right?
> >>> When the rest call arrives, only one instance handles it, as the 
> >>> URL is the same.
> >>> I do not know the identifier at compile time.
> >>>
> >>> To summarize:
> >>> I basically want to load/use the config, based on a parameter 
> >>> coming with the request.
> >>> If possible at all, I do not want to limit the amount of systems.
> >>> Could you imagine any easy solution for that problem?
> >>>
> >>>
> >>> -----Ursprüngliche Nachricht-----
> >>> Von: Raymond Auge <raymond.auge@liferay.com>
> >>> Gesendet: Donnerstag, 12. Juli 2018 18:23
> >>> An: felix users <users@felix.apache.org>
> >>> Betreff: Re: Configurator R7 example
> >>>
> >>> 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)
> >>>
> >>
> >>
> >>
> >> --
> >> *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
>
>


--
*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
Mime
View raw message