The Bad Programmer

Gradle 2.14 Publish to Maven



I have a project from which I build a small library jar containing a subset of the project’s classes. The application is a client/server application and most clients of the server are also Java applications. The library helps us stay DRY so we don’t have to duplicate code in the client applications. The project was recently changed from an Ant+Ivy build to Gradle 2.14 and we publish our internal libraries to our own Nexus repository which is a Maven formatted repository. Publishing a secondary artifact (i.e. not the main artifact of the project) to Nexus with Gradle turned into an exercise of frustration and almost made me say “fuck it” and stick with Ant+Ivy (where this is trivial).

Note though that my solution uses an incubating feature of Gradle 2.14. I could not figure out how to do this without using an incubating feature. I believe this stems from Maven’s mind-numbingly stupid and dogmatic insistence that a project can only have one artifact (seriously, WTF?!?!). For some reason Gradle appears to have went along with that approach before adding this incubating feature.

The first step is to create a jar that only contains the classes I want in the library.

def clientLibName = "libraryName"
task createClientLib(type: Jar, dependsOn: ["clean", "compileJava"]) {
    from "$buildDir/classes/main"
    archiveName = "${clientLibName}.jar"
    destinationDir = new File('./dist')
    includes = ["**/enums/*",
                "**/messages/ActionType.*",
                "**/messages/XmlActionType",
                "**/messages/cti/*",
                "**/Foo.*",
                "**/MessageAdapterInformation.*",
                "**/Supervisor.*",
                "**/Bar.*"] as Set
}

Once that was done it was just a matter of using the new publishing task. To use this task you have to apply the “maven-publish” plugin at the top of your build:

apply plugin: 'maven-publish' 
def clientLibVersion = "1.0"
def clientLibName = "libraryName"
def repositoryUrl = "http://host:port/nexus/content/repositories/your-repository"
publishing {
    repositories {
        maven {
            url "${repositoryUrl}"
            credentials {
                username = "yourUsername"
                password = "yourPassword"
            }
        }
    }

    publications {
        maven(MavenPublication) {
            artifact createClientLib
            groupId 'com.foo'
            artifactId "${clientLibName}"
            version "${clientLibVersion}"
        }
    }
}

The key line is:

artifact createClientLib

This tells Gradle that the artifact to be published is the output of the “createClientLib” task.

To run the task you simply type:

gradle publish 

Full example:

apply plugin: 'java' 
apply plugin: 'maven-publish' 

def clientLibVersion = "1.0"
def clientLibName = "libraryName"
def repositoryUrl = "http://host:port/nexus/content/repositories/your-repository"

task createClientLib(type: Jar, dependsOn: ["clean", "compileJava"]) {
    from "$buildDir/classes/main"
    archiveName = "${clientLibName}.jar"
    destinationDir = new File('./dist')
    includes = ["**/enums/*",
                "**/messages/ActionType.*",
                "**/messages/XmlActionType",
                "**/messages/cti/*",
                "**/Foo.*",
                "**/MessageAdapterInformation.*",
                "**/Supervisor.*",
                "**/Bar.*"] as Set
}

publishing {
    repositories {
        maven {
            url "${repositoryUrl}"
            credentials {
                username = "yourUsername"
                password = "yourPassword"
            }
        }
    }

    publications {
        maven(MavenPublication) {
            artifact createClientLib
            groupId 'com.foo'
            artifactId "${clientLibName}"
            version "${clientLibVersion}"
        }
    }
}