使用 `publishToMavenLocal` 构建可以发布到 maven 本地 repo 的可执行 jar - spring boot 项目
Posted
技术标签:
【中文标题】使用 `publishToMavenLocal` 构建可以发布到 maven 本地 repo 的可执行 jar - spring boot 项目【英文标题】:Building an executable jar that can be published to maven local repo with `publishToMavenLocal` - spring boot project 【发布时间】:2020-08-09 10:07:18 【问题描述】:在构建可执行 jar(可以使用 java -jar app.jar
运行)方面需要帮助,该 jar 可以发布到 Spring Boot 项目的 maven 本地存储库(使用 gradle publishToMavenLocal
)。
使用这些 gradle 设置 gradle publishToMavenLocal
有效。
Gradle 版本是 6.3 Spring Boot 版本为 2.2.6 Kotlin 1.3.71
父母build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript
repositories
mavenLocal()
mavenCentral()
dependencies
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.6.RELEASE")
plugins
id("org.springframework.boot") version "2.2.6.RELEASE" apply false
id("io.spring.dependency-management") version "1.0.9.RELEASE" apply false
kotlin("jvm") version "1.3.71" apply false
kotlin("plugin.spring") version "1.3.71" apply false
`maven-publish`
`java-library`
signing
allprojects
group = "com.example.user"
version = "0.0.1-SNAPSHOT"
tasks.withType<JavaCompile>
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
tasks.withType<KotlinCompile>
kotlinOptions
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
incremental = false
subprojects
repositories
mavenLocal()
mavenCentral()
apply
plugin("io.spring.dependency-management")
plugin("maven-publish")
子项目build.gradle.kts
:
plugins
id("org.springframework.boot")
id("io.spring.dependency-management")
kotlin("jvm")
kotlin("plugin.spring")
val developmentOnly by configurations.creating
configurations
runtimeClasspath
extendsFrom(developmentOnly)
dependencies
implementation(project(":common"))
implementation(project(":user-models"))
implementation(project(":user-core"))
implementation("org.springframework.boot:spring-boot-starter-webflux")
exclude(group = "org.springframework.boot", module = "spring-boot-starter-logging")
implementation("org.springframework.boot:spring-boot-maven-plugin:2.2.6.RELEASE")
implementation(group = "org.springframework.boot", name = "spring-boot-autoconfigure", version = "2.2.6.RELEASE")
implementation(group = "org.springframework.boot", name = "spring-boot-starter-parent", version = "2.2.6.RELEASE")
implementation("org.springframework.boot:spring-boot-configuration-processor:2.2.6.RELEASE")
implementation("org.projectreactor:reactor-spring:1.0.1.RELEASE")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation(group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version = "1.3.5")
implementation(group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-reactor", version = "1.3.5")
implementation(group = "org.springframework.boot", name = "spring-boot-starter-log4j2", version = "2.2.6.RELEASE")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
tasks.withType<Test>
useJUnitPlatform()
tasks.jar
enabled = true
manifest
attributes["Main-Class"] = "com.subnub.user.service.ServiceApplicationKt"
attributes["Class-Path"] = configurations.compileClasspath.get().map it.name .joinToString(" ")
from(configurations.compileClasspath.get().map if(it.isDirectory) it else zipTree(it) )
duplicatesStrategy = DuplicatesStrategy.INCLUDE
tasks.bootJar
enabled = false
archiveClassifier.set("application")
mainClassName = "com.example.user.service.ServiceApplicationKt"
publishing
publications
create<MavenPublication>("mavenJava")
from(components["java"])
afterEvaluate
artifactId = tasks.jar.get().archiveBaseName.get()
但是使用这些 gradle 设置构建的 jar 在尝试运行时会中断
标准错误:
➜ example-user git:(master) ✗ java -jar example-service/build/libs/example-service-0.0.1-SNAPSHOT.jar
[INFO ] 2020-04-25 22:18:11.871 [main] ServiceApplicationKt - Starting ServiceApplicationKt on admins-mbp-7 with PID 4663 (/Users/zerocase/personal/startups/example/code/example-user/example-service/build/libs/example-service-0.0.1-SNAPSHOT.jar started by abhishek in /Users/zerocase/personal/startups/example/code/example-user)
[INFO ] 2020-04-25 22:18:11.874 [main] ServiceApplicationKt - No active profile set, falling back to default profiles: default
[ERROR] 2020-04-25 22:18:12.055 [main] SpringApplication - Application run failed
java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
at org.springframework.util.Assert.notEmpty(Assert.java:464) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:173) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:116) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:396) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:878) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:808) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:779) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:192) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:319) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:236) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:66) ~[example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [example-service-0.0.1-SNAPSHOT.jar:?]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [example-service-0.0.1-SNAPSHOT.jar:?]
at com.example.user.service.ServiceApplicationKt.main(ServiceApplication.kt:19) [example-service-0.0.1-SNAPSHOT.jar:?]
我已经尝试了此处建议的解决方法 (https://docs.gradle.org/current/userguide/upgrading_version_6.html#publishing_spring_boot_applications) 来发布 bootJar
工件。在这种情况下,jar 可以正常工作,但是,
configurations
listOf(apiElements, runtimeElements).forEach
it.get().outgoing.artifacts.removeIf it.buildDependencies.getDependencies(null).contains(tasks.jar)
it.get().outgoing.artifact(tasks.bootJar)
但是 gradle 不允许我这样做 gradle pTML
➜ example-user git:(master) ✗ gradle pTML
> Task :user-service:publishMavenJavaPublicationToMavenLocal FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':user-service:publishMavenJavaPublicationToMavenLocal'.
> Failed to publish publication 'mavenJava' to repository 'mavenLocal'
> Artifact example-service-0.0.1-SNAPSHOT.jar wasn't produced by this build.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
16 actionable tasks: 3 executed, 13 up-to-date
【问题讨论】:
【参考方案1】:解决了问题,artifact
需要在发布范围内定义。
publishing
publications
create<MavenPublication>("mavenJava")
//from(components["java"]) // <-- this is not required
artifact(tasks.bootJar.get()) // <-- this is required
并对configurations
范围(ref)稍作修改:
configurations
listOf(apiElements, runtimeElements).forEach
// Method #1
val jar by tasks
it.get().outgoing.artifacts.removeIf it.buildDependencies.getDependencies(null).contains(jar)
// Method #2
it.get().outgoing.artifact(tasks.bootJar)
这里是一些发布出版物的示例implementations。
【讨论】:
【参考方案2】:我修复了错误Artifact ....jar wasn't produced by this build
添加参数enabled = true
到jar
任务
jar
enabled = true
【讨论】:
以上是关于使用 `publishToMavenLocal` 构建可以发布到 maven 本地 repo 的可执行 jar - spring boot 项目的主要内容,如果未能解决你的问题,请参考以下文章
在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?