Benson,

What you did is pretty similar in many ways to what I did although I don’t have 
the json/yaml support.

I’m not sure the [] characters are appropriate for key tokens.  Anyway my 
encoding uses key1.<number>.key2.<number>….. instead of 
key1[<number>].key2[<number>]…..

Since I’m interested in using DS spec features as much as possible, the object 
model is annotations or interfaces rather than concrete classes.  So if your DS 
component has

@Activate
void activate(MyNestedConfigAnnotation config) {…}

DS will generate implementations of the config annotation backed by the CA 
properties map.

I just realized that I haven’t yet made it easy to turn this on by committing 
the meta-annotation to generate the felix specific flag to allow nested 
annotations….. maybe this weekend.

While both you and I picked complex keys, Peter Kriens seems to be strongly in 
favor of complex values encoded in json.  I believe one of his reasons is that 
such configurations are less likely to completely break existing metatype-aware 
config viewers.  

At work I have a proprietary system that relates metatype to these nested 
configurations, but so far there is no hint of spec support.  Do you have a 
plan for using metatype?

While I’m sure OSGI would like your employer to join and help pay $$, I think 
you personally can join as a non-voting person for free or a trivial amount of 
$$.  I’d encourage you to consider this to help out with the spec development.

thanks
david jencks

> On Dec 25, 2015, at 3:00 PM, Benson Margulies <[email protected]> wrote:
> 
> David,
> 
> Warning, this is going to be a long message.
> 
> Background:
> 
> I created an OSGi DS component which is initialized from a complex
> configuration. I defined this configuration in terms of a Java object
> model. I implemented it by having a single configuration admin
> property that pointed to a file of YAML, and then I use Jackson to
> read that file into the Java objects of the model. I've typed a subset
> of it below.
> 
> It all is quite readable and maintainable as a YAML file. That's the
> driver here: I want a component with relatively complex configuration,
> and I want that configuration to be maintainable and readable in a
> natural way. I don't want the devops people to have to deal with the
> consequences of force-fitting the complex configuration into a simple
> key-value model, particularly because there are sequences of objects
> in the natural model. This all works.
> 
> How this (new) code came to be:
> 
> It occurred to us that it would be desirable to be able to manipulate
> this, to some extent, through ConfigurationAdmin -- to be able to drop
> in a new config and have the service reconfigure, to see and edit some
> details in the existing tools.
> 
> After some discussion with other people who had done similar things on
> the Karaf list, I decided to adopt 'flatten tree-shaped configurations
> into a single CA configuration', because I was able to think my way
> around it. The implementation uses complex keys to avoid complex
> values; I didn't know that Felix had existing support; I invented my
> own (rather obvious) mapping between the Jackson generic tree
> structure and complex keys. (I suspected that something awful would
> happen if I put complex values into the Dictionary and fed that to
> ConfigurationAdmin.) Certainly the web console and the Karaf shell
> would be unable to help edit such things.
> 
> To illustrate:
> 
> Consider a configuration file in YAML like:
> 
> factories:
> - id: factory1
>   componentId: tokenization
> - id: factory2
>   componentId: ner
> pipelines:
> - endpoint: ner
>   stages:
>   - factoryId: factory1
>     languages: ['*']
>   - factoryId: factory2
>     languages: ['*']
> 
> This corresponds to an overall Java class (Configuration), plus
> Factory and Stage.
> 
> class Configuration {
>    List<Factory> factories;
>    List<Pipeline> pipelines;
> };  // etc, etc.
> 
> The service component in that git repo reads a file like this as a
> generic tree structure that can represent Json, Yaml (or even XML),
> and then 'flattens' it using complex keys:
> 
>    factories[0].id = factory2
>    factories[0].componentId = tokenization
>    ...
>    pipelines[0].endpoint = ner
>    pipelines[0].stages[0].factoryId = factory1
>    ...
> 
> Given all of this, my device reads the file, makes the Dictionary with
> the complex 'flattened' keys, and pushed it into ConfigurationAdmin.
> The service that does the work now receives the Dictionary with those
> keys and their values. However, it does not have to work with them as
> such. It can call a method I've supplied to 'deflatten' -- to convert
> the key-value dictionary back into the tree structure of the Jackson
> 'JsonNode' classes. But that's not all: once it has that tree, it can
> ask Jackson to convert to the original nice object model. And now
> we've got cake and and eating it too; the code of my service works
> with the nice Java object model, the config in  source control is
> readable YAML, and you can at least look around and make simple
> changes in the standard tools.
> 
> The code I wrote today is not all that complex: one class maps back
> and forth between JsonNode trees and Dictionary objects, and another
> uses the NIO2 watcher to implement the 'watch the file system and poke
> ConfigurationAdmin'.
> 
> to answer your first question: I don't know if I have access to R7
> docs. Neither I nor my employer has any particular relationship to the
> OSGi consortium.
> 
> --benson
> 
> 
> 
> 
> On Fri, Dec 25, 2015 at 5:15 PM, David Jencks <[email protected]> 
> wrote:
>> Hi Benson,
>> 
>> Can you get to the OSGI RFCs under development for R7?  There’s the 
>> Configurer one abstracted from the enRoute configurer that David mentioned 
>> and an object conversion service abstracting the config-by-annotations from 
>> DS 1.3/R6.
>> 
>> I don’t quite understand what you mean by “Object model” and “flattening”.  
>> Does your project deal with converting nested configurations into e.g. DS 
>> references somehow?  Or does it flatten tree-shaped configurations into a 
>> single CA configuration?  I’m in favor of both of these ideas making it into 
>> the specs in some form; felix DS already has some support for tree-shaped 
>> configurations using complex keys rather than complex values.
>> 
>> I’d appreciate some more description of what your code does….
>> 
>> thanks
>> david jencks
>>> On Dec 25, 2015, at 1:56 PM, David Daniel <[email protected]> 
>>> wrote:
>>> 
>>> Thank you for the explanation
>>> 
>>> On Friday, December 25, 2015, Benson Margulies <[email protected]>
>>> wrote:
>>> 
>>>> On Fri, Dec 25, 2015 at 4:45 PM, David Daniel
>>>> <[email protected] <javascript:;>> wrote:
>>>>> What are the differences other than yaml with enroutes configuration
>>>>> provider.
>>>>> 
>>>> https://github.com/osgi/osgi.enroute.bundles/tree/master/osgi.enroute.configurer.simple.provider
>>>> 
>>>> It does not look to me as if that does a full object model; it looks
>>>> as if it just replaces property file syntax for a single-level map
>>>> with json syntax.  I may not be doing it justice in a fast read. Also,
>>>> mine allows the receiving component to convert the Dictionary (back)
>>>> to a Jackson JsonNode, and thence to a real class model. So, you can
>>>> define a configuration in terms of full data model, but still push it
>>>> through config admin and allow the use of the webconsole or karaf
>>>> shell to examine or make minor changes on the fly. I am not educated
>>>> in enroute, so I would not be surprised to learn that I've reinvented
>>>> a wheel.
>>>> 
>>>> 
>>>>> 
>>>>> On Fri, Dec 25, 2015 at 4:39 PM, Benson Margulies <[email protected]
>>>> <javascript:;>>
>>>>> wrote:
>>>>> 
>>>>>> After some hints from folks on the Karaf list, I implemented a mutant
>>>>>> cousin of fileinstall. It only does config admin, and it's role in
>>>>>> life is to read yaml or json files, 'flatten' them, and push the
>>>>>> results into config admin. My plan is for the things that use it to
>>>>>> reconstruct the original object model by reversing the flattening, not
>>>>>> to actually use keys like "foo.bar[3].baz' -- it includes an API that
>>>>>> maps a CA Dictionary back to a JsonTree.
>>>>>> 
>>>>>> For expediency, I made it depend on NIO2 (not to mention Jackson) and
>>>> DS.
>>>>>> 
>>>>>> I doubt that folks will see this as generally applicable, but I
>>>>>> carefully set it up with AL so that I could contribute it if there is
>>>>>> a surprising (to me) groundswell of interest. I know that some
>>>>>> karafers read this list, so I'm not going to bother to crosspost.
>>>>>> 
>>>>>> I haven't written any automated tests yet.
>>>>>> 
>>>>>> https://github.com/benson-basis/yaml-configuration-admin
>>>>>> 
>>>> 
>> 

Reply via email to