BootJar + MavenJar。工件不是由此构建产生的
BootJar + MavenJar. Artifact wasn't produced by this build
我有一个具有以下层次结构的示例项目:
Sample (root)
-- model (simple jar)
-- api (springboot jar)
我想发布两个生成的 jar:普通 jar 和 bootJar 到我的 localRepository。
gradlew clean build -xTest publishToMavenLocal
但是,出现以下错误:
* 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.
根build.gradle如下:
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 {
}
将 bootJava 任务添加到 api build.gradle 允许直接从 api 模块发布 bootJar,但根发布任务仍然损坏。
publishing {
publications {
bootJava(MavenPublication) {
artifact bootJar
}
}
}
我几乎尝试了文档和 google 中的所有解决方案,但 none 似乎有效。
谁能解释一下,什么配置错误?
Gradle版本:6.3
如 gradle 文档所述 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
以上 link 中提供了更多说明。
他们提出了我亲自尝试并为我工作的以下解决方法:
配置传出配置
configurations {
[apiElements, runtimeElements].each {
it.outgoing.artifacts.removeIf { it.buildDependencies.getDependencies(null).contains(jar) }
it.outgoing.artifact(bootJar)
}
}
在我的 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
}
}
}
}
节选from
从 Gradle 6.2 开始,主要的 jar
任务被 Spring 引导应用程序,并且 component
期望它存在。因为 bootJar
任务默认使用与主 jar
任务相同的文件,[=72 的先前版本=] 要么:
- 发布过时的
bootJar
工件
- 如果先前未调用 bootJar 任务,则失败
简单的解决方法是配置传出配置。对于多模块 Gradle 项目,将以下配置放在服务模块(spring 引导模块)中。
dependencies {
.....
}
configurations {
[apiElements, runtimeElements].each {
it.outgoing.artifacts.removeIf {
it.buildDependencies.getDependencies(null).contains(jar)
}
it.outgoing.artifact(bootJar)
}
}
注意:如果 artifactory
任务配置正确,则无需更改任何内容。此工作解决方案已通过 Gradle 6.4.1
.
测试
不要尝试 他们提供的替代建议,因为 classifier
属性在最近的版本中已被弃用,同时也改变了 bootJar
自定义任务配置会导致不正确的 uber jar 构建,如果你提取生成的 jar 分发包,你可以找到丢失的 BOOT-INF
目录和必要的 META-INF/MANIFEST.MF
个值。
jar {
enabled = true
}
bootJar {
classifier = 'application'
}
更新:
从 Spring Boot 2.5.0
,jar
任务生成一个额外的 jar 存档,以 -plain.jar
结尾。如果某人使用 *.jar
等模式来复制构建存档,则可能会破坏某人的构建,因此,要限制额外的 jar 创建,应使用以下 jar
任务配置代码片段。
jar {
enabled = false
}
我可以通过在发布任务中添加 artifact bootJar
来完成这项工作,如下所示,而不添加 gradle 文档中建议的任何配置。我相信这可能与他们在文档中的第一个解决方法一样有效。使用 gradle 6.5.1
测试
publishing {
publications {
mavenJava(MavenPublication) {
artifact bootJar
artifact sourceJar {
classifier "sources"
}
}
}
}
project.tasks.publish.dependsOn bootJar
根据 'Gradle' 下的文档,
只需将以下内容添加到 build.gradle
文件
jar {
enabled = true
}
bootJar {
classifier = 'application'
}
如果您正在使用 gradle kotlin dsl,请在您的 build.gradle 中添加等效项。它对我有用
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())
}
}
对于 Spring Boot 2.5.0+,此配置适用于发布嵌入式 jar、其源代码和 javadoc:
plugins {
id 'maven-publish'
id 'java-library'
}
jar {
enabled = false
}
java {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
publication(MavenPublication) {
artifact bootJar
from components.java
}
}
}
我有一个具有以下层次结构的示例项目:
Sample (root)
-- model (simple jar)
-- api (springboot jar)
我想发布两个生成的 jar:普通 jar 和 bootJar 到我的 localRepository。
gradlew clean build -xTest publishToMavenLocal
但是,出现以下错误:
* 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.
根build.gradle如下:
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 {
}
将 bootJava 任务添加到 api build.gradle 允许直接从 api 模块发布 bootJar,但根发布任务仍然损坏。
publishing {
publications {
bootJava(MavenPublication) {
artifact bootJar
}
}
}
我几乎尝试了文档和 google 中的所有解决方案,但 none 似乎有效。 谁能解释一下,什么配置错误?
Gradle版本:6.3
如 gradle 文档所述 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
以上 link 中提供了更多说明。 他们提出了我亲自尝试并为我工作的以下解决方法:
配置传出配置
configurations {
[apiElements, runtimeElements].each {
it.outgoing.artifacts.removeIf { it.buildDependencies.getDependencies(null).contains(jar) }
it.outgoing.artifact(bootJar)
}
}
在我的 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
}
}
}
}
节选from
从 Gradle 6.2 开始,主要的 jar
任务被 Spring 引导应用程序,并且 component
期望它存在。因为 bootJar
任务默认使用与主 jar
任务相同的文件,[=72 的先前版本=] 要么:
- 发布过时的
bootJar
工件 - 如果先前未调用 bootJar 任务,则失败
简单的解决方法是配置传出配置。对于多模块 Gradle 项目,将以下配置放在服务模块(spring 引导模块)中。
dependencies {
.....
}
configurations {
[apiElements, runtimeElements].each {
it.outgoing.artifacts.removeIf {
it.buildDependencies.getDependencies(null).contains(jar)
}
it.outgoing.artifact(bootJar)
}
}
注意:如果 artifactory
任务配置正确,则无需更改任何内容。此工作解决方案已通过 Gradle 6.4.1
.
不要尝试 他们提供的替代建议,因为 classifier
属性在最近的版本中已被弃用,同时也改变了 bootJar
自定义任务配置会导致不正确的 uber jar 构建,如果你提取生成的 jar 分发包,你可以找到丢失的 BOOT-INF
目录和必要的 META-INF/MANIFEST.MF
个值。
jar {
enabled = true
}
bootJar {
classifier = 'application'
}
更新:
从 Spring Boot 2.5.0
,jar
任务生成一个额外的 jar 存档,以 -plain.jar
结尾。如果某人使用 *.jar
等模式来复制构建存档,则可能会破坏某人的构建,因此,要限制额外的 jar 创建,应使用以下 jar
任务配置代码片段。
jar {
enabled = false
}
我可以通过在发布任务中添加 artifact bootJar
来完成这项工作,如下所示,而不添加 gradle 文档中建议的任何配置。我相信这可能与他们在文档中的第一个解决方法一样有效。使用 gradle 6.5.1
publishing {
publications {
mavenJava(MavenPublication) {
artifact bootJar
artifact sourceJar {
classifier "sources"
}
}
}
}
project.tasks.publish.dependsOn bootJar
根据 'Gradle' 下的文档,
只需将以下内容添加到 build.gradle
文件
jar {
enabled = true
}
bootJar {
classifier = 'application'
}
如果您正在使用 gradle kotlin dsl,请在您的 build.gradle 中添加等效项。它对我有用
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())
}
}
对于 Spring Boot 2.5.0+,此配置适用于发布嵌入式 jar、其源代码和 javadoc:
plugins {
id 'maven-publish'
id 'java-library'
}
jar {
enabled = false
}
java {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
publication(MavenPublication) {
artifact bootJar
from components.java
}
}
}