Hi Tim,

Thanks for the feedback.

>  Each time you create a ComponentInstance instance from the ComponentFactory 
> then you must dispose of it when you are done.

Yes. The consumer has a release() method to inform the MyServiceFactory that 
the service is no longer required. Perhaps there is a more elegant or less 
intrusive way?

> Is the MyServiceFactory declared in the same bundle as the MyService? If so, 
> and if the “Config” is not allowed to change the target filter(s) of the 
> MyService instance then I would strongly recommend not using a component 
> factory, but instead directly instantiating the MyServiceImpl, setting it up 
> in the “get” method. This will mean that you don’t need to worry about the 
> objects being leaked because the only person holding them is the client.

Hmmmm. Yes, this is the case, actually. However, I have other services (for 
example, reporting) that have a @Reference to each MyService. Not sure how I 
could get by, other than maybe generating an event and listening to that event… 
but it seems that the @Reference listening to the service lifecycle is much 
simpler.


Cheers,
=David



> On Jul 9, 2018, at 17:42, Tim Ward <tim.w...@paremus.com> wrote:
> 
> I’m assuming that this isn’t very close to the actual code. If it is then 
> this has a significant leak. Each time you create a ComponentInstance 
> instance from the ComponentFactory then you must dispose of it when you are 
> done. If you don’t then these instances will accumulate over time.
> 
> Is the MyServiceFactory declared in the same bundle as the MyService? If so, 
> and if the “Config” is not allowed to change the target filter(s) of the 
> MyService instance then I would strongly recommend not using a component 
> factory, but instead directly instantiating the MyServiceImpl, setting it up 
> in the “get” method. This will mean that you don’t need to worry about the 
> objects being leaked because the only person holding them is the client.
> 
> Best Regards,
> 
> Tim
> 
>> On 9 Jul 2018, at 09:36, David Leangen <o...@leangen.net 
>> <mailto:o...@leangen.net>> wrote:
>> 
>> 
>> Just some feedback…
>> 
>> This really worked nicely for me:
>> 
>> public class MyServiceFactory {
>>   @Reference(target=...)
>>   ComponentFactory cf;
>> 
>>   MyService get(Config config) {
>>     Dictionary props = config.toProps();
>>     ComponentInstance ci = cf.newInstance(props);
>>     MyService myService = (MyService) ci.getInstance();
>>     return myService;
>>   }
>> }
>> 
>> The consumers then do this:
>> 
>> public class SomeMyServiceConsumer {
>> 
>>   @Reference(target=...)
>>   MyServiceFactory msf;
>> 
>>   void someMethod() {
>>     Config config = …
>>     MyService ms = msf.get(config);
>>     ...
>>   }
>> }
>> 
>> The only addition I had to make was, because there are actually several 
>> MyServiceFactories that provide different implementations, to add a target 
>> property to the MyServiceFactory @Reference. (Actually, the target is 
>> configured in a configuration using the msf.target property, which is also 
>> quite nice!
>> 
>> Very nice and clean solution. Thanks for pointing this out!
>> 
>> 
>> Cheers,
>> =David
>> 
>> 
>> 
>>> On Jul 5, 2018, at 7:56, David Leangen via osgi-dev <osgi-dev@mail.osgi.org 
>>> <mailto:osgi-dev@mail.osgi.org>> wrote:
>>> 
>>> 
>>> Thanks to Dirk, Tim, and Christian for your replies.
>>> 
>>> That gives me plenty of options. Some very nice insights.
>>> 
>>> Cheers!!
>>> 
>>> 
>>> =David
>>> 
>>> 
>>> 
>>>> On Jul 4, 2018, at 17:51, Tim Ward <tim.w...@paremus.com 
>>>> <mailto:tim.w...@paremus.com>> wrote:
>>>> 
>>>> Hi David,
>>>> 
>>>> There are some approaches that may help, but it’s not 100% clear from this 
>>>> thread which is correct for you because the scenario isn’t fully fleshed 
>>>> out. It appears that you are either:
>>>> 
>>>> 1) In need of your own specific instance of a common stateful, or 
>>>> otherwise thread unsafe, service which you want to instantiate and then 
>>>> release. Many instances may be needed concurrently, but the configuration 
>>>> is all the same.
>>>> 2) In need of your own specially configured instance of a service, which 
>>>> should not be used by anyone else
>>>> 3) Something else...
>>>> 
>>>> 
>>>> The solution to 1) is to use a prototype scoped service. Prototype scoped 
>>>> services allow the client to request and release instances on demand. You 
>>>> can use prototype scoped services in DS by injecting a 
>>>> ComponentServiceObjects.
>>>> 
>>>> 
>>>> @Reference
>>>> ComponentServiceObjects<MyService> cso;
>>>> 
>>>> void someMethod() {
>>>>  if (someCondition) {
>>>>     // Do one thing
>>>>  } else {
>>>>     MyService myService = cso.getService()
>>>>     
>>>>     // Use the service
>>>>     
>>>>     cso.ungetService(myService);
>>>>  }
>>>> }
>>>> 
>>>> 
>>>> The solution to 2) is either to a) use a DS ComponentFactory, or b) accept 
>>>> that the API of your service needs to change.
>>>> 
>>>> DS Component Factories are not widely used, but they provide a mechanism 
>>>> to programatically “stamp out” DS component instances from a template:
>>>> 
>>>> @Reference(target=(component.name=your.component)
>>>> ComponentFactory cf;
>>>> 
>>>> void someMethod() {
>>>>  if (someCondition) {
>>>>     // Do one thing
>>>>  } else {
>>>>     ComponentInstance ci = cf.newInstance(props);
>>>> 
>>>>     MyService myService = (MyService) ci.getInstance()
>>>>     
>>>>     // Use the service
>>>>     
>>>>     ci.dispose();
>>>>  }
>>>> }
>>>> 
>>>> On the other hand for 2 b) you could just change the way that your Service 
>>>> API works…
>>>> 
>>>> @Reference
>>>> MyServiceFactory msf;
>>>> 
>>>> void someMethod() {
>>>>  if (someCondition) {
>>>>     // Do one thing
>>>>  } else {
>>>>     MyService myService = msf.getMyService(props);
>>>>     
>>>>     // Use the service
>>>>     
>>>>     // Do you really need a dispose? The GC could probably take care of it.
>>>>  }
>>>> }
>>>> 
>>>> Advantages of Component Factories
>>>> 
>>>> No need to track any references, each instance is separate and DS takes 
>>>> care of it
>>>> Your component can run (mostly) unchanged, just set factory=true in your 
>>>> @Component annotation
>>>> 
>>>> Disadvantages of Component Factories
>>>> 
>>>> Your consumers are now tied to the DS API
>>>> You have leaked implementation detail about how your bundle provides its 
>>>> “service”
>>>> You have to rely on configuration for type safety
>>>> You have no easy way to share common configuration between the instances
>>>> The configuration you supply may cause lifecycle issues (if you customise 
>>>> a target filter then it may not be satisfiable on demand) 
>>>> 
>>>> 
>>>> My preference is always to lean toward 2 b) rather than 2 a). Typically 
>>>> the “specialisation” in configuration needed for each client is a small 
>>>> tweak to an otherwise constant central configuration. Also I find that I 
>>>> often have common resources (e.g. thread pools) that it doesn’t make sense 
>>>> to create and destroy repeatedly. The MyServiceFactory is then just a 
>>>> simple type which instantiates a MyServiceImpl, passing in any necessary 
>>>> backing services/objects/additional configuration as needed.
>>>> 
>>>> I hope this helps to widen your available options.
>>>> 
>>>> Best Regards,
>>>> 
>>>> Tim
>>>> 
>>>> 
>>>>> On 4 Jul 2018, at 07:13, David Leangen via osgi-dev 
>>>>> <osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>> wrote:
>>>>> 
>>>>> 
>>>>> Thank you Dirk, those are very nice posts. I have come across these in 
>>>>> the past and thought they were very informative.
>>>>> 
>>>>> If I am not mistaken, each of the methods you mention requires a 
>>>>> @Reference. In this case, I am looking for a way to instantiate a service 
>>>>> instance inline.
>>>>> 
>>>>> Example:
>>>>> 
>>>>> 
>>>>> void someMethod() {
>>>>>  if (someCondition) {
>>>>>     // Do one thing
>>>>>  } else {
>>>>>     // Instantiate the required service using ConfigAdmin — don’t use 
>>>>> @Reference here because it is done inline
>>>>>     // Use the service
>>>>>     // Delete the configuration, which will deactivate the service
>>>>>  }
>>>>> }
>>>>> 
>>>>> It is the meme above that I am not satisfied with:
>>>>> 
>>>>>  1. Activate a service instance by creating a Configuration
>>>>>  2. Locate that specific service instance and use it
>>>>>  3. Delete the Configuration to deactivate the service instance
>>>>> 
>>>>> 
>>>>> Unless of course there is a clever way to use @Reference that I am 
>>>>> missing which would provide an alternative means of accomplishing this.
>>>>> 
>>>>> 
>>>>> Best regards,
>>>>> =David
>>>>> 
>>>>> 
>>>>> 
>>>>>> On Jul 4, 2018, at 14:45, Fauth Dirk (AA-AS/EIS2-EU) 
>>>>>> <dirk.fa...@de.bosch.com <mailto:dirk.fa...@de.bosch.com>> wrote:
>>>>>> 
>>>>>> Hi,
>>>>>> 
>>>>>> not sure about your use case in detail, but it sounds like you either 
>>>>>> could use the ConfigurationAdmin approach like I explained here: 
>>>>>> http://blog.vogella.com/2017/02/13/control-osgi-ds-component-instances/ 
>>>>>> <http://blog.vogella.com/2017/02/13/control-osgi-ds-component-instances/>
>>>>>> Probably that is what you have already tried.
>>>>>> 
>>>>>> But maybe the target reference property is what satisfies your need in a 
>>>>>> more easy way. I explained that at the bottom of a blog post here: 
>>>>>> http://blog.vogella.com/2016/09/26/configuring-osgi-declarative-services/
>>>>>>  
>>>>>> <http://blog.vogella.com/2016/09/26/configuring-osgi-declarative-services/>
>>>>>> 
>>>>>> As an alternative you could also try if the available DS mechanisms 
>>>>>> would help, like servicefactory, scope or factory. I explained that 
>>>>>> here: 
>>>>>> http://blog.vogella.com/2017/02/13/control-osgi-ds-component-instances/ 
>>>>>> <http://blog.vogella.com/2017/02/13/control-osgi-ds-component-instances/>
>>>>>> 
>>>>>> From your question that you want to request one special instance, I 
>>>>>> suppose the target property on a reference is what you need, but there 
>>>>>> are several ways for different scenarios. :)
>>>>>> 
>>>>>> Mit freundlichen Grüßen / Best regards
>>>>>> 
>>>>>> Dirk Fauth
>>>>>> 
>>>>>> Automotive Service Solutions, ESI application (AA-AS/EIS2-EU) 
>>>>>> Robert Bosch GmbH | Postfach 11 29 | 73201 Plochingen | GERMANY | 
>>>>>> www.bosch.com <http://www.bosch.com/>
>>>>>> Tel. +49 7153 666-1155 | dirk.fa...@de.bosch.com 
>>>>>> <mailto:dirk.fa...@de.bosch.com>
>>>>>> 
>>>>>> Sitz: Stuttgart, Registergericht: Amtsgericht Stuttgart, HRB 14000; 
>>>>>> Aufsichtsratsvorsitzender: Franz Fehrenbach; Geschäftsführung: Dr. 
>>>>>> Volkmar Denner, 
>>>>>> Prof. Dr. Stefan Asenkerschbaumer, Dr. Michael Bolle, Dr. Rolf Bulander, 
>>>>>> Dr. Stefan Hartung, Dr. Markus Heyn,
>>>>>> Dr. Dirk Hoheisel, Christoph Kübel, Uwe Raschke, Peter Tyroller
>>>>>> 
>>>>>> 
>>>>>> -----Ursprüngliche Nachricht-----
>>>>>> Von: osgi-dev-boun...@mail.osgi.org 
>>>>>> <mailto:osgi-dev-boun...@mail.osgi.org> 
>>>>>> [mailto:osgi-dev-boun...@mail.osgi.org 
>>>>>> <mailto:osgi-dev-boun...@mail.osgi.org>] Im Auftrag von David Leangen 
>>>>>> via osgi-dev
>>>>>> Gesendet: Mittwoch, 4. Juli 2018 07:12
>>>>>> An: osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>
>>>>>> Betreff: [osgi-dev] DS factory-type pattern
>>>>>> 
>>>>>> 
>>>>>> Hi,
>>>>>> 
>>>>>> This may be another really dumb question… but is there a smart way to 
>>>>>> use DS as a kind of factory?
>>>>>> 
>>>>>> What I have been doing so far:
>>>>>> 
>>>>>> * Creating a Configuration via ConfigurationAdmin (I need to configure 
>>>>>> my component first)
>>>>>> * In the config, including a kind of “secret” so I know which is MY 
>>>>>> instance
>>>>>> * Listening for the existence of a service (which includes the secret)
>>>>>> 
>>>>>> 
>>>>>> It works very well, but there is a bit more cruft then I would like, and 
>>>>>> it doesn’t seem as elegant as it ought to.
>>>>>> 
>>>>>> 
>>>>>> Am I missing something, or is this the “right” was to do it at this time?
>>>>>> 
>>>>>> 
>>>>>> Cheers,
>>>>>> =David
>>>>>> 
>>>>>> 
>>>>>> _______________________________________________
>>>>>> OSGi Developer Mail List
>>>>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>
>>>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev 
>>>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>>>>> 
>>>>> _______________________________________________
>>>>> OSGi Developer Mail List
>>>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>
>>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev 
>>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>>> 
>>> _______________________________________________
>>> OSGi Developer Mail List
>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>
>>> https://mail.osgi.org/mailman/listinfo/osgi-dev 
>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
> 

_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to