Gradle exclude group from dependant subproject - java

Given a gradle project A having a dependency on project B (no common parent)
compile project('B'){
exclude group: 'org.slf4j'
}
how do we exclude transitive dependency group from a project we depend upon? (this piece of script will fail as there is no exclude for compile projet(..))
and more general question : is there an elegant way to exclude a particular group from all dependancies except if its a first level dependency?
for example we may have a bunch of libraries, and each may declare its logging environment, but by excluding all known groups of slf4j, its implementations and declaring specific version, we would ensure we don't have any version conflicts and would control version on module level.

Here is an example from the Gradle documentation of how to exclude a transitive dependency (I guess that is what you meant by "except if its a first level dependency") on project level:
configurations {
compile.exclude module: 'commons'
all*.exclude group: 'org.gradle.test.excludes', module: 'reports'
}
See 52.4.7. Excluding transitive dependencies here
You can either specify the dependency directly with the desired version or use a forced version resolution strategy

Related

Excluding a specific package from a dependency in Gradle

I have a dependency in one of my project
implementation (group: 'com.ibm.cloud', name: 'ibmcloudsql-jdbc', version: '2.5.34')
I want to specifically exclude a package from this jar, i.e
com.ibm.cloud.sdk.core.http
Is there a way? I already tried this but did not work.
implementation (group: 'com.ibm.cloud', name: 'ibmcloudsql-jdbc', version: '2.5.34'){
exclude module: 'com.ibm.cloud.sdk.core.http'
}
You can't use dependency management to remove part of a dependency - with dependency management it's either the complete dependency or no dependency (and this is not limited to gradle - other dependency managers / build systems like maven or ivy also don't have this feature).
The exclude module can only be used to prevent inclusion of transitive dependencies (i.e. you need dependency com.xy:A and com.xy:A declares that it also needs com.xy:B - with exclude module you can prevent the inclusion com.xy:B)
It might be possible to create your own version of that dependency by manually removing the package com.ibm.cloud.sdk.core.http from the jar itself and adding that modified jar file to your project.

Excluding dependency from implementation files

I have a jar that I am including in my Android project using the following syntax
implementation files('lib/fm.liveswitch.jar')
fm.liveswitch has a dependency of org.bouncycastle that I am already including as a dependency of my project. How do I exclude bouncycastle from being included as part of the jar?
I have already tried each of the following:
implementation (files('lib/fm.liveswitch.jar')) {
exclude group: 'org.bouncycastle'
}
implementation (files('lib/fm.liveswitch.jar')) {
exclude module: 'org.bouncycastle'
}
implementation (files('lib/fm.liveswitch.jar'), {
exclude group: 'org.bouncycastle'
})
implementation files('lib/fm.liveswitch.jar') {
exclude group: 'org.bouncycastle'
}
But each time I get an error similar to the below:
Could not find method exclude() for arguments [{group=org.bouncycastle}] on object of type org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency
When you add file based dependencies, they have no dependency metadata and thus no transitive dependency information.
Given this, there is no point in trying to add an exclude.
Adding implementation files('lib/fm.liveswitch.jar') will only add fm.liveswitch.jar on the classpath, nothing else.
Now if that JAR contains some bouncycastle classes inside, it is a different story. Gradle has no direct way of letting you control the visibility of the contents of a JAR.
You would then have two options:
Since it is a local JAR, you can yourself remove the offending classes from it.
You could attempt to leverage artifact transforms

How to let dependencies in modules have higher precedence over build.gradle in the top level repository

My project repository tree looks like the following:
Project
module1
module1.gradle
module2
module2.gradle
...
build.gradle
Then in the build.gradle file there are some dependencies and some forced resolutionStrategies like
configurations.all {
resolutionStrategy {
cacheChangingModulesFor 0, 'seconds'
force 'org.apache.hadoop:hadoop-common:2.5.0-cdh5.3.3',
}
}
dependencies {
compile(group: 'org.apache.hadoop', name: 'hadoop-common', version: '2.6.0-cdh5.16.1')
}
However, module1.gradle defines a later version of hadoop-common like
compile group: 'org.apache.hadoop', name: 'hadoop-common', version: '2.5.0-cdh5.3.3'
I want to make this upgrade to my module1, module2..moduleX to use the '2.6.0-cdh5.16.1'. There are some projects that don't need the upgrade and should keep using the older version so I need to keep the forced dependencies in the top level build.gradle file. In fact, I don't want to touch any modules that I don't own.
Is there a way to specify at the module level to ALWAYS use whatever it is defined in the current module instead of inheriting from the top level build.gradle?
The force(..) statement at the top level is intended to override whatever version is specified in the modules.
You can re-override that force(..) statement by placing another force(..) statement inside the module build. This second force statement is evaluated after the top-level one, so it will re-override the module version.
You can place in the build.gradle file for your module:
configurations.all {
resolutionStrategy {
force 'org.apache.hadoop:hadoop-common:2.6.0-cdh5.16.1'
}
}
Note though that overriding and re-overriding versions can cause confusion. In example, people editing the top-level build will expect their force to be rightly applied to all modules- which isn't the case if you re-override that in the module.

Gradle dependency resolution - fetch only direct dependencies

I have a gradle project with the following dependencies declaration.
dependencies{
implementation 'com.github.gwtmaterialdesign:gwt-material:2.1'
implementation 'com.github.gwtmaterialdesign:gwt-material-addins:2.1'
implementation 'com.github.gwtmaterialdesign:gwt-material-themes:2.1'
implementation 'com.github.gwtmaterialdesign:gwt-material-table:2.1'
}
However, gwt-material-2.1 depends on gwt-user-2.8.2 and gwt-dev-2.8.2.
In turn they have numerous dependencies which are not required by my project.
I can disable transitive dependencies completely and manually add gwt-user and gwt-dev. However, I would like it to happen automatically but still fetch only 1st level dependencies.

Compile zip with gradle including libraries implemented by a sibling subproject

I have a java project made by some sibling modules. One of these modules is a library and I'm applying java-library plugin on it. All the other modules depend on it.
What I need to do is to automate the creation of a zip for each module, containing all the classes and all the dependencies needed for it to work (I'm deploying the zip as aws-lambda functions).
So far this is what I have achieved, but the resulting zip only contains module's classes. I thought that the problem might be the type of dependency I'm using (implementation) and I tried switching to the default one but gradle doesn't even success in building.
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
task buildZip(type: Zip) {
from compileJava
from processResources
from configurations.runtime
}
dependencies {
implementation project(':utils')
testCompile group: 'junit', name: 'junit', version: '4.12'
}
After some testing, I think I have the answer.
First: the order you declared the task and the dependencies is fine! It's OK to use a configuration before it's populated. I only say this because I indicated in my comments that it might be an issue.
Second, the issue here is the use of configurations.runtime. This does not extend implementation and api, so those dependencies are not included. runtime has been superseded by runtimeOnly, which hopefully makes the behaviour clear.
The following task definition should work:
task buildZip(type: Zip) {
from compileJava
from processResources
from configurations.runtimeClasspath
}

Categories