Gradle未生成在META-INF中嵌入pom.xml的Springboot Library Jar

mcdcgff0  于 5个月前  发布在  Spring
关注(0)|答案(2)|浏览(93)

我有Springboot多模块库项目,Gradle 7.4和Springboot 3.2如下所示

buildscript {

    dependencies {
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.21.0"
    }
}
plugins {
    id "com.diffplug.spotless" version "6.8.0"
    id 'io.spring.dependency-management' version '1.1.4'
    id 'org.springframework.boot' version '3.2.0' apply false
    id "org.openapi.generator" version "6.0.0"
    id "org.hidetake.swagger.generator" version "2.19.2"
}

ext.versions = [
        springBoot        : '3.2.0',
        springCloud       : '2022.0.4',
        micrometer        : '1.10.3',
        commonLogging     : '1.2',
]

allprojects {
    apply plugin: 'io.spring.dependency-management'
    group 'com.springboot.web.library'
    version = '0.0.3-SNAPSHOT'

    dependencyManagement {
        imports {
            mavenBom("org.springframework.boot:spring-boot-dependencies:${versions.springBoot}")
            mavenBom("org.springframework.cloud:spring-cloud-dependencies:${versions.springCloud}")
        }
        dependencies {
            //dependency group: 'io.micrometer', name: 'micrometer-registry-prometheus', version: versions.micrometer
            dependency group: 'commons-logging', name: 'commons-logging', version: versions.commonLogging
        }
    }
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'maven-publish'
    apply plugin: "com.diffplug.spotless"

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(17)
        }
        withSourcesJar()
    }

    //https://dev.to/ankityadav33/standardize-code-formatting-with-spotless-2bdh
    spotless {
        java {
            //googleJavaFormat("1.15.0")
            target fileTree('.') {
                include '**/*.java'
                exclude '**/build/**', '**/build-*/**'
            }
            importOrder()
            toggleOffOn()
            palantirJavaFormat()
            removeUnusedImports()
            trimTrailingWhitespace()
            endWithNewline()
        }
    }

    afterEvaluate {
        def spotless = tasks.findByName('spotlessApply')
        if (spotless) {
            tasks.withType(JavaCompile) {
                finalizedBy(spotless)
            }

        }
    }

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter'
        compileOnly 'org.projectlombok:lombok:1.18.22'
        annotationProcessor 'org.projectlombok:lombok:1.18.22'
        testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
    }

    repositories {
        mavenLocal()
        mavenCentral()
    }

    test {
        useJUnitPlatform()
    }
    jar {
        enabled = true
        archiveClassifier=''
    }
}

字符串
下面是我的module-commons build.gradle文件

plugins {
    id 'java-library'
}

dependencies {
    compileOnly 'com.fasterxml.jackson.core:jackson-databind:2.16.0'
    compileOnly 'com.fasterxml.jackson.core:jackson-core:2.16.0'
    compileOnly 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.16.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testImplementation 'org.mockito:mockito-core:5.8.0'
    testImplementation 'org.projectlombok:lombok:1.18.30'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
    compileOnly 'org.projectlombok:lombok:1.18.30'
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            artifact jar
        }
    }
    repositories {
        mavenLocal()
    }
}


我在module-commons中有下面的类

package com.springboot.web.library.commons.utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonUtils {
    public String serialize(Object object) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.writeValueAsString(object);
    }
}


我正在运行gradle build jar module-commons:publishToMavenLocal命令,以将该命令发布到本地maven repo。
我将在springboot-demo项目中导入module-commons库作为implementation 'com.springboot.web.library:module-commons:0.0.3-SNAPSHOT',下面是springboot-demo项目build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.springboot.web'
version = '1.0-SNAPSHOT'

repositories {
    mavenLocal()
    mavenCentral()
}

dependencies {
    implementation 'org.projectlombok:lombok:1.18.28'
    testImplementation platform('org.junit:junit-bom:5.9.1')
    testImplementation 'org.junit.jupiter:junit-jupiter'
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation 'com.springboot.web.library:module-commons:0.0.3-SNAPSHOT'

}

test {
    useJUnitPlatform()
}


我在springboot-demo项目中导入JsonUtils Main类如下

package com.springboot.web.library.commons;

import com.springboot.web.library.commons.utils.JsonUtils;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {

    @lombok.SneakyThrows
    public static void main(String[] args) {
        JsonUtils jsonUtils = new JsonUtils();
        jsonUtils.serialize("test");
        System.out.println("Hello world!");
    }
}


在运行Main类时,由于module-commons jar在META-INF目录中没有包含pom.xml的maven.com.springboot.web.library.module-commons目录,因此Gradle无法解析module-commons中引用的Jackson库,因此出现了编译器错误。我已经尝试了Github和Stackoverflow中提供的许多解决方案,但到目前为止都没有运气。我感谢任何人可以帮助解决这个问题。完整的项目可以在这里找到https://github.com/JavaSpringBooteer/springboot-gradle-library

D:\Git\springboot-gradle-library\springboot-demo\src\main\java\com\springboot\web\library\commons\Main.java:12: error: cannot access JsonProcessingException
        jsonUtils.serialize("test");
                           ^
  class file for com.fasterxml.jackson.core.JsonProcessingException not found


尝试Github和Stackoverflow的解决方案来调整build.gradle

carvr3hs

carvr3hs1#

你的项目应该是:

