Using Gradle 1.0 milestone 8.
My project uses slf4j+Logback for logging, so I want to prevent any transitive deps on log4j from polluting my classpath. Thus, I added a global exclusion, like so:
configurations {
all*.exclude group: "log4j", module: "log4j"
}
However, I am using a test library (hadoop-minicluster
) which has a runtime dependency on log4j, so I now need to allow a log4j dependency for my test runtime. I tried adding a direct dependency on log4j:
testRuntime group: "log4j", name: "log4j", version: "1.2.15"
and editing my exclusion code (a bit of a hack):
configurations.findAll {!it.name.endsWith('testRuntime')}.each { conf ->
conf.exclude group: "log4j", module: "log4j"
}
But this does not work. Adding the exclusion to the testCompile conf automatically adds it to all inheriting configurations as well, including testRuntime. And it seems that this exclusion overrides even the explicit dependency that I added.
It appears that this is expected behaviour for Gradle. From the docs:
If you define an exclude for a particular configuration, the excluded transitive dependency will be filtered for all dependencies when resolving this configuration or any inheriting configuration.
So is there any other way to do what I want to achieve?
Ideas:
myTestRuntime
that does not extend from testCompile, and use that for my test classpath.
Option 1) per-dependency exclude rules. When you specify a dependency in your build script, you can provide an exclude rule at the same time telling Gradle not to pull in the specified transitive dependency. For example, say we have a Gradle project that depends on Google's Guava library, or more specifically com.
Multiple transitive dependencies can be excluded by using the <exclusion> tag for each of the dependency you want to exclude and placing all these exclusion tags inside the <exclusions> tag in pom. xml. You will need to mention the group id and artifact id of the dependency you wish to exclude in the exclusion tag.
A variant of a component can have dependencies on other modules to work properly, so-called transitive dependencies. Releases of a module hosted on a repository can provide metadata to declare those transitive dependencies. By default, Gradle resolves transitive dependencies automatically.
compileOnly. Gradle adds the dependency to the compile classpath only (that is, it is not added to the build output). This is useful when you're creating an Android module and you need the dependency during compilation, but it's optional to have it present at runtime.
For now I have managed to work around the problem, but I still welcome any better solutions.
Here is what I ended up doing:
Add a new configuration just for log4j:
log4j(group: 'log4j', name: 'log4j', version: '1.2.15') {
transitive = false
}
Leave the config-level exclusion for all configurations apart from that one:
configurations.findAll {!it.name.endsWith('log4j')}.each { conf ->
conf.exclude group: "log4j", module: "log4j"
}
Add the log4j configuration to my tests' classpath:
test {
classpath += configurations.log4j
}
This way we can get log4j.jar onto the classpath, even though it is excluded from the testRuntime configuration.
Even i encountered similar situation where i need to exclude spark jars from including in fat jar but test cases requires spark jars to execute.so below configuration worked for me. So basically i am adding compile time dependencies to test classpath. so for your problem below solution should work
configurations{
runtime.exclude group: 'log4j'
}
test {
classpath += configurations.compile
}
You should not need to define an exclusion. Unless you reconfigured something, a project's testRuntime
configuration will only be used for that project's test
task.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With