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

Reply via email to