BootJar + MavenJar。工件不是由这个构建产生的

Erm*_*tar 13 gradle maven-publish spring-boot-gradle-plugin

我有一个具有以下层次结构的示例项目:

Sample (root)
   -- model (simple jar)
   -- api   (springboot jar)
Run Code Online (Sandbox Code Playgroud)

我想将两个生成的 jars:plain jar 和 bootJar 发布到我的 localRepository。

gradlew clean build -xTest publishToMavenLocal    
Run Code Online (Sandbox Code Playgroud)

但是,出现以下错误:

* 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.
Run Code Online (Sandbox Code Playgroud)

根 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

api build.gradle

apply plugin: 'org.springframework.boot'

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

bootJar {
}
Run Code Online (Sandbox Code Playgroud)

将 bootJava 任务添加到 api build.gradle 允许直接从 api 模块发布 bootJar,但根发布任务仍然中断。

publishing {
    publications {
        bootJava(MavenPublication) {
            artifact bootJar
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几乎所有来自 docs 和 google 的解决方案,但似乎都没有奏效。谁能解释一下,什么配置错误?

摇篮版本:6.3

has*_*nae 14

正如此处的 gradle 文档所述:

从 Gradle 6.2 开始,Gradle 在上传之前执行健全性检查,以确保您不会上传陈旧文件(由另一个构建生成的文件)。这引入了使用 components.java 组件上传的 Spring Boot 应用程序的问题

上面的链接中提供了更多解释。他们提出了以下我亲自尝试并为我工作的解决方法:

配置传出配置

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

在我的 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Pra*_*ran 9

节选

从 Gradle 6.2开始,主要jar任务被 Spring Boot 应用程序禁用,并且component期望它存在。由于默认情况下bootJar任务使用与主jar任务相同的文件,因此以前的 Gradle 版本将:

  • 发布一个陈旧的bootJar工件
  • 如果之前没有调用过 bootJar 任务,则失败

简单的解决方法是配置传出配置。对于多模块 Gradle 项目,将以下配置放在服务模块(spring boot 模块)中。


dependencies {
          .....
}

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

Run Code Online (Sandbox Code Playgroud)

注意:artifactory如果任务配置正确,则无需更改任何内容。该工作解决方案已经过测试Gradle 6.4.1

不要尝试他们提供的替代建议,因为classifier属性在最近的版本中已弃用,bootJar使用自定义配置更改任务也会导致uber jar 构造不当,如果您提取生成的 jar 分发文件,您可以找到丢失的BOOT-INF目录和必要的 META-INF/MANIFEST.MF值。

jar {
   enabled = true
}

bootJar {
   classifier = 'application'
}

Run Code Online (Sandbox Code Playgroud)

更新:

Spring Boot 2.5.0jar任务生成一个附加的 jar 档案,以-plain.jar. 如果他们使用了一些模式,比如*.jar复制构建存档,它可能会破坏某人的构建,因此,为了限制额外的 jar 创建,jar应该使用以下任务配置代码片段。

jar {
    enabled = false
}
Run Code Online (Sandbox Code Playgroud)


Jar*_*vis 7

我可以通过添加artifact bootJar如下所示的发布任务来完成这项工作,而无需添加 gradle 文档中建议的任何配置。我相信这可能与他们在文档中的第一个解决方法相同。用gradle测试6.5.1

publishing {
    publications {
        mavenJava(MavenPublication) {
            artifact bootJar
            artifact sourceJar {
                classifier "sources"
            }
        }
    }
}

project.tasks.publish.dependsOn bootJar
Run Code Online (Sandbox Code Playgroud)


Jan*_*han 5

根据下面的“Gradle”文档,

https://docs.gradle.org/current/userguide/upgrading_version_6.html#publishing_spring_boot_applications

只需将以下内容添加到build.gradle文件中

jar {
   enabled = true
}

bootJar {
   classifier = 'application'
}
Run Code Online (Sandbox Code Playgroud)