问题
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
回答1:
As stated by gradle documentation here:
Starting from Gradle 6.2, Gradle performs a sanity check before uploading, to make sure you don’t upload stale files (files produced by another build). This introduces a problem with Spring Boot applications which are uploaded using the components.java component
More explanation is available in the link above. They propose the following workaround that I personally tried and worked for me :
configure the outgoing configurations
configurations {
[apiElements, runtimeElements].each {
it.outgoing.artifacts.removeIf { it.buildDependencies.getDependencies(null).contains(jar) }
it.outgoing.artifact(bootJar)
}
}
here after the configuration from my build.gradle:
....
apply plugin: 'maven-publish'
...
configurations {
[apiElements, runtimeElements].each {
it.outgoing.artifacts.removeIf { it.buildDependencies.getDependencies(null).contains(jar) }
it.outgoing.artifact(bootJar)
}
....
}
publishing {
publications {
myPublication(MavenPublication) {
groupId groupId
artifactId artifactId
version version
from components.java
versionMapping {
usage('java-api') {
fromResolutionOf('runtimeClasspath')
}
usage('java-runtime') {
fromResolutionResult()
}
}
}
}
repositories {
maven {
url azureRepoUrl
name azureRepoName
credentials {
username azureRepoUserName
password azureRepoAccessToken
}
}
}
}
回答2:
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'
}
回答3:
I could get this worked by just adding artifact bootJar
in the publishing task as shown below and with out adding any configurations as suggested in the gradle documentation. I believe this could be working same as their first workaround in the documentation. Tested with gradle 6.5.1
publishing {
publications {
mavenJava(MavenPublication) {
artifact bootJar
artifact sourceJar {
classifier "sources"
}
}
}
}
project.tasks.publish.dependsOn bootJar
回答4:
According to the 'Gradle' documentation under,
https://docs.gradle.org/current/userguide/upgrading_version_6.html#publishing_spring_boot_applications
Just add the following to the build.gradle
file
jar {
enabled = true
}
bootJar {
classifier = 'application'
}
来源:https://stackoverflow.com/questions/61197984/bootjar-mavenjar-artifact-wasnt-produced-by-this-build