Working with a dependency on a bundle of JAR files

We have dependencies on a small boatload of jar files provided by a vendor. Previously, I’ve been adding these to our application using the uber-jar approach with no problems.

I want to bundle all those jars into a single zip/jar file and keep them in our Nexus repository.

For the most part, this question on accessing the contents of a dependency has helped me address the dependencies in builds of the various components that use those libraries. Specifically, I am doing this:

task extractJarBundle(type: Copy,dependsOn:[‘clean’,configurations.bundlecfg]) {

outputs.dir("$buildDir/lib")

from {

configurations.bundlecfg.collect { zipTree(it) }

}

into “$buildDir”

doLast {

sourceSets.main.compileClasspath += files(file("$buildDir/lib").listFiles())

}

}

compileJava.dependsOn extractJarBundle

This is needed because when the ‘bundlecfg’ is pulled down from the artifact repository, it’s a single archive of all the other jar files we need to access.

That part works fine. But some of these components are also used in a plugin resident in ‘buildSrc’. Now I’m having trouble because the plugin itself has dependencies on jars in this bundle-o-jars but I don’t believe the ‘buildscript’ block can do what I’m doing in the stand-alone projects in order to first unzip this bundle and then add it to the ‘buildscript’ classpath.

This is getting pretty ugly, maybe I’m not taking the right approach. Any suggestions?

Thank you! Andy

You can have a build.gradle in buildSrc that does the same thing, I believe. Are you having problems with that and do you have a small project to recreate?

Looking at your code snippet, I notice a few things you could improve. Because you’re adding to the main classpath during the execution (vs configuration) phase, you could run into ordering problems.

A more Gradle-idiomatic looking example might look like this:

configurations {
  bundlecfg
}
  task extractJarBundle(type: Copy, dependsOn: configurations.bundlecfg) {
  from { configurations.bundlecfg.collect { zipTree(it) } }
  into "${buildDir}/lib"
}
  dependencies {
  bundlecfg 'group:bundle:someVersion'
  compile fileTree(tasks.extractJarBundle.outputs.files.singleFile) {
     builtBy tasks.extractJarBundle
     include "**/*.jar"
  }
}

This uses the ‘builtBy’ property of the file collections to auto-wire things together (compileJava needs configurations.compile which needs extractJarBundle which needs configurations.bundlecfg).

Wow, I didn’t know I could do that with the ‘compile fileTree’ bit. I will give this a try and report back. Thank you!

Unfortunately, this doesn’t work for me in ‘buildSrc/build.gradle’. It doesn’t recognize ‘tasks.extractJarBundle’ (‘Could not find property ‘extractJarBundle’ on task set.’) Should it be OK to reference tasks of the main script from within the ‘buildscripts’ block? It seems the only configuration it recognizes is ‘classpath’. I can use ‘configurations.create(‘compile’)’ which it will recognize but I still can’t access the ‘extractjarBundle’ task.

I will try to put together a sample project to illustrate but if you have any ideas, that would be very much appreciated.

The ‘buildscript’ block cannot reference the remainder of the build script. It’s probably better to provide and pull in the Jars individually, rather than as a bundle. Alternatively, you could decouple your plugin’s code from the external Jars so that it can load them at runtime, rather than having them on the buildscript class path.

Ok, I see. I will chew on those options. I think decoupling the plugin might work well in the end. Thanks for your help!

For a moment I thought that declaring a custom configuration for the ‘buildscript’ block could help to solve the problem, but this doesn’t appear to be possible.