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> 
> 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
> 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