Maven 2 & 3

Direct dependencies should come before transitive dependencies in build classpath.

Details

  • Type: Improvement Improvement
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Duplicate
  • Affects Version/s: 2.0.7
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None
  • Number of attachments :
    1

Description

Currently the transitive dependencies appear to take priority over direct dependencies in the compile and test classpaths.
For example project A depends on B version 2 and C version 1:
A -> B.2
A -> C.1 -> B.1

When the tests are run, the classpath will be in an order similar to:
B.1:C.1:B.2

Since B.1 comes first in the classpath, it will be used when running the tests. But it seems that B.2 should be used when testing because it has the direct dependency.

Issue Links

Activity

Hide
Paul Gier added a comment -

Attaching a patch to the issue.
Looking at the code, it seems that the order of the list of dependencies for the classpaths is not predictable. This is due to the use of Sets for storing dependencies which don't preserve the order when an iterator is used.
The second issue is that the artifact collector uses a depth first traversal of the tree to gather the list. Which means that an artifact several levels deep off the first branch (1st direct dependency) will come before the 2nd direct dependency.
The attached patch sorts the dependencies in order of how far they are from the root and stored them in a LinkedHashSet so that this order is preserved.

Show
Paul Gier added a comment - Attaching a patch to the issue. Looking at the code, it seems that the order of the list of dependencies for the classpaths is not predictable. This is due to the use of Sets for storing dependencies which don't preserve the order when an iterator is used. The second issue is that the artifact collector uses a depth first traversal of the tree to gather the list. Which means that an artifact several levels deep off the first branch (1st direct dependency) will come before the 2nd direct dependency. The attached patch sorts the dependencies in order of how far they are from the root and stored them in a LinkedHashSet so that this order is preserved.
Hide
richard rattigan added a comment -

See my comment on MNG-1412.

I don't think the problem is that transitive dependencies take priority; rather the problem is that there is no defined ordering. Depth-first traversal (in order of dependency declaration) would allow adequate control. In this case, it would give a classpath of

B.2:C.1:B.1

Reversing the dependencies in the pom:

A -> C.1 -> B.1
A -> B.2

would give a classpath of:

C.1:B.1:B.2

Show
richard rattigan added a comment - See my comment on MNG-1412. I don't think the problem is that transitive dependencies take priority; rather the problem is that there is no defined ordering. Depth-first traversal (in order of dependency declaration) would allow adequate control. In this case, it would give a classpath of B.2:C.1:B.1 Reversing the dependencies in the pom: A -> C.1 -> B.1 A -> B.2 would give a classpath of: C.1:B.1:B.2
Hide
Paul Gier added a comment -

Yes, I agree that there should be a well defined order for dependencies in the classpath instead of the random order we have now.

The problem I experienced with depth-first ordering is that we had some transitive dependencies that were actually re-named older versions of direct dependencies. In the example above, imagine that B1 is actually an older version of B2. Now I'm going to be compiling against the older versions of the classes that are contained in B1 instead of the newer classes listed in my dependencies.

I can take care of this through using exclusions, but with a big dependency tree this can become pretty tedious. If MNG-1977 was resolved it would be easier for me to do this exclusion.

I think it would be better to have a breadth first order in the edge case that two classes from different dependencies have the same fully qualified name.

Show
Paul Gier added a comment - Yes, I agree that there should be a well defined order for dependencies in the classpath instead of the random order we have now. The problem I experienced with depth-first ordering is that we had some transitive dependencies that were actually re-named older versions of direct dependencies. In the example above, imagine that B1 is actually an older version of B2. Now I'm going to be compiling against the older versions of the classes that are contained in B1 instead of the newer classes listed in my dependencies. I can take care of this through using exclusions, but with a big dependency tree this can become pretty tedious. If MNG-1977 was resolved it would be easier for me to do this exclusion. I think it would be better to have a breadth first order in the edge case that two classes from different dependencies have the same fully qualified name.
Hide
Carlos Sanchez added a comment -

Please move discussion to MNG-1412

Show
Carlos Sanchez added a comment - Please move discussion to MNG-1412

People

Vote (0)
Watch (5)

Dates

  • Created:
    Updated:
    Resolved: