Gradle, SpringBoot, MavenPublish - Publication only contains dependencies and/or constraints without a version
Asked Answered
R

3

18

I'm using maven-publish plugin in Gradle to publish my Spring Boot application jar. I run the usual task: ./gradlew artifactorypublish. However, the following error appeared, which I couldn't understand the meaning of:

> Task :assembleArtifact
> Task :application-jar:compileJava UP-TO-DATE
> Task :application-jar:processResources UP-TO-DATE
> Task :application-jar:classes UP-TO-DATE
> Task :application-jar:jar SKIPPED
> Task :generateMetadataFileForMavenJavaPublication FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':generateMetadataFileForMavenJavaPublication'.
> Invalid publication 'mavenJava':
    - Publication only contains dependencies and/or constraints without a version. You need to add minimal version information, publish resolved versions (https://docs.gradle.org/6.1/userguide/publishing_maven.html#publishing_maven:resolved_dependencies) or reference a platform (https://docs.gradle.org/6.1/userguide/platforms.html)

My build.gradle:

plugins {
    id 'org.springframework.boot' version '2.2.6.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
    id 'maven-publish'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

publishing {
    publications {
        mavenJava(MavenPublication){
            components.java
        }
    }
}

...

Versions:
Gradle 6.1
Spring Boot 2.2.6 (mostly generated from Spring Boot Initializr)

Ranchod answered 29/4, 2020 at 11:37 Comment(0)
C
17

The problem that you're facing is actually the desired behavior because of the change - https://github.com/gradle/gradle/pull/11388 that came along with Gradle 6.0.1

The thing is that Gradle requires you to provide a proper version of dependencies so as to disallow users from publishing an invalid Gradle Module Metadata. The discussions on the issues below will help you to get a deeper insight into this

https://github.com/gradle/gradle/issues/11862

https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/262

Now, in your case, there are two solutions that you can choose from

publishing {
    publications {
        mavenJava(MavenPublication){
            // bootJar is the default build task configured by Spring Boot
            artifact bootJar
        }
    }
}

or

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java

            versionMapping {
                usage('java-api') {
                    fromResolutionOf('runtimeClasspath')
                }
                usage('java-runtime') {
                    fromResolutionResult()
                }
            }
        }
    }
}

More information on the second option can be found on this link - https://docs.gradle.org/6.6.1/userguide/publishing_maven.html

Cerebrum answered 10/9, 2020 at 18:31 Comment(1)
FYI artifact bootJar skips the generation of a .module metadata for me and, looking at the source code of DefaultMavenPublication.java, it always will. @Isank can you elaborate a bit more on the solution using versionMapping. Your links to sources are brilliant but leave me asking how one would get to the solution, rather than how the solution works. E.g. where do I find info on the strings java-api and java-runtime?Maricruzmaridel
B
9

Extend the answer by @Nakamura, If you make a project to be Springboot Library and need to set:

bootJar {
    enabled=false
}

jar {
    enabled=true
}

You can set :

publishing {
    publications {
        mavenJava(MavenPublication){
            // jar is the default build task configured by Spring Boot if bootJar=false
            artifact jar
        }
    }
}
Below answered 8/6, 2020 at 5:46 Comment(0)
R
6

After messing around for a while, I found the solution:

publishing {
    publications {
        mavenJava(MavenPublication){
            // bootJar is the default build task configured by Spring Boot
            artifact bootJar
        }
    }
}

Detailed Explanation

This is because components.java is configured for default java plugin task: jar or war. However for Spring Boot, after applying plugin org.springframework.boot, the default task become bootJar or bootWar.

(For your reference) From Spring Boot doc:

Executable jars can be built using the bootJar task. The task is automatically created when the java plugin is applied and is an instance of BootJar. The assemble task is automatically configured to depend upon the bootJar task so running assemble (or build) will also run the bootJar task.

Therefore, the artifact could not be correctly identified by components.java. We should point to bootJar or bootWar instead.

Reference: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#publishing-your-application-maven-publish

Ranchod answered 29/4, 2020 at 11:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.