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 <[email protected]>
> 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 <[email protected]
>> <mailto:[email protected]>> 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 <[email protected]
>>> <mailto:[email protected]>> 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)
>>>> <[email protected] <mailto:[email protected]>> 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 | [email protected]
>>>> <mailto:[email protected]>
>>>>
>>>> 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: [email protected]
>>>> <mailto:[email protected]>
>>>> [mailto:[email protected]
>>>> <mailto:[email protected]>] Im Auftrag von David Leangen via
>>>> osgi-dev
>>>> Gesendet: Mittwoch, 4. Juli 2018 07:12
>>>> An: [email protected] <mailto:[email protected]>
>>>> 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
>>>> [email protected] <mailto:[email protected]>
>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>>>
>>> _______________________________________________
>>> OSGi Developer Mail List
>>> [email protected] <mailto:[email protected]>
>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev>
>
> _______________________________________________
> OSGi Developer Mail List
> [email protected]
> https://mail.osgi.org/mailman/listinfo/osgi-dev
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev