Gradle: Upload a List of JARs Into Nexus/Artifactory
Want to see the beauty of Gradle in action? Here we'll learn how to build a custom task that uploads a list of JARs to Nexus or Artifactory.
Join the DZone community and get the full member experience.
Join For FreeMore and more Java projects are starting to use Gradle as their build tool. As a coder, you'll find the power back in your hands again after using it. Because Gradle itself is a Groovy script, a custom task can be easily and concisely created. Here is an example of loading a list of libraries into a Nexus or Artifactory server. Before trying to load it, let's start with a custom task.
configurations {
oneLib
}
artifacts {
oneLib file("path-to/one-lib.jar")
}
apply plugin: 'maven'
project.tasks.create('uploadOneLib', Upload.class) {
configuration = configurations.oneLib
repositories {
mavenDeployer {
repository(url: "${protReleaseUrl}") {
authentication(userName: "${protReleaseUser}", password: "${protReleasePswd}")
}
pom.version = "0.0.1"
pom.artifactId = "one-lib"
pom.groupId = "com.onelib"
}
}
}
The above Gradle DSL defines an "uploadOneLib" task to load one-lib.jar into the release repository as com.onelib:one-lib-0.0.1.jar (URL and credentials are provided by gradle.properties under ${user.home}/.gradle or the current folder). It extends the built-in task "Upload" to use Maven Deploy. If one-lib-0.0.1.jar has 5 dependent JARs, to load all of them, we can simply duplicate it for each one with slight modifications. But since Gradle has a loop construct, it would be nice to just list the libraries to be uploaded, the target URLs/credentials, some consideration to allow different URLs/credentials for different libraries, and some different classifiers for some libraries. The meta-data structure will look like:
{
"libs": [
{
"cfgName": "uploadInternal1"
, "groupId": "com.prot.zbank.client"
, "artifactId": "client-model"
, "version": "0.0.8"
, "jarLocation": "client/client-model.jar"
}
, {
"cfgName": "uploadInternal2"
, "groupId": "com.prot.zbank.client"
, "artifactId": "client-model"
, "classifier": "test"
, "version": "0.0.8"
, "jarLocation": "client/unit-test.jar"
}
, {
"cfgName": "uploadInternal3"
, "groupId": "com.prot.zbank.client"
, "artifactId": "client-service"
, "version": "0.0.9"
, "jarLocation": "client/rest-api.jar"
}
, {
"cfgName": "uploadOracleDriver"
, "groupId": "com.oracle"
, "artifactId": "ojdbc8"
, "version": "0.2b"
, "jarLocation": "3rd/ojdbc8.jar"
, "repoUrl": "http://a.b.com/repository/third-party/"
, "repoUser": "david"
, "repoPswd": "Passw0rd888"
}
]
, "repoUrl": "http://a.b.com/repository/zbank-project-release/"
, "repoUser": "george"
, "repoPswd": "Passw0rd999"
}
The model says to:
Upload from client/client-model.jar to com.prot.zbank.client:client-model-0.0.8.jar
Upload from client/unit-test.jar to com.prot.zbank.client:client-model-0.0.8-test.jar
Upload from client/rest-api.jar to com.prot.zbank.client:client-service-0.0.9.jar
Upload from 3rd/ojdbc8.jar to com.oracle:ojdbc8-0.2b.jar
The first 3 JARs are uploaded to http://a.b.com/repository/zbank-project-release/, and the last one will be uploaded to http://a.b.com/repository/third-party/.
Gradle shines for this kind of task. In about 50 lines of code, a custom task — "batchUpload" — is created for our needs.
apply plugin: 'maven'
def f = file("upload-list.json")
def m = f.exists() ? new groovy.json.JsonSlurper().parse(f) : null
task batchUpload() {
}
if (m == null || m.libs == null || m.libs.isEmpty()) {
batchUpload.doLast {
println "WARNING: no file to upload"
}
} else {
m.libs.each { lib ->
configurations.create( "${lib.cfgName}" )
if (lib.classifier == null) {
artifacts.add("${lib.cfgName}", file("${lib.jarLocation}"))
} else {
artifacts.add("${lib.cfgName}", file("${lib.jarLocation}")) {
setClassifier( "${lib.classifier}" )
}
}
def repoUrl = lib.repoUrl != null ? lib.repoUrl : m.repoUrl;
def repoUser = lib.repoUser != null ? lib.repoUser : m.repoUser;
def repoPswd = lib.repoPswd != null ? lib.repoPswd : m.repoPswd;
def classifier = lib.classifier == null ? "" : ("-" + lib.classifier)
println "define task '${lib.cfgName}' to upload ${lib.jarLocation} to ${repoUrl} as ${lib.groupId}:${lib.artifactId}-${lib.version}${classifier}.jar"
project.tasks.create("${lib.cfgName}", Upload.class) {
configuration = configurations[lib.cfgName]
repositories {
mavenDeployer {
repository(url: "${repoUrl}") {
authentication(userName: "${repoUser}", password: "${repoPswd}")
}
pom.version = "${lib.version}"
pom.artifactId = "${lib.artifactId}"
pom.groupId = "${lib.groupId}"
}
}
}
batchUpload.dependsOn "${lib.cfgName}"
}
}
It loops through each lib from the JSON model, creates a custom task to perform the upload, then tells the "batchUpload" task to depend on this task, so running "gradle batchUpload" will try to upload all libraries. Running "gradle ${lib.cfgName}" will just upload that ${lib} only. I can feel the beauty of this simplicity after using Gradle for one year.
Opinions expressed by DZone contributors are their own.
Comments