Inline...

Sent from my iPhone

> On Feb 23, 2018, at 4:05 PM, Leschke, Scott <slesc...@medline.com> wrote:
> 
> Well, the ConfigurationAdmin.createFactoryConfiguration method call works in 
> the version of ConfigurationAdmin that gets installed into Karaf 4.2M2, ie. a 
> service gets created and is activated.  If that's not what you're referring 
> to, then I guess I'm misunderstanding.

That has always worked:-) however it generates a new pid for the configuration 
and you have no control over it. In R7 you can specify the pid. I think what is 
happening to you is that the ca call is generating a configuration with one 
pid, then you write it to a .cfg file and file install reads it and generates a 
new configuration with a different pid. A future R7 fileinstall ought to be 
able to determine that you only intend one configuration and update it instead. 
I’m not very familiar with fileinstall so there might be a proprietary non-spec 
way to do that already; if there is I don’t know about it.
> 
> I currently only have 1 instance and it's unlikely I'll ever go to a 
> multi-instance setup.  If I ever do go to a such an architecture, the service 
> being created would only apply to a single instance and the service would be 
> specific to a team who is associated with the instance. In that case, yes I 
> imagine that there would be one instance that acted as a manager for the 
> others. More likely, each team would get a separate instance to use in their 
> own VM thereby keeping things pretty much like they are now. 
> 
> I'd have to check to be sure, but I think configuration changes are already 
> written out to .cfg files now.  Seems to me that you can make updates to a 
> configuration via the Karaf console and they end up in the associated .cfg.  
> My recollection is that it was even careful to not mess up the formatting of 
> the .cfg.

I thought I remembered something like that, but I’ve never known exactly what 
it does or where the change detection happens.

