The implementation of the resolver will be different depending on the OSGi Framework implementation, so you're really getting into the weeds if you start relying on those internals.
If one of your bundle's imports is optional, then by definition your bundle has to work when that import is not wired. The Framework is not required to give you a wiring for the import even if a compatible export appears to be available. I agree with Justin that services are the answer, but I disagree a little with the structure of his solution, there is no need for a shim. Here is what I would do: * Bundle A (for "API") exports both packages org.foo and org.bar. Both of these are pure APIs without implementation, so there is no cost to exporting both packages. * Either bundle A or another bundle (A') provides a service implementing the org.foo API, e.g. org.foo.Service. * Bundle B (for "Bonus"?) imports package org.bar and provides a service implementing the org.bar API, e.g. org.bar.BonusService. * Bundle C ("Consumer") imports both packages org.foo and org.bar. Neither of these are optional imports so they are always wired. C attempts to find a service instance implementing the BonusService, but if it doesn't find that then it can fall back to the inferioer org.foo.Service instance. This can be easily modelled as a Declarative Services component with one mandatory reference to org.foo.Service, and an optional+greedy reference to the org.bar.BonusService. Neil On Fri, 15 Oct 2021 at 08:40, Dirk Rudolph <d...@apache.org> wrote: > Thanks for the suggestion Justin. > > What if I cannot guarantee that the Shim API Bundle exists on all > installations, same as Bundle B? That would mean the org.shim import > in Bundle C is optional again. > > In fact I have a Bundle D already implementing both APIs from Bundle A > and B and registering the implementation as a service of both. > > Bundle A > interface org.foo.Service {} > > Bundle B > interface org.bar.ServiceExt extends org.foo.Service {} > > Bundle D > @Component(service = {org.foo.Service,org.bar.ServiceExt}) class > ServiceImpl implements ServiceExt {} > > So Bundle B always resolves, at least wired to Bundle A and so the > service from Bundle D is used with the org.foo API. > > If I understand the StatefulResolver correctly, it uses a ThreadPool > as executor for the ResolverImpl, meaning it may happen that bundles > do not alway get resolved in the same order. If so I would assume the > implementation should repeat the resolution once a bundle fulfilling > an optional requirement gets resolved (greedy behaviour). Is that the > case? I haven't found anything about that in the specs. > > Regards, > Dirk > > > > > > > On Fri, 15 Oct 2021 at 00:09, Justin Edelson <jus...@justinedelson.com> > wrote: > > > > Hi Dirk, > > This is a possibly impractical suggestion in your context, but have you > > thought about modeling this as services? Something like: > > > > Bundle A (ID: 200) > > - Export-Package: org.foo;version=1.0.0 > > > > Bundle B (ID: 210) > > - Import-Package: org.foo;version="[1.0,2)" > > - Export-Package: org.bar;version=1.0.0 > > > > Shim API Bundle: > > - Export-Package: org.shim;version=1.0.0 > > > > Shim for Bundle A Bundle > > - Import-Package: org.shim;version="[1.0.0,2)",org.foo;version="[1.0,2)" > > > > Shim for Bundle B Bundle > > - Import-Package: org.shim;version="[1.0.0,2)",org.bar;version="[1.0,2)" > > > > Bundle C > > - Import-Package: org.shim;version="[1.0.0,2)" > > > > The Shim API bundle exports a service interface that is implemented in > both > > "Shim for Bundle A Bundle" and "Shim for Bundle B Bundle" (backed by the > > corresponding org.foo or org.bar API). The service in "Shim for Bundle B > > Bundle" has a higher service ranking. The service reference in Bundle C > > would (assuming it was properly set up) get one or the other. > > > > Regards, > > Justin > > > > On Thu, Oct 14, 2021 at 1:40 PM Dirk Rudolph <d...@apache.org> wrote: > > > > > Hi, > > > > > > tldr; is the order in which bundles get resolved predictable? > > > > > > We are facing issues with the usage of optional imports. Sometimes an > > > optionally imported package gets wired and sometimes it doesn't. > > > Refreshing the consuming bundle's package imports after startup always > > > works to get the wiring done right. > > > > > > Consider the following bundles: > > > > > > Bundle A (ID: 200) > > > - Export-Package: org.foo;version=1.0.0 > > > > > > Bundle B (ID: 210) > > > - Import-Package: org.foo;version="[1.0,2)" > > > - Export-Package: org.bar;version=1.0.0 > > > > > > Bundle C (ID: 500) > > > - Import-Package: > > > > org.foo;version="[1.0,2)",org.bar;version="[1.0,2)";resolution:=optional > > > > > > All bundles have the same startlevel (20), in case it matters (?). > > > > > > Our use-case is that Bundle C used to use an API provided by Bundle A, > > > which got improved and extended into a new API provided by Bundle B. > > > Not all installations provide Bundle B, but all provide Bundle A. > > > Bundle C now prefers the optionally available API of Bundle B but > > > falls back to the API provided by Bundle A if Bundle B is not > > > available. > > > > > > I think the usage of optional imports is reasonable here, or are there > > > alternatives besides using dynamic imports? > > > > > > Thanks, > > > > > > - Dirk > > > > > > --------------------------------------------------------------------- > > > To unsubscribe, e-mail: users-unsubscr...@felix.apache.org > > > For additional commands, e-mail: users-h...@felix.apache.org > > > > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@felix.apache.org > For additional commands, e-mail: users-h...@felix.apache.org > >