Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BootJar + MavenJar. Artifact wasn't produced by this build

I have a sample project with the following hierearhy:

Sample (root)
   -- model (simple jar)
   -- api   (springboot jar)

I want to publish both generated jars: plain jar & bootJar to my localRepository.

gradlew clean build -xTest publishToMavenLocal    

However, the following error occures:

* What went wrong:
Execution failed for task ':api:publishMavenJavaPublicationToMavenLocal'.
> Failed to publish publication 'mavenJava' to repository 'mavenLocal'
   > Artifact api.jar wasn't produced by this build.

The root build.gradle is a follows:

plugins {
    id 'java'
    id "org.springframework.boot" version "2.2.5.RELEASE" apply false
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
group 'sample'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}
ext {
    artifactVersion = version
    springBootVersion = "2.2.5.RELEASE"
}

allprojects {
    apply plugin: 'java'
    apply plugin: 'idea'
    apply plugin: 'maven'
    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }
    repositories {
        mavenCentral()
        jcenter()
    }
}

subprojects {
    apply plugin: "io.spring.dependency-management"
    apply plugin: "maven-publish"

    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8

    dependencyManagement {
        imports {
            mavenBom "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
        }
    }
    dependencies {
        implementation "org.springframework.boot:spring-boot-dependencies:${springBootVersion}"
    }

    publishing {
        publications {
            mavenJava(MavenPublication) {
                groupId project.group
                artifactId project.name
                version project.version

                from components.java
            }
        }
    }
}

api build.gradle

apply plugin: 'org.springframework.boot'

dependencies {
    compile project(":model")
    implementation "org.springframework.boot:spring-boot-starter-web"
}

bootJar {
}

Adding bootJava task to api build.gradle allowes to publish the bootJar directly from api module, but the root publish task remains broken.

publishing {
    publications {
        bootJava(MavenPublication) {
            artifact bootJar
        }
    }
}

I've tried almost every solution from docs & google, but none seem to work. Can anyone explain, what is misconfigured?

Gradle version: 6.3

like image 904
Ermintar Avatar asked Apr 13 '20 22:04

Ermintar


2 Answers

If you are using gradle kotlin dsl add the equivalent in your build.gradle. It worked for me

 configurations {
    val elements = listOf(apiElements, runtimeElements)
    elements.forEach { element ->
        element.get().outgoing.artifacts.removeIf { it -> it.buildDependencies.getDependencies(null).contains(tasks.jar.get())}
        element.get().outgoing.artifact(tasks.bootJar.get())
    }
}
like image 168
Sujay Bhowmick Avatar answered Sep 20 '22 12:09

Sujay Bhowmick


Excerpt from

Starting from Gradle 6.2, the main jar task is disabled by the Spring Boot application, and the component expects it to be present. Because the bootJar task uses the same file as the main jar task by default, previous releases of Gradle would either:

  • publish a stale bootJar artifact
  • or fail if the bootJar task hasn’t been called previously

To simple workaround would be configuring the outgoing configurations. For multi-module Gradle project, place the below configuration in the service module(spring boot module).


dependencies {
          .....
}

configurations {
    [apiElements, runtimeElements].each {
        it.outgoing.artifacts.removeIf {
            it.buildDependencies.getDependencies(null).contains(jar)
        }
        it.outgoing.artifact(bootJar)
    }
}

Note: There is no need for changing anything with artifactory task if it was configured correctly. This working solution has been tested with Gradle 6.4.1.

Don't try the alternate suggestion that they provided, because classifier attribute is deprecated in recent versions, also altering the bootJar task with custom configuration would result in improper uber jar construction, and if you extract the generated jar distributive, you could find the missing BOOT-INF directory and necessary META-INF/MANIFEST.MF values.

jar {
   enabled = true
}

bootJar {
   classifier = 'application'
}

Update:

From Spring Boot 2.5.0, jar task generates an additional jar archive which ends with -plain.jar. It may break someone's build if they have used some patterns like *.jar to copy the build archive, hence, to restrict the additional jar creation, the following jar task configuration code snippet should be used.

jar {
    enabled = false
}
like image 38
Prasanth Rajendran Avatar answered Sep 19 '22 12:09

Prasanth Rajendran