David Jencks 
> 
> Thanks for the help.  I appreciate the input.
> 
> Regards,
> 
> Scott
> 
> -----Original Message-----
> From: David Jencks [mailto:david.a.jen...@gmail.com] 
> Sent: Friday, February 23, 2018 5:14 PM
> To: user@karaf.apache.org
> Subject: Re: On another topic: Creating services programatically again
> 
> Nothing R7 is released yet, the specs aren’t final, so I doubt very much that 
> karaf implements any of it.
> 
> I don’t think you’ve considered very many ramifications of what you’re 
> proposing. In my experience an osgi web server has its port and interface 
> configured via config admin, so you aren’t going to be able to have two 
> instances with the same set of configurations.  Therefore IMO having a CA 
> implementation that somehow uses a shared persistence location isn’t going to 
> be useful, ignoring whether it’s spec compliant or not (I think not).
> 
> If all of your instances have the same services running on them, then you’d 
> need all of them to get the stimulus to create the factory configuration, or 
> they will respond differently;  with a shared fileinstall directory you get 
> the behavior you have now, where one instance gets 2 copies of the service 
> and the others presumably get one, or without the shared fileinstall you get 
> one or two services on one instance and none on the others.
> 
> If one of your instances (or a separate process) is acting as a management 
> agent for config admin, then that has to give all the instances the same 
> stimulus.  I’m suggesting that since the stimulus for all the other instances 
> is fileinstall noticing the new .cfg file, you can use that for the instance 
> that is acting as the management agent as well.  Note that config admin is 
> asynchronous, so at best the delay is shorter if you create the config in 
> code rather than letting fileinstall find it.
> 
> There might possibly be a way to configure fileinstall to detect 
> configuration changes and write them back out, but when I’ve thought that 
> class of approaches to configuration management I’ve decided the behavior is 
> too hard to reason about for it to be a plausible solution to anything except 
> making an unusable system.  Other people might have different points of view.
> 
> david jencks
> 
>> On Feb 23, 2018, at 1:49 PM, Leschke, Scott <slesc...@medline.com> wrote:
>> 
>> The fundamental question is:
>> 
>> What is the best way to create service instances (from a factory component) 
>> programmatically and store the associated configurations such that they 
>> persist across installations/upgrades of the platform, preferably using the 
>> facilities of the platform itself (ie. no DB).
>> Preferably, default configuration values are defined in a single location, 
>> code or file, if possible.
>> 
>> It would seem that at the moment at least, you probably need to lead by 
>> writing the .cfg file and just deal with the FIleInstall delay even though 
>> it seems to me that using ConfigurationAdmin.createFactoryConfiguration 
>> would be the preferred approach.
>> 
>> Scott
>> 
>> -----Original Message-----
>> From: Leschke, Scott [mailto:slesc...@medline.com]
>> Sent: Friday, February 23, 2018 3:14 PM
>> To: user@karaf.apache.org
>> Subject: RE: On another topic: Creating services programatically again
>> 
>> I should have clarified that this is running on Karaf 4.2 M2 so I suppose 
>> that's R7.  The only issue with writing the .cfg myself and relying on Felix 
>> FileInstall to do its thing is that I really didn't want to have to wait for 
>> FIleInstall to hit its poll interval since the UI needs to update the 
>> display with the new service.
>> 
>> I have to wait for the service to get created either way but if I create the 
>> configuration first I can look up the associated service by its 
>> configuration PID.  It would be if you could have the ConfigurationAdmin 
>> service write a .cfg file at the location of your choosing but that doesn't 
>> seem to be the case.
>> 
>> Scott
>> 
>> -----Original Message-----
>> From: David Jencks [mailto:david.a.jen...@gmail.com]
>> Sent: Friday, February 23, 2018 2:57 PM
>> To: user@karaf.apache.org
>> Subject: Re: On another topic: Creating services programatically again
>> 
>> I’m not sure what all of your code is doing. However, pre R7 you can’t 
>> specify the pid of a factory configuration. You might get the desired result 
>> by, on only one karaf instance, writing the .cfg file without creating a 
>> factory configuration yourself.
>> 
>> David Jencks
>> 
>> Sent from my iPhone
>> 
>>> On Feb 23, 2018, at 11:59 AM, Leschke, Scott <slesc...@medline.com> wrote:
>>> 
>>> That should have read "a service from a factory".  To clarify, I have a 
>>> component that is a factory (component), I create a new instance of the 
>>> configuration and service using cfgAdmin.createFactoryConfiguration as 
>>> shown below.  I have a single Karaf instance but if I had multiple, since 
>>> my hierarchy is outside of the Karaf installation, I think they would all 
>>> just look at the same folder structure.
>>> 
>>> My experience that Karaf DOES NOT write a .cfg file when a configuration is 
>>> created.  If it wrote a file to the location given by 
>>> "felix.fileinstall.filename", this would solve my problem.
>>> 
>>>  private void createConfig(String cpid, String dir, String name, 
>>> Map<String,Object> props)
>>>      throws Exception
>>>  {
>>>      Configuration conf =
>>> parent.cfgAdmin.createFactoryConfiguration(cpid, "?");
>>> 
>>>      dir  = (dir.endsWith("/") ? dir : dir + '/');
>>>      name = name.replaceAll(" ", "_").toLowerCase();
>>>      File cfg = new File(dir + cpid + '-' + name + ".cfg");
>>> 
>>>      Dictionary<String,Object> confProps = toDictionary(props);
>>>      confProps.put("felix.fileinstall.filename",
>>> cfg.toURI().toString());
>>> 
>>>      try
>>>      {
>>>          conf.update(confProps);
>>> 
>>>          // Get the properties for the new service object
>>>          props = getProps(conf.getPid());
>>> 
>>>          // Create .cfg file with initial property set
>>>          ITemplate tmp = parent.templateMgr.getTemplate( 
>>> configTemplates.get(cpid) );
>>>          tmp.bind("cfg", props);
>>> 
>>>          try (FileLineWriter w = new FileLineWriter(cfg))
>>>          {
>>>              w.putLine(tmp.render());
>>>          }
>>>      }
>>>      catch (Exception e)
>>>      {
>>>          cfg.delete();
>>>          conf.delete();
>>>          throw e;
>>>      }
>>>  }
>>> 
>>> -----Original Message-----
>>> From: David Jencks [mailto:david.a.jen...@gmail.com]
>>> Sent: Friday, February 23, 2018 12:23 PM
>>> To: user@karaf.apache.org
>>> Subject: Re: On another topic: Creating services programatically 
>>> again
>>> 
>>> What do you mean by “create instances of service from a factory” and how 
>>> would doing this result in a configuration at all?
>>> How are you proposing to replicate the configuration or .cfg file across 
>>> multiple karaf instances?
>>> 
>>> I’m not sure if or when karaf writes out a .cfg for a ca configuration 
>>> created through the ca api, but doing both of creating a configuration and 
>>> writing out a .cfg file is pretty sure to result in 2 instances, at least 
>>> until the r7 ca changes let you specify the pid of a factory configuration.
>>> 
>>> David Jencks
>>> 
>>> Sent from my iPhone
>>> 
>>>> On Feb 23, 2018, at 9:20 AM, Leschke, Scott <slesc...@medline.com> wrote:
>>>> 
>>>> That's exactly what I'm currently doing but I want to create instances of 
>>>> service from a factory and write the resulting configuration to .cfg.  I 
>>>> need to do this so that I can save the configurations across Karaf 
>>>> installs.  My app hierarchy resides outside of the Karaf installation so 
>>>> this works well.  Unfortunately, the code I show below gives me two 
>>>> separate service instances.
>>>> 
>>>> Scott
>>>> 
>>>> -----Original Message-----
>>>> From: David Jencks [mailto:david.a.jen...@gmail.com]
>>>> Sent: Friday, February 23, 2018 11:03 AM
>>>> To: user@karaf.apache.org
>>>> Subject: Re: On another topic: Creating services programatically 
>>>> again
>>>> 
>>>> Rather than using a relatively low level api such as ManagedServiceFactory 
>>>> I’d suggest considering a ds component with configuration required and 
>>>> supplying it with factory configurations to get multiple instances. By 
>>>> using a configuration annotation you can have the configuration injected 
>>>> in a typed form and you can supply default values for any keys not present 
>>>> in the factory configuration.
>>>> 
>>>> David Jencks
>>>> 
>>>> Sent from my iPhone
>>>> 
>>>>> On Feb 23, 2018, at 6:32 AM, Leschke, Scott <slesc...@medline.com> wrote:
>>>>> 
>>>>> OK, that sounds like it may be a good approach.  Could you point me to 
>>>>> the Decanter code as a reference?
>>>>> 
>>>>> Thanks,
>>>>> 
>>>>> Scott
>>>>> 
>>>>> -----Original Message-----
>>>>> From: Jean-Baptiste Onofré [mailto:j...@nanthrax.net]
>>>>> Sent: Thursday, February 22, 2018 9:53 PM
>>>>> To: user@karaf.apache.org
>>>>> Subject: Re: On another topic: Creating services programatically 
>>>>> again
>>>>> 
>>>>> Hi Scott,
>>>>> 
>>>>> Service Managed Factory is the other way around: you start from the cfg 
>>>>> file, then the service is created. The content of the file can be default 
>>>>> or whatever, it doesn't matter.
>>>>> 
>>>>> Basically, you would have:
>>>>> 
>>>>> etc/org.scott.foo-one.cfg
>>>>> etc/org.scott.foo-two.cfg
>>>>> etc/org.scott.foo-three.cfg
>>>>> 
>>>>> with the corresponding service for each cfg file. If you create 
>>>>> etc/org.scott.foo-four.cfg, then, automatically,  you will have a new 
>>>>> corresponding service created.
>>>>> 
>>>>> For instance, it's what we are using in Decanter for the JMX collector: 
>>>>> you can create a new JMX collector "on the fly", just adding a new 
>>>>> etc/org.apache.karaf.decanter.collector.jmx-foobar.cfg file.
>>>>> 
>>>>> Regards
>>>>> JB
>>>>> 
>>>>>> On 02/23/2018 04:47 AM, Leschke, Scott wrote:
>>>>>> Thanks JB,
>>>>>> 
>>>>>> Initially, the .cfg would be populated almost entirely with the defaults 
>>>>>>  the service receives using a configuration type so the idea is that the 
>>>>>> service creation needs to come first so that the service can be used to 
>>>>>> get the values to write the .cfg.
>>>>>> 
>>>>>> Is there a way to get those value without actually having a service 
>>>>>> instance or hard-coding them? 
>>>>>> 
>>>>>> Scott
>>>>>> 
>>>>>> -----Original Message-----
>>>>>> From: Jean-Baptiste Onofré [mailto:j...@nanthrax.net]
>>>>>> Sent: Thursday, February 22, 2018 9:38 PM
>>>>>> To: user@karaf.apache.org
>>>>>> Subject: Re: On another topic: Creating services programatically 
>>>>>> again
>>>>>> 
>>>>>> Hi Scott,
>>>>>> 
>>>>>> why don't use a managed service factory ?
>>>>>> 
>>>>>> It would automatically create a service based on a cfg. So for your 
>>>>>> user, he creates the cfg file, and then, automatically, the 
>>>>>> corresponding service is created.
>>>>>> 
>>>>>> Thoughts ?
>>>>>> 
>>>>>> Regards
>>>>>> JB
>>>>>> 
>>>>>>> On 02/22/2018 09:18 PM, Leschke, Scott wrote:
>>>>>>> As I mentioned a few weeks ago, I'm trying to create a service 
>>>>>>> instance programmatically and write the associated .cfg file for it.
>>>>>>> Based on feedback I got, I create the following method.
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> The goal is to create the service instance and then get its 
>>>>>>> configuration which at this point will mostly be the defaults 
>>>>>>> that it receives in its configuration type (hence my previous 
>>>>>>> post). It /appears/ to work, except what is really happening is 
>>>>>>> that I get two services. One is created by 
>>>>>>> createFactoryConfguration call and the other by Felix FileInstall after 
>>>>>>> the .cfg file is written.
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> Actually I'm a bit surprised that placeholder .cfg file isn't 
>>>>>>> created if property /felix.fileinstall.filename/is defined, as I 
>>>>>>> think that would solve this problem, but perhaps there's another way?
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> Thoughts?
>>>>>>> 
>>>>>>> * *
>>>>>>> 
>>>>>>> * *
>>>>>>> 
>>>>>>> *private**void* createConfig(String cpid, String dir, String 
>>>>>>> name, Map<String,Object> props)
>>>>>>> 
>>>>>>>    *throws* Exception
>>>>>>> 
>>>>>>> {
>>>>>>> 
>>>>>>>    Configuration conf =
>>>>>>> parent.cfgAdmin.createFactoryConfiguration(cpid, "?");
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>    dir  = (dir.endsWith("/") ? dir : dir + '/');
>>>>>>> 
>>>>>>>    name = name.replaceAll(" ", "_").toLowerCase();
>>>>>>> 
>>>>>>>    File cfg = *new* File(dir + cpid + '-' + name + ".cfg");
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>    Dictionary<String,Object> confProps = toDictionary(props);
>>>>>>> 
>>>>>>>    confProps.put("felix.fileinstall.filename",
>>>>>>> cfg.toURI().toString());
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>    *try*
>>>>>>> 
>>>>>>>    {
>>>>>>> 
>>>>>>>           conf.update(confProps);
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>           // Get the properties for the new service object
>>>>>>> 
>>>>>>>           props = getProps(conf.getPid());
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>           // Create .cfg file with initial property set
>>>>>>> 
>>>>>>>           ITemplate tmp = parent.templateMgr.getTemplate(
>>>>>>> configTemplates.get(cpid) );
>>>>>>> 
>>>>>>>           tmp.bind("cfg", props);
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>           *try* (FileLineWriter w = *new* FileLineWriter(cfg))
>>>>>>> 
>>>>>>>           {
>>>>>>> 
>>>>>>>                  w.putLine(tmp.render());
>>>>>>> 
>>>>>>>           }
>>>>>>> 
>>>>>>>    }
>>>>>>> 
>>>>>>>    *catch* (Exception e)
>>>>>>> 
>>>>>>>    {
>>>>>>> 
>>>>>>>           cfg.delete();
>>>>>>> 
>>>>>>>           conf.delete();
>>>>>>> 
>>>>>>>           *throw* e;
>>>>>>> 
>>>>>>>    }
>>>>>>> 
>>>>>>> }
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>>> --
>>>>>> Jean-Baptiste Onofré
>>>>>> jbono...@apache.org
>>>>>> http://blog.nanthrax.net
>>>>>> Talend - http://www.talend.com
>>>>>> 
>>>>> 
>>>>> --
>>>>> Jean-Baptiste Onofré
>>>>> jbono...@apache.org
>>>>> http://blog.nanthrax.net
>>>>> Talend - http://www.talend.com
> 

Reply via email to