javamavengradlegroovymaven-publish

Java/Groovy/Gradle : How can I change the jar name (but not artifact-id) for publication?


Soon I will publish a new version of my library, which is composed of several modules. For this release, I'm now using Gradle 7, so I'm thinking about changing something that I feel needs to be fixed:

This is the library declaration (for example, the thread module):

group: 'com.intellisrc', name: 'thread', version: '2.8.0'

when published, it generates a jar with the name: thread-2.8.0.jar, which I would prefer to be: intellisrc-thread-2.8.0.jar as it is more descriptive (other than that, it is working without issues).

To fix it, one option is to change the artifact-id, so the declaration will become:

group: 'com.intellisrc', name: 'intellisrc-thread', version: '2.8.0'

But I would prefer not to change it as consumers would have to update it and it might be confusing.

I guess that if I can change the jar name and the publication files (pom.xml, module.json), it should work.

So far I was able to change the jar file name that it is generated inside build/libs/ using:

jar {
    archiveBaseName.set("intellisrc-" + project.name)
}

and inside publishing:

publishing {
    publications {
       mavenJava(MavenPublication) {
           artifactId project.name
           from components.java
           
           pom {
               ...
               archivesBaseName = "intellisrc-" + project.name
               ...
           }
       }
    }
}

By default, the pom-default.xml has no file names in it. I followed this recommendation, and added:

pom {
    properties = [
        "jar.finalName" : archivesBaseName + "-" + project.version
    ]
}

which adds in pom-default.xml file:

  <properties>
    <jar.finalName>com.intellisrc.core-2.8.0-SNAPSHOT</jar.finalName>
  </properties>

However in module.json the name hasn't changed:

