[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [equinox-dev] RequiresBundle, ImportPackage and virtual providers

Alex,

I disagree.

> Requires-Bundle allows an ordering between two implementations such
> that one implementation must be brought up/started before another; and
> that regardless of the contents of the bundle, I get access to only
> what that bundle provides to me.

You need to take care about the lifecycle of a bundle. There are three
relevant states: INSTALLED, RESOLVED and ACTIVE... and I think I will
drop the ALLCAPS for these names from now on.

"Installed" means that the bundle has been installed into the runtime
but some or all of its dependencies (ie both through Requires-Bundle
and Import-Package) could not be resolved yet.

"Resolved" means that the bundle is installed AND all of the bundles
named in Requires-Bundle are installed AND all of the Import-Packages
have been wired to a corresponding Export-Package in an installed
bundle.

"Active" merely means that a Resolved bundle has an Activator and the
start() method has been called by the framework. In pure OSGi terms, a
bundle is only activated if another bundle asks the framework to start
that bundle, for example if the user types "start 10" in the OSGi
console. Equinox also has the Eclipse-LazyStart directive which
indicates that the bundle should be automatically started if any other
bundle caused a class inside it to be loaded.

Typically a bundle that provides only Java classes (eg the interfaces
for XML parsing) needs only to be Resolved and never Activated. A
bundle needs to be Activated only if it registers services, consumes
services from other bundles, or (in Equinox) registers extensions or
extension points. My bundle shouldn't care about whether another
bundle is Active or not - in order to depend on the code in that
bundle it needs merely to be Resolved.

Therefore there is no real difference in start ordering between
Require-Bundle and Import-Package. The only differences are that with
Require-Bundle, ALL of the packages exported by that bundle are
imported, (including the ones you might not need) and also you know
which specific bundle is supplying the implementation that you use.

More comments after this block quote:

> It sems to me like Import-Package is being promoted since it allows a
> looser coupling between the client bundle and the server bundle (for
> want of better terminology). In other words, with something like an
> XML parser, I could have an import for javax.xml, and then I could
> substitute either Xerces or Crimson since both would export those
> packages.
>
> However, I don't think that last approach works tremendously well.
> Firstly, the import package is specific to a particular package, and
> it's quite likely that the implementation of the service is going to
> be in a different package from the interfaces in any case. (For a
> single-interface type service, it might be OK. This may be more common
> in embedded OSGi environments but may not scale well to larger
> systems.) Secondly, you do want to semantically ensure that an XML
> service is available (though perhaps not caring which one) if you are
> intending to use it, so you would need to have some kind of
> relationship between bundles.

If you look at the way most of the services in the OSGi Compendium are
specified, you don't depend on the implementation, either through
Import-Package or Require-Bundle. The implementation is supplied at
runtime as a service.

Take for example the LogService specification. If I have a bundle that
consumes LogService, I need to import the org.osgi.service.log
package, which gives me just the interface
org.osgi.service.log.LogService, along with some other things like
LogEntry, LogListener etc. I cannot avoid this dependency, because it
specifies the contract.

However my bundle does not depend on the Equinox implementation of
LogService, which is in org.eclipse.equinox.log.LogServiceImpl. The
implementation is bound at runtime, and I can use Declarative Service
or a ServiceTracker to keep my code supplied with an implementation.
If I prefer I can supply my own LogService implementation that sends
the logging to a monitoring agent.

This works very well with Import-Package. It seems like your proposal
is driven by a desire to depend on the implementation rather than the
interface.

By the way, if two bundles supply the package org.xml.parsers, they
should supply the *same code* in those packages (subject to versioning
of course). Java packages were always intended to be a global
namespace, so Crimson has no business supplying something different in
org.xml.parsers than Xerces.

Regards
Neil