Extract file from jar dependency defined against maven repo


#1

I have a build.gradle file with a buildScript block like this

buildscript {
    repositories {
        maven { url 'http://myrepo/content/repositories/snapshots' }
        maven { url 'http://myrepo/content/repositories/releases' }
    }
    configurations.all {
        // check for updates every build (if we are using snapshot with the same version)
        resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    }
    dependencies {
        classpath group: 'com.mycompany.dev', name: 'stuffs-common', version: '0.0.1-SNAPSHOT'
    }
}

Inside the stuffs-common.jar are two text files at the root level that I want to be extracted and copied to the build output folder. Currently all that makes it to the folder are those dependencies specifically named (i.e. com.mycompany.dev).

How can I extract arbitrary files from a jar that is referenced as a dependency in this manner?


(uklance) #2
configurations {
   stuffCommon { transitive = false } 
} 
dependencies {
   stuffCommon 'com.mycompany:stuff-common:1.0' 
} 
task unzip(type: Copy) {
   from zipTree(configurations.stuffCommon.singleFile).matching {
      include 'foo.txt'
      include 'bar.txt'
   } 
   into "$buildDir/unzipped" 
} 

#3

Hi Lance, thank you for the reply. I tried adding this code to the buildScript block after the “dependencies” sub-block above, but I get this error:

What went wrong:
A problem occurred evaluating root project 'myproject'.
Could not find method stuffsCommon() for arguments [com.mycompany.dev:stuffs-common:0.0.1-SNAPSHOT] 
on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

Just for fun I also moved your snippet outside the buildScript block but got a different error.

* What went wrong:
A problem occurred evaluating root project 'myproject'.
> Could not resolve all dependencies for configuration ':stuffsCommon'.
   > Cannot resolve external dependency com.mycompany.dev:stuffs-common:0.0.1-SNAPSHOT because no repositories are defined.
     Required by:
         project :

So this tells me it must be inside the buildScript block, however I can’t get passed the error I pasted above. Just for reference this is what the buildScript block looks like now.

buildscript {
    repositories {
        maven { url 'http://myrepo/content/repositories/snapshots' }
        maven { url 'http://myrepo/content/repositories/releases' }
    }
    configurations.all {
        // check for updates every build (if we are using snapshot with the same version)
        resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    }
    dependencies {
        classpath group: 'com.mycompany.dev', name: 'stuffs-common', version: '0.0.1-SNAPSHOT'
    }
    configurations {
        stuffsCommon { transitive = false }
    }
    dependencies {
        stuffsCommon 'com.mycompany.dev:stuffs-common:0.0.1-SNAPSHOT'
    }
    task unzip(type: Copy) {
        from zipTree(configurations.stuffsCommon.singleFile).matching {
            include 'foo.txt'
            include 'bar.txt'
        }
        into "$buildDir"
    }
}

(uklance) #4

The configuration, dependency and repository must be declared together. Either in the buildscript closure or outside (ie in the main project block).

The task can only be defined in the main project block (not in the buildscript closure)

See ScriptHandler and Project javadocs

Could not find method stuffsCommon()

You won’t get that error if the configuration and dependency are declared in the same block. I can only assume a misspelling (I notice you’ve changed stuffCommon to stuffsCommon)

If you declare your confguration & dependency in the buildscript block, you’ll need to change the task to

task unzip(type: Copy) {
   from zipTree(buildscript.configurations.stuffsCommon.singleFile)

#5

Thank you very much, its hard to post the complete final solution because someone came in and refactored parts of this already :slight_smile: However I will say this for reference:

I added a configuration to the buildScript closure:

configurations {
    stuffsCommonJar
}

I changed the dependency reference for the given jar to have the configuration label:

stuffsCommonJar 'com.mycompany.dev:stuffs-common:0.0.1-SNAPSHOT'

Then I added a task to the main project block

task extractScripts(type: Copy) {
    from zipTree(configurations.stuffsCommonJar.singleFile).matching {
        include '**/foo.txt'
        include '**/bar.txt'
    }
    into 'build/resources/main'
    includeEmptyDirs = false
}

compileJava.dependsOn(extractScripts)

Once these pieces were in place the two files are extracted properly to the build output folder. Thanks!


#6

I’ve tried this but gradle can’t find the dependency at configuration time.

I’ve added a configuration called clientWar, added a dependency for that configuration and a copy task which tries to access the war file. Even just printing it out with
println(configurations.clientwar.singleFile);
results in the error:

A problem occurred evaluating project ‘:server’.

Could not resolve all dependencies for configuration ‘:server:clientwar’.
Could not find com.boss:boss-client:0.0.0-SNAPSHOT.
Required by:
com.boss.boss-server:server:0.0.0-SNAPSHOT

If I put the println in a doLast block of a non-copy task then it finds it fine. However the copy task won’t run if it’s in a doLast block because it’s always UP-TO-DATE.


#7

I think mine didn’t work because I had no closure in my ‘from’ statement. So I had:

task copyWar(type: Copy) {
    from zipTree(configurations.clientwar.singleFile)
    into 'temp/clientWar'
}

If I put the from value inside a closure:
from { zipTree(configurations.clientwar.singleFile) }

then it worked. The copy task input is resolved at execution time and not configuration time, and the task always runs.