...
      "files": [
        {
          "name": "thread-2.8.0.jar",
          "url": "thread-2.8.0.jar",
          "size": 92799,
          ...

Is there a way to change those values in module.json from gradle? I can think of decoding the json file and replace its values, but I hope there is a better way to do it.

When I execute gradle publishToMavenLocal, the jars installed on .m2/repository/com/intellisrc/ haven't changed: it is still thread-2.8.0.jar (despite being correctly in build/libs), I'm not sure why.

How can I rename the jar without changing the artifact-id so it works with publish and publishToMavenLocal?

This is the complete build.gradle:

plugins {
    id 'groovy'
    id 'java-library'
    id 'maven-publish'
    id 'signing'
}

def currentVersion = "2.8.0-SNAPSHOT"

allprojects {
    group = groupName
    version = currentVersion
    repositories {
        mavenLocal()
        mavenCentral()
    }
}

/**
 * Returns project description
 * @param name
 * @return
 */
static String getProjectDescription(String name) {
    String desc = ""
    switch (name) {
        case "core":
            desc = "Basic functionality that is usually needed " +
                    "in any project. For example, configuration, " +
                    "logging, executing commands, controlling " +
                    "services and displaying colors in console."
            break
        case "etc":
            desc = "Extra functionality which is usually very " +
                    "useful in any project. For example, monitoring " +
                    "Hardware, compressing or decompressing data, " +
                    "store data in memory cache, manage system " +
                    "configuration in a multithreading safe environment " +
                    "(using Redis as default), simple operations with " +
                    "bytes, etc."
            break
        case "db":
            desc = "Manage databases, such as MySQL, SQLite, " +
                    "BerkeleyDB, Postgresql. Create, store and " +
                    "perform CRUD operations to data without having " +
                    "to use SQL (a light-weight implementation as " +
                    "alternative to Hibernate)."
            break
        case "net":
            desc = "Classes related to networking. For example, " +
                    "sending emails through SMTP, connecting or " +
                    "creating TCP/UDP servers, getting network " +
                    "interfaces and perform netmask calculations, etc."
            break
        case "serial":
            desc = "Manage serial communication easily. It uses " +
                    "JSSC library on the background."
            break
        case "web":
            desc = "Create restful HTTP (GET, POST, PUT, DELETE, etc) " +
                    "or WebSocket application services. Manage JSON " +
                    "data from and to the server easily. It is build " +
                    "on top of Spark-Java Web Framework, so it is " +
                    "very flexible and powerful, but designed to be " +
                    "elegant and easier to use."
            break
        case "crypt":
            desc = "Offers methods to encode, decode, hash and encrypt " +
                    "information. It is built using the BountyCastle " +
                    "library and simplifying its usage without reducing " +
                    "its safety."
            break
        case "thread":
            desc = "Manage Tasks (Threads) with priority and watches " +
                    "its performance. You can create parallel processes " +
                    "easily, processes which are executed in an interval, " +
                    "as a service or after a specified amount of time. " +
                    "This module is very useful to help you to identify " +
                    "bottlenecks and to manage your main threads in a " +
                    "single place."
            break
        case "term":
            desc = "Anything related to terminal is in this module " +
                    "(except AnsiColor, which is in core). It uses JLine " +
                    "to help you create interactive terminal (console) " +
                    "applications easily. It also contains some tools " +
                    "to display progress with colors."
            break
        case "img":
            desc = "Classes for using Images (BufferedImage, File, FrameShot) " +
                    "and non-opencv related code, trying to keep dependencies " +
                    "to a minimum. It also includes common geometric operations."
            break
        case "cv":
            desc = "Classes for Computer Vision (extension to OpenCV). " +
                    "Convert image formats, crop, rotate images or draw " +
                    "objects on top of them. It simplifies grabbing images " +
                    "from any video source."
            break
    }
    return desc
}

subprojects {
    apply plugin: 'groovy'
    apply plugin: 'java-library'
    apply plugin: 'maven-publish'
    apply plugin: 'signing'

    dependencies {
        //def groovyVer = "2.5.14"
        def groovyVer = "3.0.7"
        def groovyExt = "3.0.8.7"
        def spock = "2.0-groovy-3.0"
        def junit = "4.13.2"

        boolean isDev = currentVersion.contains("SNAPSHOT")
        def deps = ["org.codehaus.groovy:groovy-all:${groovyVer}"]
        if(isDev) {
            deps.each { api it }
        } else {
            deps.each { compileOnly it } //Link it so we can choose version
        }
        // Always include groovy-extend and expose it to consumers:
        api "com.intellisrc:groovy-extend:${groovyExt}"
        testImplementation "org.spockframework:spock-core:${spock}"
        testImplementation "junit:junit:${junit}"
    }
    jar {
        archiveBaseName.set("intellisrc-" + archiveBaseName.get())
    }
    java {
        withSourcesJar()
        withJavadocJar()
    }
    // Used to publish to MavenLocal
    publishing {
        repositories {
            maven {
                def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2"
                def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots"
                url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
                credentials {
                    username = ossrhUsername
                    password = ossrhPassword
                }
            }
        }
       publications {
           mavenJava(MavenPublication) {
               artifactId project.name
               from components.java

               pom {
                   name = projectName + " : " + project.name.capitalize() + " Module"
                   description = getProjectDescription(project.name) ?: projectDescription
                   url = projectURL
                   inceptionYear = projectSince
                   archivesBaseName = "intellisrc-" + project.name
                   properties = [
                        "jar.finalName" : archivesBaseName + "-" + project.version
                   ]

                   licenses {
                       license {
                           name = 'GNU General Public License v3.0'
                           url = 'https://www.gnu.org/licenses/gpl-3.0.en.html'
                           distribution = 'repo'
                       }
                   }
                   developers {
                       developer {
                           id = authorId
                           name = authorName
                           email = authorEmail
                       }
                   }
                   scm {
                       url = projectURL
                       connection = "scm:git:${projectURL}.git"
                       developerConnection = "scm:git:${projectDevURL}"
                   }
               }
           }
       }
    }

    signing {
        required {
            !version.endsWith("SNAPSHOT")
        }
        sign publishing.publications.mavenJava
    }

    tasks.named('test') {
        // Use JUnit Platform for unit tests.
        useJUnitPlatform()
    }
}

Solution

  • This is 100% a bug. It's not just a "nice to have", this bug's presence breaks the ability for consumers of libraries that use modules with common names (i.e. "core") to include the same named JARs, if their dependencies happen to have the same version number.

    I ran into the same issue and filed a tracking bug. Hopefully it will be resolved in an upcoming version of Gradle.