Resolution strategy should use internal project dependencies by default

Working through adding exclusions on a project I’m porting from maven. I love how much more explicit the dependency resolution is and how much control is given over what goes where! However, I am noticing something interesting that I think could be improved as a default behavior.

Suppose I have multi-module project with a war project ‘webapp’ which depends on a jar project ‘utils’. ‘utils’ depends on ‘commons-IO’ at , say, 1.4, and ‘webapp’ depends on some other lib which depends on ‘commons-IO’ at version ‘2.4’. Currently, the dependency resolution on ‘webapp’ is picking version 2.1 because it is newer. ‘webapp’ does not explicitly declare a dependency on ‘commons-IO’ because it gets it transitively through ‘utils’. It looks like my options right now are (1) re-declare the dependency in ‘webapp’; or (2) write a custom resolution strategy that picks out my explicit versions. Neither of these seem optimal.

It would seem right for a default behavior that if a dependency is coming from (a) a parent/child/sibling project, versus (b) an external module, then the parent/child/sibling project should win.

Have I misunderstood anything here? Is there a better way to solve this than I have realized?

I don’t think that Gradle’s default conflict resolution strategy will change anytime soon (and there isn’t one best default anyway), but we might offer other strategies beyond ‘highest’ and ‘fail’. Personally, I’d like to see support for something like Maven’s ‘nearest’.

The best way to enforce versions of direct and transitive dependencies alike is to use ‘Configuration.resolutionStrategy.force’; see the Gradle Build Language Reference for details. To enforce versions across multiple projects in the same build, you can use ‘force’ inside ‘allprojects { … }’, ‘subprojects { … }’, or the like. With this you’ll get an effect similar to specifying versions using Maven’s ‘dependencyManagement’ element.

Sweet, that did the trick. Thanks.