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