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

Reply via email to