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

Posted

技术标签:

【中文标题】BootJar + MavenJar。工件不是由这个构建产生的【英文标题】:BootJar + MavenJar. Artifact wasn't produced by this build 【发布时间】:2020-07-26 14:35:26 【问题描述】:

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

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

我想将两个生成的 jar:plain 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
        
    

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

Gradle 版本:6.3

【问题讨论】:

适用于 Gradle 5.3。 :-( 【参考方案1】:

正如 gradle 文档 here 所述:

从 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)
       
    

在我的 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
            
        
    

【讨论】:

您能分享更多信息吗?它放在哪里?我收到无法将提供的表示法转换为 ConfigurablePublishArtifact 类型的对象 注意:在多模块项目中的“配置”块应该在带有 bootjar 任务的模块中 没有一种解决方案适用于 bootWar 任务。有什么想法吗? configurations 中的附加行对我有用,在我的情况下是 Gradle v6.5。【参考方案2】:

摘录from

从 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)
    


注意:如果配置正确,则无需更改 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.0jar 任务会生成一个以-plain.jar 结尾的附加 jar 存档。如果有人使用*.jar 之类的模式来复制构建存档,可能会破坏他们的构建,因此,为了限制额外的 jar 创建,应使用以下jar 任务配置代码 sn-p。

jar 
    enabled = false

【讨论】:

【参考方案3】:

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

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


project.tasks.publish.dependsOn bootJar

【讨论】:

【参考方案4】:

根据下面的“Gradle”文档,

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

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

jar 
   enabled = true


bootJar 
   classifier = 'application'

【讨论】:

【参考方案5】:

如果您使用的是 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())
    

【讨论】:

【参考方案6】:

对于 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
        
    

【讨论】:

以上是关于BootJar + MavenJar。工件不是由这个构建产生的的主要内容,如果未能解决你的问题,请参考以下文章

如何让 Teamcity Artifactory 插件在 Gradle 中调用 bootJar 而不是 Jar?

使用分类器更改工件的 Maven 依赖项

Maven JAR Plugin 3.0.2 错误:您必须使用分类器将补充工件附加到项目而不是替换它们

Firebase 存储工件巨大且不断增加

mavenjar包下载出错解决方法

从 springBoots `bootJar` gradle 任务中排除特定依赖项