On Fri, Jul 13, 2018 at 4:37 AM, Philipp Höfler <
[email protected]> 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 <[email protected]>
> Gesendet: Donnerstag, 12. Juli 2018 18:23
> An: felix users <[email protected]>
> Betreff: Re: Configurator R7 example
>
> On Thu, Jul 12, 2018 at 11:58 AM, Philipp Höfler <
> [email protected]> 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 <[email protected]>
> > Gesendet: Donnerstag, 12. Juli 2018 16:43
> > An: felix users <[email protected]>
> > 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 <
> > [email protected]> 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 <[email protected]>
> > > Gesendet: Donnerstag, 12. Juli 2018 11:15
> > > An: [email protected]
> > > 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
> > > <[email protected]
> > > >
> > > 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: [email protected]
> > > For additional commands, e-mail: [email protected]
> > >
> >
> >
> >
> > --
> > *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: [email protected]
> > For additional commands, e-mail: [email protected]
> >
>
>
>
> --
> *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)