Skip to content

Commit

Permalink
KAFKA-16359: Corrected manifest file for kafka-clients (apache#15532)
Browse files Browse the repository at this point in the history
The issue KAFKA-16359 reported inclusion of kafka-clients runtime dependencies in MANIFEST.MF Class-Path.

The root cause is the issue defined here with the usage of shadow plugin.

Looking into the specifics of plugin and documentation, specifies that any dependency marked as shadow will be treated as following by the shadow plugin:

    1. Adds the dependency as runtime dependency in resultant pom.xml - code here
    2. Adds the dependency as Class-Path in MANIFEST.MF as well - code here

Resolution

We do need the runtime dependencies available in the pom (1 above) but not on manifest (2 above). Also there is no clear way to separate the behaviour as both above tasks relies on shadow configuration.

To fix, I have defined another custom configuration named shadowed which is later used to populate the correct pom (the code is similar to what shadow plugin does to populate pom for runtime dependencies).

Though this might seem like a workaround, but I think that's the only way to fix the issue. I have checked other SDKs which suffered with same issue and went with similar route to populate pom.

Reviewers: Luke Chen <showuon@gmail.com>, Reviewers: Mickael Maison <mickael.maison@gmail.com>, Gaurav Narula <gaurav_narula2@apple.com>
  • Loading branch information
apoorvmittal10 authored and clolov committed Apr 5, 2024
1 parent b349ad7 commit a9ea274
Showing 1 changed file with 26 additions and 8 deletions.
34 changes: 26 additions & 8 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,24 @@ subprojects {
} else {
apply plugin: 'com.github.johnrengelman.shadow'
project.shadow.component(mavenJava)

// Fix for avoiding inclusion of runtime dependencies marked as 'shadow' in MANIFEST Class-Path.
// https://github.com/johnrengelman/shadow/issues/324
afterEvaluate {
pom.withXml { xml ->
if (xml.asNode().get('dependencies') == null) {
xml.asNode().appendNode('dependencies')
}
def dependenciesNode = xml.asNode().get('dependencies').get(0)
project.configurations.shadowed.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', 'runtime')
}
}
}
}

afterEvaluate {
Expand Down Expand Up @@ -1403,6 +1421,7 @@ project(':clients') {

configurations {
generator
shadowed
}

dependencies {
Expand All @@ -1413,10 +1432,10 @@ project(':clients') {
implementation libs.opentelemetryProto

// libraries which should be added as runtime dependencies in generated pom.xml should be defined here:
shadow libs.zstd
shadow libs.lz4
shadow libs.snappy
shadow libs.slf4jApi
shadowed libs.zstd
shadowed libs.lz4
shadowed libs.snappy
shadowed libs.slf4jApi

compileOnly libs.jacksonDatabind // for SASL/OAUTHBEARER bearer token parsing
compileOnly libs.jacksonJDK8Datatypes
Expand Down Expand Up @@ -1469,10 +1488,9 @@ project(':clients') {

// dependencies excluded from the final jar, since they are declared as runtime dependencies
dependencies {
exclude(dependency(libs.snappy))
exclude(dependency(libs.zstd))
exclude(dependency(libs.lz4))
exclude(dependency(libs.slf4jApi))
project.configurations.shadowed.allDependencies.each {
exclude(dependency(it.group + ':' + it.name + ':' + it.version))
}
// exclude proto files from the jar
exclude "**/opentelemetry/proto/**/*.proto"
exclude "**/google/protobuf/*.proto"
Expand Down

0 comments on commit a9ea274

Please sign in to comment.