Why package deps won't work (Was: Re: Converting plain JARs to Java modules)
David M. Lloyd
david.lloyd at redhat.com
Tue Nov 15 09:06:56 PST 2011
On 11/15/2011 10:54 AM, Nicolas Lalevée wrote:
> Le 15 nov. 2011 à 17:40, David M. Lloyd a écrit :
>> On 11/15/2011 10:00 AM, Nicolas Lalevée wrote:
>>> Hi guys,
>>> Thank you for this very interesting discussion. I'll just react on a particular point and an example you raised.
>>> Le 15 nov. 2011 à 06:14, David M. Lloyd a écrit :
>>>> Yes, and it is actually fairly common in practice to want two versions of something in the sense of the two versions being wholly different implementations (think apache commons logging versus jcl-over-slf4j for a trivial example which crops up a lot). There are reasons to use one or the other. Multiplicity of versions (in this respect) is something the module system has to handle gracefully and simply.
>>> Then how a m2m solution is expected to resolve such case where a module is declaring a dependency on "commons-logging", whereas at deployment time I want "jcl-over-slf4j" instead ?
>>> With Maven/Ivy, some exclude rule can be set to build the classpath. Then at runtime the jvm just see one classpath and not the "module" declaration, so everything work then fine.
>>> An OSGi runtime being aware of the modules/bundle, you cannot really trick it with exclude rules. If you do, then what's the point of declaring them in the first place ? It is like tricking the jvm and declare that ch.qos.logback.classic.Logger is the substitute of org.apache.commons.logging.Log. Expressing dependencies on APIs, package in the OSGi space, then the modules can correctly bind each other without any overridden declaration.
>>> I think that was the main point of Peter's mail, API vs implementation. "Package" and "Bundle" is the way of declaring module level API and Implementation in OSGi. I can imagine than in a m2m solution it would be possible to invent special kind of module which would be about declaring APIs, just like Java Interfaces are to Java Classes. I don't know much about JBoss Modules, but such "Module Interface" doesn't exist there, does it ? How the slf4j libraries are handled in JBoss Modules world ?
>> In our case we never want apache commons logging because of a long history of memory leaks and other such bugs, so we created a module alias called "org.apache.commons.logging" which points to "org.slf4j.jcl-over-slf4j". Thus the user can depend on the commons-logging module and get the API they expect to get.
> That's not the use case I was talking about. To be more precise:
> * "Team A" release "Module A" and declare a dependency on "commons-logging"
> * "Team B" want to use "Module A" but with "jcl-over-slf4j"
> Are we stuck with third party declared dependency ?
I suppose it depends on who administers the module repository. Note
that the same question applies to m2m versus m2p. I think that the
owner of the module repository gets to make that choice as the
administrator for the system. To take the JCL case in point: the
administrator is the one who determines which implementation is
appropriate for the platform. You never really would want to support
both in this case.
This is as opposed to another case: Say one user is using Hibernate 3
and one is using Hibernate 4. We solve this type of versioning issue in
JBoss Modules with a version "slot". Put simply, this is a
disambiguating identifier used to allow two same-named modules to exist
in one repository. The "latest version" progression of each "slot"
advances independently of the other.
As with the equivalent situation on an operating system distribution,
the long term goal is always to phase out old versions and introduce new
versions over a period of time which is managed by a social process.
This type of setup has been proven to work in a number of operating
system distributions to date, and seems to work well for our case as well.
Like the operating system case, I believe that run-time dependencies are
the domain of the module distributor. The dependencies are often
slightly varied depending on who is installing the library, where, and
why. I think it's better to maintain a simple system which is flexible
enough to be customized by distribution than to try to come up with a
centralized or globalized dependency scheme. Hard realities like
licensing, implementation selection, and defective software will make a
pure globalized scheme unworkable. Take the simple division of
philosophy between Debian and Ubuntu or Fedora, where licensing ideology
makes a substantial difference in what is distributed and how.
Consider also the case where a proprietary shop wants to maintain its
own distribution, but certain libraries are considered disallowed or are
reimplemented with security or other concerns in mind. The original
build dependencies of a module might not be directly translatable into
run-time dependencies in these cases, yet to ignore these cases is to
put an undue burden on the user.
More information about the jigsaw-dev