There is nothing actually wrong with your code, but let me make a couple of
comments:

1) Using service.ranking to give preference to a particular service
implementation is very weak. As you have found (in another thread), there
is no "pressure" on a consumer to make it consume the highest ranked
instance of a service type. In fact you have to make a special effort in
each consumer to do this.

2) In general as a Java programmer (i.e. not just when using OSGi), prefer
composition over inheritance. DS clearly prefers this as well: it is very
easy to create a component that consumes others components as services, and
then combines and augments their functionality, whereas it is hard to
create a component that extends another component with inheritance, because
the the componenty nature is not inherited by default.

3) Notwithstanding point (2), you can actually make the @Reference
annotation inherited by adding the bnd instruction "-dsannotations-options:
inherit". You have to be cautious with this because, depending on how your
build path is setup, bnd might not always see the full type hierarchy of
your component. It's safe enough if you only inherit components within a
single bundle. You should never inherit types (other than interfaces and
100% abstract classes) across bundles anyway. If you do use this
inheritance then I recommend using method injection rather than field
injection, because then the subclass can choose to override the bind or
unbind methods.

Neil



On Wed, Jul 11, 2018 at 12:26 PM, Alain Picard via osgi-dev <
osgi-dev@mail.osgi.org> wrote:

>
> Converting existing code to DS in an EMF environment where we have models
> starting with core and being extended at different levels by different
> applications, and those providing various type of "features". Trying to
> determine the best approach that allows for specialization, inheritance of
> injected service, including specialization, etc.
>
> I now have a small test bed that works as expected, but looking to apply
> best practices.
>
> Let's say I start with this service:
> @Component(service=ICoreUtils.class)
> public class CoreUtils implements ICoreUtils {
>   protected ISay another;
>
>   @Reference(
>     policy=ReferencePolicy.STATIC,
>     policyOption=ReferencePolicyOption.GREEDY
>   )
>   protected void setAnother(ISay another) {
>     this.another = another;
>   }
>
> And now I can have an extension like so:
> @Component(
>   property="service.ranking:Integer=10",
>   service= { IExtUtils.class, ICoreUtils.class }
> )
> public class ExtUtils extends CoreUtils implements IExtUtils {
>   @Reference(
>     policy=ReferencePolicy.STATIC,
>     policyOption=ReferencePolicyOption.GREEDY
>   )
>   protected void setAnother(ISayMore another) {
>     this.another = another;
>   }
>
> Since @Reference are not inherited, so far I have found that using a field
> reference at each level with a protected field holding the value seems to
> be the way to go. Also the extended service registers all interfaces it
> implements. The referenced service as shown here can also be provided in
> the same way, either providing an extended interface or just a different
> implementation that is more specific.
>
> Thanks
> Alain
>
> _______________________________________________
> 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