This is a pretty common gotcha when rebuilding/publishing Spring Framework modules with Gradle. Let’s break down what’s happening and why you’re seeing the warning about missing version for micrometer-observation
.
mavenJava
fails but mavenKotlin
"works"mavenJava
is the default publication name Gradle wires up when you use the java
plugin with maven-publish
.
But Spring’s build adds additional plugins/components (Java + Kotlin + test fixtures, etc.).
That’s why you got the error:
Maven publication 'mavenJava' cannot include multiple components
→ It was trying to mix in multiple components (java, kotlin, test fixtures).
By renaming it to mavenKotlin
, you avoided the collision, but you also ended up with a stripped-down POM where dependency management didn’t carry over correctly (that’s why micrometer-observation
lost its version).
Spring Framework doesn’t put versions directly in each module’s build.gradle
.
Instead, it relies on dependency management (via the Spring Dependency Management Plugin or BOMs like spring-framework-bom
).
When Gradle generates the POM without that plugin hooked into publishing, you get dependencies like:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation</artifactId>
<!-- version missing -->
</dependency>
This leads to the warnings you saw.
✅ Option A: Keep mavenJava
but fix the multi-component issue
Instead of renaming to mavenKotlin
, explicitly pick which component to publish:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
Make sure only components.java
is used (not components.kotlin
or test fixtures).
That way Gradle generates the POM with proper dependency management.
✅ Option B: Use the java
plugin correctly (don’t apply kotlin
unless you need it)
Right now you have:
apply plugin: "kotlin"
But spring-context
itself is not a Kotlin module in the official repo. Adding the Kotlin plugin pulls in components.kotlin
→ which confuses publishing.
If you don’t actually need Kotlin compilation in spring-context
, just remove that line and stick with java
.
✅ Option C: Force versions into the POM
If for some reason you want to keep your mavenKotlin
publication, you can still inject dependency management into the generated POM:
publishing {
publications {
mavenKotlin(MavenPublication) {
from components.java
pom {
withXml {
asNode().dependencies.'dependency'.findAll {
it.artifactId.text() == 'micrometer-observation' && !it.version
}.each {
it.appendNode('version', '1.13.5') // or whatever version Spring’s BOM manages
}
}
}
}
}
}
But this is brittle (you’d have to maintain versions manually).
If you look at Spring’s official build, they:
Use java
+ maven-publish
.
Apply the Spring dependency management plugin so that BOM-managed versions are written into the generated POM correctly.
Publish with mavenJava
(not a renamed publication).
Remove apply plugin: "kotlin"
from spring-context/build.gradle
(unless you’re actually modifying the module to contain Kotlin sources).
Go back to:
publications {
mavenJava(MavenPublication) {
from components.java
}
}
Make sure the Spring dependency management plugin is applied at the root project (so the POM has versions resolved).
👉 Do you want me to show you exactly how Spring wires dependency-management-plugin
into its Gradle build, so you can replicate the same setup and get clean POMs without missing versions?