How resolutionStrategy works when included from an external resource

Hello,

I’m trying to solve a particular use-case:

  1. I have a utility jar in a maven repository which handles logging for all of my applications
  2. To use the utility dependency, it requires a project not include log4j, or commons-logging.

Instead of writing a bunch of exclude statements in my other dependency declarations, I would like to include a utility-script.gradle which injects a resolutionStrategy which examines the dependency graph and rejects all log4j or commons-logging dependencies from the dependency graph.

Furthermore, I want the utility-script.gradle file to come from a jar within the maven repository, such that developers have a centralized place to pull utility scripts using our natural repository setup (as opposed to setting up a new http server to serve utility scripts.)

I have the following in a logging.jar deployed in my maven repository (utility-script.gradle):

configurations.all {
  resolutionStrategy {
    componentSelection {
      withModule("log4j:log4j") { ComponentSelection selection ->
        selection.reject("Logging-Utility Ejects log4j dependencies!")
      }
      withModule("commons-logging:commons-logging") { ComponentSelection selection ->
        selection.reject("Logging-Utility Ejects commons-logging dependencies!")
      }
    }
  }
}

In my project’s build file i have:

buildscript {
  dependencies { classpath 'x.y.z.utilities:logging:1.0+' }
}

apply from: project.buildscript.classLoader.getResource('utility-script.gradle').toURI()

dependencies {
  compile 'x.y.z.utilities:logging:1.0+'
  compile 'x.y.z.site:mycode:1.0+'
}

When I build, i get the following:

Could not resolve all dependencies for configuration ':myproject:compile'.
> Could not find log4j:log4j:1.2.17.
  Searched in the following locations:
  file:/Users/tercan/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.pom
  http://myrepo:8081/nexus/content/groups/myrepo-build/log4j/log4j/1.2.17/log4j-1.2.17.pom
  http://myrepo:8081/nexus/content/groups/myrepo-proxy/log4j/log4j/1.2.17/log4j-1.2.17.jar
Required by:
  x.y.z.myproject:myproject:1.0-SNAPSHOT > x.y.z.site:mycode:1.0

BUT if i take the script defined in logging.jar and paste it directly into my project’s build script, OR, paste the script into a local file and include that file in my project’s build script, it works! So I guess this is a question about how gradle “scopes” instructions in my utility jar’s script? It obviously worked at rejecting the dependencies from lookup in the filesystem, but failed at ejecting the dependencies in the dependency graph of the compile configuration…

I’m not sure why it would work at all, because the error you are getting is exactly what I would expect. If I understand what you are trying to do, a component selection rule is not what you are after. A selection rule is designed to reject a particular candidate dependency, but it doesn’t exclude the dependency from the graph at all. It expects to find at least one candidate that is accepted (i.e. not rejected). In the rules you provided, it would reject all candidate dependencies so at the end of the resolution there would be an unresolved dependency and the error you got is what should happen.

Instead, I think you just want an “all” exclude rule:

configurations {
    all*.exclude group: 'log4j', module: 'log4j'
    all*.exclude group: 'commons-logging', module: 'commons-logging'
}

(sigh) I thought I tried that and it didn’t work complaining it could not find “exclude” on a particular configuration, but your syntax worked great! I must have fat fingered something prior. This is much simpler! :smile:

Thanks so much!