is there a way I can use dependency substitution t...
# gradle
j
is there a way I can use dependency substitution to substitute a particular module with a locally patched
.jar
I have? I know I can substitute using
project(":patched-project")
but I’m trying to avoid having to pull in the entire other project because it’s huge, creates CI implications, and the patch is a temporary solution when I try to swap
implementation("the.original:dependency")
with
implementation("libs/patched.jar")
that creates a whole world of other problems because the dependencies-of-dependency don’t come into the project, so I get a ton of `NoClassDefFoundError`s, and if I build them into the
.jar
that creates duplicate class errors, so I am wondering if there’s some trick I can use with dependency substitution to solve this problem, or is there a simpler way that I don’t know about?
e
you could set up a simple maven repo with your patched jar and dependency metadata
r
I had a similar use case where I needed to patch a single file in a dependency. I used Gradle to patch the dependency for me, with a configuration that resembled something like this:
Copy code
// Create a configuration that includes the jar dependencies we wish to patch
val jarsToModify = configurations.create("jarsToModify") { isTransitive = false }

dependencies {
    // Add the original dependency as a depndency of the `jarsToModify` config
    jarsToModify("the.original:original-dependency")
    
    // Add a 'normal' implementation dependency on a modified version of the above jar (which we will build below)
    implementation(files("${project.buildDir}/libs/modified-jars/modified-dependency.jar") {
        builtBy("createModifiedDependency")
    })
}

tasks {
    // Build a modified version of the dependency, using our own version of the `ClassToPatch.java` file
    // (located in our own project in the directory: `src/dependency_modified/java/`)
    register<Jar>("createModifiedDependency") {
        val patchDirectory = "com/original/package/"
        val patchFile = "ClassToPatch.java"

        // Input: All the original jar contents, except the file(s) to replace
        from(zipTree(jarsToModify.first { it.name.startsWith("original-dependency") })) {
            exclude("$patchDirectory/$patchFile")
        }
        // Input: The modified mapping file
        from("src/dependency_modified/java") {
            include(patchFile)
            into(patchDirectory)
        }
        
        // Output: the file `build/libs/modified-jars/modified-dependency.jar`
        archiveBaseName.set("modified-dependency")
        archiveVersion.set("")
        destinationDirectory.set(file("${project.buildDir}/libs/modified-jars"))
    }
}
this basically makes the creation of the patched jar part of the Gradle build, which also allows for easier upgrading of the dependency when needed (although I left out versions in the example, of course they can be easily added). I applied this as a 'temporary' patch a few years ago in some project, pretty sure it's still there, up and running 😛
a
you could try substituting the subproject https://docs.gradle.org/current/userguide/resolution_rules.html#sub:project_to_module_substitution or maybe use a transformer to swap the jar https://docs.gradle.org/current/userguide/artifact_transforms.html The simplest way is probably just copy&paste the
dependencies {}
from
:patched-project
, and include the jar
100 Views