如何修正Java Gradle插件使其实现原Kotlin Maven发布逻辑?
问题:Java Gradle插件无法推送源码Jar和二进制Jar至S3 Maven仓库,如何修正?
我之前在每个build.gradle.kts中复制粘贴一段Kotlin代码,用于将Java构件发布到指定S3 Maven仓库,该代码会生成sources Jar并配置相关凭证。目前我已编写对应的Java Gradle插件,插件可正常编译,但运行时无法推送源码Jar和二进制Jar至仓库,请问如何修正该插件使其与原Kotlin代码功能一致?
原Kotlin代码
System.getenv("JRS_S3_URI")?.let { val sourcesJar by tasks.creating(Jar::class) { classifier = "sources" from(java.sourceSets["main"].allSource) } publishing { repositories { maven { url = uri(it) credentials(AwsCredentials::class.java) { accessKey = System.getenv("JRS_ACCESSKEYID") secretKey = System.getenv("JRS_SECRETACCESSKEY") } } } publications { "mavenJava"(MavenPublication::class) { from(components["java"]) artifact(sourcesJar) } } } }
当前Java Gradle插件代码
public class Maven extends SourceSetConfiguredPlugin { public Maven( XenoExtension extension ) { super( extension ); } @Override public void apply( Project project ) { if ( System.getenv( "JRS_S3_URI" ) != null ) { project.getPluginManager().apply( MavenPublishPlugin.class ); TaskContainer tasks = project.getTasks(); Jar sourceSet = tasks.create( "sources", Jar.class, task -> { getSourceSets().stream() .map( SourceSet::getAllSource ) .map( sds -> project.copySpec().from( sds ) ) .forEach( copySpec -> task.include( copySpec.getIncludes() ) ); } ); tasks.withType( PublishToMavenRepository.class, task -> { task.getRepository().setUrl( URI.create( System.getenv( "JRS_S3_URI" ) ) ); task.getRepository().credentials( AwsCredentials.class, creds -> { creds.setAccessKey( System.getenv( "JRS_ACCESSKEYID" ) ); creds.setSecretKey( System.getenv( "JRS_SECRETACCESSKEY" ) ); } ); MavenPublication publication = task.getPublication(); publication.artifact( project.getComponents() ); publication.artifact( sourceSet ); } ); } } }
问题分析与修正方案
你的Java插件和原Kotlin代码的核心差异在于配置时机、源码Jar构建逻辑、Publication与仓库的配置方式,下面是具体的修正点和完整的修复代码:
1. 核心问题点
- 源码Jar构建错误:原Kotlin代码明确指定了
classifier = "sources"并直接关联main源码集的所有源码,而你的Java代码没有设置classifier,且错误地用include代替from来关联源码。 - Publishing扩展配置时机错误:原Kotlin代码直接配置
publishing扩展(仓库和Publication),而你是在PublishToMavenRepository任务层面修改,这会导致配置不生效或重复覆盖。 - Publication配置错误:你调用
publication.artifact(project.getComponents())是错误的,project.getComponents()返回的是组件容器,应该关联java组件来自动包含二进制Jar。
2. 修正后的Java插件代码
import org.gradle.api.Project; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.MavenPublishPlugin; import org.gradle.api.publish.PublishingExtension; import org.gradle.api.publish.maven.MavenPublication; import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.TaskContainer; import org.gradle.api.provider.Provider; import software.amazon.awssdk.auth.credentials.AwsCredentials; public class Maven extends SourceSetConfiguredPlugin { public Maven(XenoExtension extension) { super(extension); } @Override public void apply(Project project) { String s3Uri = System.getenv("JRS_S3_URI"); if (s3Uri != null) { // 应用必要的插件 project.getPluginManager().apply(MavenPublishPlugin.class); project.getPluginManager().apply(JavaPlugin.class); TaskContainer tasks = project.getTasks(); // 1. 正确创建sources Jar任务,和原Kotlin逻辑对齐 Provider<Jar> sourcesJarProvider = tasks.register("sourcesJar", Jar.class, task -> { task.setClassifier("sources"); // 设置源码Jar的classifier标识 // 关联main源码集的所有源码文件 task.from(project.getExtensions().getByType(org.gradle.api.plugins.JavaPluginExtension.class) .getSourceSets().getByName("main").getAllSource()); }); // 2. 获取Publishing扩展,全局配置仓库和Publication PublishingExtension publishing = project.getExtensions().getByType(PublishingExtension.class); // 配置S3 Maven仓库 publishing.getRepositories().maven(repo -> { repo.setUrl(project.getUri(s3Uri)); // 配置AWS凭证信息 repo.getCredentials(AwsCredentials.class, creds -> { creds.setAccessKey(System.getenv("JRS_ACCESSKEYID")); creds.setSecretKey(System.getenv("JRS_SECRETACCESSKEY")); }); }); // 配置Maven Publication,关联Java组件和sources Jar publishing.getPublications().create("mavenJava", MavenPublication.class, publication -> { // 关联Java组件,自动包含编译后的二进制Jar publication.from(project.getComponents().getByName("java")); // 添加sources Jar作为额外构件 publication.artifact(sourcesJarProvider); }); } } }
3. 关键修正说明
- 源码Jar任务:使用
tasks.register(Gradle推荐的懒加载任务创建方式)创建sourcesJar,明确设置classifier = "sources",并正确关联main源码集的allSource,和原Kotlin逻辑完全一致。 - Publishing扩展配置:直接操作
PublishingExtension来配置仓库和Publication,确保配置在Gradle生命周期的正确时机生效,避免任务层面配置的不确定性。 - Publication关联:通过
publication.from(project.getComponents().getByName("java"))关联Java组件,自动包含编译后的二进制Jar,再添加sourcesJar作为额外构件,保证发布内容完整。 - 凭证配置:在仓库层面统一配置AWS凭证,确保所有发布任务都使用相同的凭证信息,避免重复配置。
这样修改后,你的Java插件就会和原Kotlin代码实现完全一致的功能,能够正确生成并推送源码Jar和二进制Jar到指定的S3 Maven仓库。
内容的提问来源于stack exchange,提问作者xenoterracide
相关产品推荐
相关产品推荐

