Hi Tim That's an interesting approach! I hadn't considered using DS but handling the service registration myself.
To me it would have felt consistent if registering a ServiceFactory as a service using DS had just worked. Next to controlling the scope (singleton, bundle, prototype) of a service, a ServiceFactory seems suitable to creating service objects by means other than their default constructor. Thus, supporting ServiceFactories in DS would make it very easy to provide OSGi-glue for arbitrary Java classes that are themselves unaware of OSGi. Of course there is a trade-off between the usefulness of a feature and bloating the spec. And I'll leave this decision with you guys. Regards Julian On Thu, Apr 20, 2017 at 12:35 PM, Timothy Ward <tim.w...@paremus.com> wrote: > DS isn’t intended to solve every single use case, rather to make common use > cases simple to write and understand. In this case what you want is more > advanced, and unlikely to make it into DS as a natively supported pattern. > Given that you’re already tied to the core OSGi API (ServiceFactory) then > registering the service programatically would still let DS help you with > config and service injection. > > > @Component( > // Do not let DS provide the service > service = {}, > configurationPolicy = ConfigurationPolicy.REQUIRE > ) > public class FooServiceFactory implements ServiceFactory<Foo> { > > @Reference // provides FooBuilder instances that are pre-configured via > OSGi > private FooBuilderFactory fooBuilderFactory; > > private ServiceRegistration<?> reg; > > @Activate > void start(BundleContext ctx, Map<String, Object> props, Config config) { > reg = ctx.registerService(Foo.class.getName(), this, props); > } > > @Deactivate > void stop() { > reg.unregister(); > } > > @Override > public Foo getService() { > FooBuilder fooBuilder = fooBuilderFactory.builder(); > applyConfiguration(fooBuilder); > return fooBuilder.build(); > } > > private void applyConfiguration(FooBuilder fooBuilder) { > // apply OSGi configuration to FooBuilder object > } > > ... // ungetService omitted for brevity > > } > > > Regards, > > Tim > > >> On 20 Apr 2017, at 11:11, Julian Sedding <jsedd...@gmail.com> wrote: >> >> Hi Timothy >> >> Thanks for your reply. Using delegation works, I currently use it to >> solve my use-case. >> >> However, compared to implementing a ServiceFactory, delegation adds >> some overhead: >> >> - delegation needs to be implemented, which is trivial, but noisy if >> there are lots of methods that need delegating >> - by delegating, my implementation becomes a "provider" of Foo, rather >> than a "consumer", making my bundle more susceptible to changes in >> Foo's API >> - also: delegation is not possible if Foo is a final class >> >> I brought up this topic in order to (a) confirm that my desired >> approach is indeed not possible at the moment and (b) to see if adding >> support for registering custom ServiceFactory implementations via DS >> could be a desirable enhancement for the spec. >> >> Regards >> Julian >> >> >> On Thu, Apr 20, 2017 at 11:22 AM, Timothy Ward <tim.w...@paremus.com> wrote: >>> Have you not considered the following: >>> >>> >>> @Component(configurationPolicy = ConfigurationPolicy.REQUIRE, >>> scope = ServiceScope.BUNDLE) >>> public class FooImpl implements Foo { >>> >>> public @interface Config { >>> // Config definition in here >>> } >>> >>> @Reference >>> private FooBuilderFactory fooBuilderFactory; >>> >>> private Foo delegate; >>> >>> @Activate >>> void start(Config config) { >>> FooBuilder fooBuilder = fooBuilderFactory.builder(); >>> applyConfiguration(fooBuilder, config); >>> delegate = fooBuilder.build(); >>> } >>> >>> // Deactivation and Foo delegation methods go here >>> … >>> } >>> >>> Regards, >>> >>> Tim >>> >>>> On 20 Apr 2017, at 09:30, Julian Sedding <jsedd...@gmail.com> wrote: >>>> >>>> Hi there >>>> >>>> I have been trying to implement a use-case, but I seem to be running >>>> into walls ;) (Disclaimer: I can see multiple ways to implement this, >>>> but would like to re-use the dependency injection and lazy >>>> instantiation of DS). >>>> >>>> My aim is to create configured service objects in the way that is >>>> normally achieved by using a DS factory component with >>>> configuration-policy require. >>>> >>>> The catch is that the implementation of the objects I want to >>>> configure and register as a service is not under my control and is >>>> instanciated via a builder obtained from a factory that is registered >>>> as an OSGi-service. Sounds a bit complicated, maybe it's clearer in >>>> code. >>>> >>>> @Component( >>>> service = Foo.class, >>>> configurationPolicy = ConfigurationPolicy.REQUIRE >>>> ) >>>> public class FooServiceFactory implements ServiceFactory<Foo> { >>>> >>>> @Reference // provides FooBuilder instances that are pre-configured via >>>> OSGi >>>> private FooBuilderFactory fooBuilderFactory; >>>> >>>> @Override >>>> public Foo getService() { >>>> FooBuilder fooBuilder = fooBuilderFactory.builder(); >>>> applyConfiguration(fooBuilder); >>>> return fooBuilder.build(); >>>> } >>>> >>>> private void applyConfiguration(FooBuilder fooBuilder) { >>>> // apply OSGi configuration to FooBuilder object >>>> } >>>> >>>> ... // ungetService omitted for brevity >>>> >>>> } >>>> >>>> As far as I understand, this is not currently possible. The bnd tool >>>> shouts at the mismatch between the "service" attribute (Foo.class) and >>>> the ServiceFactory interface and refuses to generate the SCR XML. With >>>> a manually crafted XML, Apache Felix SCR ends up throwing exceptions. >>>> And most likely both implementations are correct, as I could not find >>>> anything supporting my use-case in the spec. >>>> >>>> Can anyone on this list please confirm that this is not (currently) >>>> possible? >>>> >>>> I think this use-case is relatively generic. It has two preconditions: >>>> >>>> - the implementation of the service object (e.g. Foo) is out of my >>>> control and can therefore not be enhanced with OSGi-specifics >>>> - in order to be able to create the service object, dependencies on >>>> other services are required >>>> >>>> Does this sound like a possible addition to the Declarative Services >>>> specification? >>>> >>>> Regards >>>> Julian >>>> >>>> PS: For those curious on how this could be implemented today. One way >>>> to implement this is to register the ServiceFactory (lazily) by hand. >>>> Provided Foo is not a final class, another way is to create a wrapper >>>> for Foo that delegates all calls to a "real" Foo instance. The >>>> FooWrapper implementation is then under my control and can be enhanced >>>> with DS annotations etc. >>>> _______________________________________________ >>>> 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 >> _______________________________________________ >> 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 _______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev