John,
Thanks for the feedback. My responses are now inline:
On Mar 3, 2006, at 7:57 AM, John Casey wrote:
Comments inline.
Cheers,
John
Garrett Conaty wrote:
I've been working quite a bit with Maven2 transitive dependencies
at work, and think that they're one of the best strengths of M2.
In the course of building quite a number of artifacts through
build, deployment, and update I've found that there are number of
improvements that can be made. So with the use cases that I've
seen at work and listening to what other devs in the community
have experienced, I'm proposing some enhancements.
These points are only an overview, and some are a variation or
enhancement on features in the Maven 2.1 design docs. I've gone
into more depth on the rationale and the features themselves on
the MavenUser Wiki at http://docs.codehaus.org/display/MAVENUSER/
Improving+Maven2+Dependency+Resolution :
* Virtual Dependencies (also know as spec jars)
This is something we've been discussing for some time now. We just
need to have a concrete discussion about what's involved in
implementing it. For instance, we have to provide a portable way to
resolve spec -> implementation mappings. This might take a form
similar to the plugin-prefix -> implementation metadata file. Once
we have that in place, we need some consistent mechanism for
choosing one implementation over another. The corresponding
mechanisms for plugin selection based on prefix are somewhat crude...
How about putting a new <virtual> in the <dependency> stanzas of the
POM? Of course, it would still need someway to resolve this map
(perhaps by putting them in profiles or something).
* Environmental Context - Use the JDK environment and deploy
environment as part of the resolution phase. As an example, you
don't need to get JAXP API classes from a repository if compiling
with JDK 1.4
If you can represent pieces like the JDK as a repository with an
alternate layout, I don't see why we couldn't tie this into the
spec dependencies bit above and make it work.
Yeah, I definitely see these being very related. So you could define
a JDK 1.4 environment or Geronimo 1.0 environment (profile?) that
would be contain the list of the spec JARS. This would be really
helpful for building some of the Apache Commons packages that require
different JARs (currently) depending on what JDK they're using. I'd
love it if the build files for these would be able to list all the
spec JARs that they require and then when you build, Maven could have
the knowledge of your environment. Though I'm not sure they'd
actually be POMs themselves (like for JDK 1.4) that would list
artifacts. It might be viewed something more like how Eclipse shows
you library entries for JDK or app servers (like Tomcat in the
Eclipse WebToolsProject)
* Pinning Dependencies (Overrides) - If you have a fixed
dependency tree for a given release, it's important to be able to
provided patches that can override a node of the tree.
<dependencyManagement> only appears to handle this for parent-
child projects.
I suspect an elegant way to handle this might be with an
alternative dependency selection implementation that uses some
authoritative set of "approved" versions when resolving artifacts...
That makes some sense from an 'approved' perspective, though the use
case I'm describing is actually a specific patch (e.g. you've built
your application with a certain release of dependencies, and then
your vendor tells you you need to slot in this security fix). This
is slightly different than having a compliant or standard set of
dependencies.
Questions I have WRT this are:
1. will this set of blessed versions be portable (i.e. travel with
the POM)?
The simplest scoping would be to have it be an element of your
application's POM. I could also see it in /.m2/ specific settings
for a build machine, though this would be less portable. A fancy
solution might be to point to a central server and download updates,
but this is probably overkill.
2. how will developers in a team setting share this info? It seems
like implementing this would be an exercise in walking a tightrope
between portability and centralized declaration for versions.
(see previous answer)
* Filtering Parameters - Let the dependency resolution be able to
pick artifacts based on things like required JDK version, license,
signed/unsigned, tags,etc.
Is this a dependency selection technique? It seems like it's just a
matter of "approving" a given dependency as a candidate for
selection using POM attributes and possibly attributes of the jar
itself (which could be a bit more involved), before allowing
artifact version selection to proceed. Much of this could probably
be factored out of the DefaultArtifactCollector, into some sort of
pluggable component.
Exactly, I think these filters are additional parameters to the
ArtifactCollector. So just like version ranges let you select which
artifact to map to a dependency, these would be additional critiera.
Some of my colleagues have been working on some matching algorithms
for the collector to let you match the artifacts based on different
filtering parameters. Some of these filters can be required (e.g.
JDK > 5 is required because the library uses annotations) or soft
(prefer debug versions of the JAR).
A lot of this kind of info should be present in the JAR, though that
might mean you have to download them as part of the dependency
resolution/"ArtifactCollector" phase, rather than the current
artifact resolution phase, whereas if they're in the
artifactmetadata, this already gets downloaded.
* Blacklisting artifacts - Not just repositories. This is
appropriate if you don't control the POM that's using the artifact
to be blacklisted.
...so you're talking about a global exclusions list? Again, my
questions about this center on dissemination of that list.
Otherwise, can't you do this with dependency exclusions now?
I'd actually use the same scoping mechanism as per virtual
dependencies/specJARs. Unfortunately I don't think you can do this
with exclusions now, but I could be wrong. Let's say A depends on B
depends on C and B specifies a range. If B is not under my control
then could I still eliminate the version of C that would match B's
range in the pom for A? (I think I might have just figured that this
would actually work). If A puts in its own dependency for C as a !C
(bad version) then I think this would work and is an effective
blacklist.
* License Acknowledgment - Some commercial vendors (Sun) require a
clickthrough license before downloading. Also a user getting an
artifact under an Apache license with an LGPL dependency would
need to be notified that they are not only accepting the Apache
License but LGPL.
This might be another thing that gets added to the dependency
selection process, when we're gathering candidate artifact/
versions. If you combine it with spec dependencies, the selection
algorithm might be able to select an alternate [set of] deps to
satisfy the spec dependency you specify (when the user refuses to
traverse the click-through)...
Yep, though I'd like to see the APIs on the resolver to expose the
set of artifacts that could satisfy a dependency, and which would be
selected by default. This way a resolver client could present the
info to the user (like through an IDE tool).
Also, any click-through implementation will have to completely
satisfy the legal requirements of people like Sun, which could mean
finding a way to embed/interact with a full-featured browser. I
don't know of any cross-platform way to do this, without embedding
a browser...and I'm not aware of any mature embeddable browser
implementations, personally.
I was thinking it would be up to the client (e.g. maven-client) to
provide the implementation of the plug-ins for this. The resolver
would just specify a request/response interface and then the clients
would need to write their own adapters.
* Expose dependency resolution to client tools - Provide APIs so
that clients can pass in different artifacts with different
filters to see not only the multiple artifacts and paths that can
resolve a dependency, but also which one would be selected. This
would be very helpful for debugging and also to let UI tools
visualize the dependency graphs.
We can undoubtedly go further in making this accessible, but it
should be possible to do what you describe even now. It's just a
matter of knowing the APIs...
My understanding of the APIs now are that you can get an
ArtifactResolutionResult for ArtifactResolver.resolveTransitively
(...) and then the work is done in the ArtifactCollector. The thing
is, these methods return a path for the dependency that's already
resolved. Yes, you might be able to plug-in listeners that get
called at various stages and then build up your own graph of what's
going on, but I'd like a public API that returns the dependency graph
for a given artifact that includes all the nodes that 'could' match
vs just the ones that were picked. I could be missing something here
in the APIs, but I'm pretty sure that this functionality isn't
possible or is unwieldly to do with the current interfaces.
I don't think these features have easy workarounds in Maven 2.0.x,
but if there are, that would be great.
I've peer reviewed these with the folks at work as well and I'm
interested in feedback from the community on these improvements as
I'd like to get started working on them.
Thanks,
Garrett
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]