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