[ Gradle Build System ]
        |
        |---[ module-commons Library ]
        |        |---[ build.gradle ]
        |        |---[ src ]
        |        |---[ dependencies (Jackson, Lombok, etc.) ]
        |
        |---[ springboot-demo Project ]
                 |---[ build.gradle ]
                 |---[ src ]
                 |---[ dependencies (including module-commons) ]

字符串
您需要修改您的module-commons构建脚本,以在发布的工件中包含依赖关系信息,这可以通过正确配置maven-publish plugin来实现。
你的module-commons/build.gradle是:

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact sourcesJar

            pom.withXml {
                def dependenciesNode = asNode().appendNode('dependencies')
                configurations.compileClasspath.allDependencies.each { dep ->
                    def dependencyNode = dependenciesNode.appendNode('dependency')
                    dependencyNode.appendNode('groupId', dep.group)
                    dependencyNode.appendNode('artifactId', dep.name)
                    dependencyNode.appendNode('version', dep.version)
                }
            }
        }
    }
    repositories {
        mavenLocal()
    }
}


这将包括主Java组件(from components.java),它确保编译的类和资源是发布的一部分。
它还向生成的POM文件中添加了一个自定义部分,其中列出了所有编译类路径依赖项。
运行./gradlew module-commons:publishToMavenLocal命令。将更新后的module-commons工件发布到本地Maven存储库后,构建并运行springboot-demo项目。它现在应该正确解析依赖项。

Duplicated tag: 'dependencies'


我假设您的build.gradle中的pom.withXml块正在将一个新的<dependencies>节点附加到现有的POM结构中,该结构已经定义了一个<dependencies>标记。
让我们修改module-commons/build.gradle中的pom.withXml块,以正确处理现有的<dependencies>标记。

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact sourcesJar

            pom.withXml {
                def pomNode = asNode()
                // Find or create the 'dependencies' node
                def dependenciesNode = pomNode.children().find { it.name() == 'dependencies' }
                if (dependenciesNode == null) {
                    dependenciesNode = pomNode.appendNode('dependencies')
                }

                configurations.compileClasspath.allDependencies.each { dep ->
                    if (dep.group != null && dep.version != null) {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', dep.group)
                        dependencyNode.appendNode('artifactId', dep.name)
                        dependencyNode.appendNode('version', dep.version)
                    }
                }
            }
        }
    }
    repositories {
        mavenLocal()
    }
}


在追加依赖项之前,检查它们的groupversion是否不为null,以避免包含无效条目,这很重要。
将更新后的脚本应用于module-commons/build.gradle,并运行./gradlew clean build以确保正确应用所有更改并清除旧工件。
执行./gradlew module-commons:publishToMavenLocal。发布后,检查本地Maven仓库中的pom.xml,以确保其格式正确,没有重复的标记。
运行您的springboot-demo项目以检查问题是否已解决。
作为替代方法,您可以考虑清除任何现有的<dependencies>节点并重新创建它,而不是追加新的<dependencies>节点或尝试查找和增强现有节点。这将确保不会发生重复。
你的module-commons/build.gradle是:

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java
            artifact sourcesJar

            pom.withXml {
                def pomNode = asNode()
                // Remove existing 'dependencies' node if present
                def dependenciesNode = pomNode.children().find { it.name() == 'dependencies' }
                if (dependenciesNode != null) {
                    dependenciesNode.replaceNode {}
                }
                // Re-create the 'dependencies' node
                dependenciesNode = pomNode.appendNode('dependencies')
                configurations.compileClasspath.allDependencies.each { dep ->
                    if (dep.group != null && dep.version != null) {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', dep.group)
                        dependencyNode.appendNode('artifactId', dep.name)
                        dependencyNode.appendNode('version', dep.version)
                    }
                }
            }
        }
    }
    repositories {
        mavenLocal()
    }
}

moiiocjp

moiiocjp2#

您的Gradle构建版本没有在您的module-commons项目的META-INF目录中使用嵌入的pom.xml生成Sping Boot 库示例。当您将示例发布到Maven存储库时,需要使用此嵌入的pom.xml来正确解析依赖项。若要生成此pom.xml,您需要为您的module-commons项目配置MavenPublication。
以下是如何修改module-commons build.gradle文件以包含MavenPublication所需的配置:

plugins {
    id 'java-library'
    id 'maven-publish' // Add the Maven Publish plugin
}

dependencies {
    // Your dependencies
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java // This will include the Java component
            pom {
                // Customize the generated POM here if needed
                // For example, you can add dependencies or other metadata
                // Example:
                withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')
                    dependenciesNode.appendNode('dependency')
                            .appendNode('groupId', 'com.fasterxml.jackson.core')
                            .appendNode('artifactId', 'jackson-databind')
                            .appendNode('version', '2.16.0')
                            .appendNode('scope', 'compile')
                }
            }
        }
    }
    repositories {
        mavenLocal()
    }
}

字符串
在发布块中,我们配置一个名为mavenJava的MavenPublication,它包含项目的Java组件。在pom块中,您可以根据需要自定义生成的POM。在上面的示例中,我已经展示了如何为jackson-databind的POM添加依赖项,因为它是项目的编译依赖项。
在对module-commons build.gradle文件进行这些更改后,再次运行gradle build module-commons:jumshToMavenLocal,它应该会在META-INF目录中生成带有嵌入式pom.xml的xml。这应该会解决springboot-demo项目中的依赖问题。

相关问题