Search code examples
javamavengradledependencies

What does gradle import fom a war dependency and how can I control/manipulate the war contents?


I added this artifact which is a war to my gradle project dependencies. I need to extend some classes, and use a modified servlet contexts from it.

I was expecting the war to be imported as is then I would use gradle tasks to manipulate to include the jars to dependencies, copy static resources to correct classpath etc. But gradle actually added a bunch of jars to dependency.

Im not sure if gradle scanned recursively all paths for jars and poms or probably just the jars under the WEB-INF/classes folder in the war. I can assume probably not the poms repositories as stated here.

Im I correct is assuming the jars in the WEB-INF/lib folder in the deflated war were not imported? its hard to tell as there are a lot of shared dependencies between my project and the war in question

Then whats the best way to declare a dependency on a war in the maven repo/jcenter if I need to extend and modify as I described at the top?

UPDATE:

I am now trying to use answer below and this solution https://discuss.gradle.org/t/how-to-add-an-artifactory-war-as-a-gradle-dependency/19804/2 , This only worked after moving the directory with the copied jars outside the buildDir my build.gradle

configurations {
    warOnly
}
dependencies {   
// not working    implementation fileTree('$buildDir/explodedWar/WEB-INF/classes')
    implementation fileTree('anotherDir/explodedWar/WEB-INF/classes')
//    implementation fileTree('$buildDir/explodedWar/WEB-INF/lib')
    implementation fileTree('anotherDir/explodedWar/WEB-INF/lib')
    warOnly 'ca.uhn.hapi.fhir:hapi-fhir-jpaserver-starter:4.2.0@war'
    }
    tasks.register("explodeWar",Copy) {
        from zipTree(configurations.warOnly.singleFile)
   //     into "${buildDir}/explodedWar"
    into "anotherDir/explodedWar"
    }
    compileJava {
        dependsOn explodeWar

    }

Solution

  • By declaring a dependency on a WAR, Gradle will simply add it to the list of files for the matching configuration. So if you add a WAR in implementation, it will simply be on the compileClasspath and runtimeClasspath without any processing.

    So for sure Gradle will not transform your WAR dependency in a dependency on the JARs it contains.

    If you want to use a WAR to copy and modify some of its content before repackaging it, you can use an isolated and custom configuration to resolve it from a remote repositories. Then you will define a Gradle task that will take the files of that configuration as the input and do the required processing on the WAR. Note that the task could also be the starting point of a series of tasks manipulating the WAR to one output, then that output to another one, etc ...

    configurations {
        warOnly
    }
    dependencies {
        warOnly "com.pany:some-war:1.0"
    }
    tasks.register("copyWar", Copy) { // Register a copy task to modify the WAR
        from(zipTree(configurations.warOnly)) // I did not run this, so you may have to get to the single file instead
        // Regular copy configuration to decide a destination, perform on the fly changes, etc ...
    }