But then you loose the DS dependency management on Foo … Since your 
FooServiceFactory no longer promises to provide a Foo service :-(

Kind regards,

        Peter Kriens


> On 20 Apr 2017, at 12:35, 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

Reply via email to