Files
kafka/build.gradle
Federico Valeri d2e62a6a75 KAFKA-21224: Add mirror-level configs (#23843)
After broker configs, this patch completes the ClusterMirrorConfig
class.

Reviewers: Luke Chen <showuon@gmail.com>, Omnia Ibrahim
 <o.g.h.ibrahim@gmail.com>, Christo Lolov <lolovc@amazon.com>

---------

Signed-off-by: Federico Valeri <fedevaleri@gmail.com>
2026-11-04 11:10:58 +00:00

4509 lines
144 KiB
Groovy
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import org.eclipse.jgit.api.Git
import org.gradle.api.artifacts.FileCollectionDependency
import java.nio.charset.StandardCharsets
buildscript {
repositories {
mavenCentral()
}
apply from: "$rootDir/gradle/dependencies.gradle"
}
plugins {
id 'idea'
id 'jacoco'
id 'java-library'
id 'org.owasp.dependencycheck' version '12.2.2'
id 'org.nosphere.apache.rat' version "0.8.1"
id "io.swagger.core.v3.swagger-gradle-plugin" version "${swaggerVersion}"
id "com.github.spotbugs" version '6.5.12' apply false
id 'org.scoverage' version '9.1' apply false
id 'com.gradleup.shadow' version '9.6.1' apply false
id 'com.diffplug.spotless' version "8.10.3"
// Pre-register the KIP-1265 checker so `apply plugin:` resolves it inside subprojects { }.
// The plugin itself ships from the `:api-checker` included build (see settings.gradle's
// pluginManagement block).
id 'org.apache.kafka.public-api-checker' apply false
}
ext {
minClientJavaVersion = 11
minNonClientJavaVersion = 17
modulesNeedingJava11 = [":clients", ":generator", ":streams", ":streams:test-utils", ":streams:examples", ":streams:streams-scala", ":test-common:test-common-util"]
buildVersionFileName = "kafka-version.properties"
defaultMaxHeapSize = "2g"
defaultJvmArgs = ["-Xss4m", "-XX:+UseParallelGC"]
// "JEP 403: Strongly Encapsulate JDK Internals" causes some tests to fail when they try
// to access internals (often via mocking libraries). We use `--add-opens` as a workaround
// for now and we'll fix it properly (where possible) via KAFKA-13275.
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16))
defaultJvmArgs.addAll(
"--add-opens=java.base/java.io=ALL-UNNAMED",
"--add-opens=java.base/java.lang=ALL-UNNAMED",
"--add-opens=java.base/java.nio=ALL-UNNAMED",
"--add-opens=java.base/java.nio.file=ALL-UNNAMED",
"--add-opens=java.base/java.util=ALL-UNNAMED",
"--add-opens=java.base/java.util.concurrent=ALL-UNNAMED",
"--add-opens=java.base/java.util.regex=ALL-UNNAMED",
"--add-opens=java.base/java.util.stream=ALL-UNNAMED",
"--add-opens=java.base/java.text=ALL-UNNAMED",
"--add-opens=java.base/java.time=ALL-UNNAMED",
"--add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED"
)
maxTestForks = project.hasProperty('maxParallelForks') ? maxParallelForks.toInteger() : Runtime.runtime.availableProcessors()
maxScalacThreads = project.hasProperty('maxScalacThreads') ? maxScalacThreads.toInteger() :
Math.min(Runtime.runtime.availableProcessors(), 8)
userIgnoreFailures = project.hasProperty('ignoreFailures') ? ignoreFailures.toBoolean() : false
userMaxTestRetries = project.hasProperty('maxTestRetries') ? maxTestRetries.toInteger() : 0
userMaxTestRetryFailures = project.hasProperty('maxTestRetryFailures') ? maxTestRetryFailures.toInteger() : 0
skipSigning = project.hasProperty('skipSigning') && skipSigning.toBoolean()
shouldSign = !skipSigning && !version.endsWith("SNAPSHOT")
mavenUrl = project.hasProperty('mavenUrl') ? project.mavenUrl : ''
mavenUsername = project.hasProperty('mavenUsername') ? project.mavenUsername : ''
mavenPassword = project.hasProperty('mavenPassword') ? project.mavenPassword : ''
userShowStandardStreams = project.hasProperty("showStandardStreams") ? showStandardStreams : null
userTestLoggingEvents = project.hasProperty("testLoggingEvents") ? Arrays.asList(testLoggingEvents.split(",")) : null
userEnableTestCoverage = project.hasProperty("enableTestCoverage") ? enableTestCoverage : false
userKeepAliveModeString = project.hasProperty("keepAliveMode") ? keepAliveMode : "daemon"
userKeepAliveMode = KeepAliveMode.values().find(m -> m.name().toLowerCase().equals(userKeepAliveModeString))
if (userKeepAliveMode == null) {
def keepAliveValues = KeepAliveMode.values().collect(m -> m.name().toLowerCase())
throw new GradleException("Unexpected value for keepAliveMode property. Expected one of $keepAliveValues, but received: $userKeepAliveModeString")
}
// Used by :test task
isGithubActions = System.getenv('GITHUB_ACTIONS') != null
// See README.md for details on this option and the reasoning for the default
userScalaOptimizerMode = project.hasProperty("scalaOptimizerMode") ? scalaOptimizerMode : "inline-kafka"
def scalaOptimizerValues = ["none", "method", "inline-kafka", "inline-scala"]
if (!scalaOptimizerValues.contains(userScalaOptimizerMode))
throw new GradleException("Unexpected value for scalaOptimizerMode property. Expected one of $scalaOptimizerValues, but received: $userScalaOptimizerMode")
generatedDocsDir = new File("${project.rootDir}/docs/generated")
repo = file("$rootDir/.git").isDirectory() ? Git.open(project.getRootDir()) : null
commitId = determineCommitId()
configureJavaCompiler = { name, options, projectPath ->
// -parameters generates arguments with parameter names in TestInfo#getDisplayName.
// ref: https://github.com/junit-team/junit5/blob/4c0dddad1b96d4a20e92a2cd583954643ac56ac0/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTest.java#L161-L164
def releaseVersion = modulesNeedingJava11.any { projectPath == it } ? minClientJavaVersion : minNonClientJavaVersion
options.compilerArgs << "-encoding" << "UTF-8"
options.release = releaseVersion
if (name in ["compileTestJava", "compileTestScala"]) {
options.compilerArgs << "-parameters"
} else if (name in ["compileJava", "compileScala"]) {
options.compilerArgs << "-Xlint:all"
options.compilerArgs << "-Xlint:-serial"
options.compilerArgs << "-Xlint:-try"
options.compilerArgs << "-Werror"
if (userKeepAliveMode == KeepAliveMode.SESSION){
// Suppress warning triggered under keepAliveMode=SESSION during joint compilation
// Unexpected javac output: warning: [path] bad path element ".../core/build/classes/java/main": no such file or directory
options.compilerArgs << "-Xlint:-path"
}
}
}
runtimeTestLibs = [
libs.slf4jLog4j2,
libs.junitPlatformLauncher,
libs.jacksonDataformatYaml,
project(":test-common:test-common-util")
]
log4jReleaseLibs = [
libs.slf4jLog4j2,
libs.log4j1Bridge2Api,
libs.jacksonDataformatYaml
]
log4j2Libs = [
libs.log4j2Api,
libs.log4j2Core
]
testLog4j2Libs = [
libs.slf4jApi,
libs.slf4jLog4j2,
libs.log4j2Api,
libs.log4j2Core
]
}
allprojects {
repositories {
mavenCentral()
}
dependencyUpdates {
revision="release"
resolutionStrategy {
componentSelection { rules ->
rules.all { ComponentSelection selection ->
boolean rejected = ['snap', 'alpha', 'beta', 'rc', 'cr', 'm'].any { qualifier ->
selection.candidate.version ==~ /(?i).*[.-]${qualifier}[.\d-]*/
}
if (rejected) {
selection.reject('Release candidate')
}
}
}
}
}
configurations.all {
// zinc is the Scala incremental compiler, it has a configuration for its own dependencies
// that are unrelated to the project dependencies, we should not change them
if (name != "zinc") {
resolutionStrategy {
force(
// be explicit about the javassist dependency version instead of relying on the transitive version
libs.javassist,
// ensure we have a single version in the classpath despite transitive dependencies
libs.scalaLibrary,
libs.scalaReflect,
libs.jacksonAnnotations
)
}
}
}
tasks.register('printAllDependencies', DependencyReportTask) {}
tasks.withType(Javadoc) {
options.charSet = 'UTF-8'
options.docEncoding = 'UTF-8'
options.encoding = 'UTF-8'
options.locale = 'en'
options.memberLevel = JavadocMemberLevel.PUBLIC // Document only public members/API
// Turn off doclint for now, see https://blog.joda.org/2014/02/turning-off-doclint-in-jdk-8-javadoc.html for rationale
options.addStringOption('Xdoclint:none', '-quiet')
// Javadoc warnings should fail the build in JDK 15+ https://bugs.openjdk.org/browse/JDK-8200363
options.addBooleanOption('Werror', JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_15))
options.links "https://docs.oracle.com/en/java/javase/${JavaVersion.current().majorVersion}/docs/api/"
}
tasks.withType(Checkstyle) {
minHeapSize = "200m"
maxHeapSize = "1g"
}
clean {
delete "${projectDir}/src/generated"
delete "${projectDir}/src/generated-test"
}
}
def determineCommitId() {
def takeFromHash = 16
if (project.hasProperty('commitId')) {
commitId.take(takeFromHash)
} else if (repo != null) {
repo.repository.resolve("HEAD").abbreviate(takeFromHash).name()
} else {
"unknown"
}
}
/**
* For a given Project, compute a nice dash separated directory name
* to store the JUnit XML files in. E.g., Project ":connect:api" -> "connect-api"
*/
static def projectToJUnitXmlPath(project) {
var p = project
var projectNames = []
while (p != null) {
projectNames.push(p.name)
p = p.parent
if (p.name == "kafka") {
break
}
}
return projectNames.join("/")
}
apply from: file('wrapper.gradle')
if (repo != null) {
rat {
dependsOn subprojects.collect {
it.tasks.matching {
it.name == "processMessages" || it.name == "processTestMessages"
}
}
verbose.set(true)
reportDir.set(project.file('build/rat'))
stylesheet.set(file('gradle/resources/rat-output-to-html.xsl'))
// Exclude everything under the directory that git should be ignoring via .gitignore or that isn't checked in. These
// restrict us only to files that are checked in or are staged.
excludes = new ArrayList<String>(repo.clean().setIgnore(false).setCleanDirectories(true).setDryRun(true).call())
// And some of the files that we have checked in should also be excluded from this check
excludes.addAll([
'**/.git/**',
'**/build/**',
'.github/pull_request_template.md',
'CONTRIBUTING.md',
'gradlew',
'gradlew.bat',
'gradle/wrapper/gradle-wrapper.properties',
'trogdor/README.md',
'**/README.md',
'**/AGENTS.md',
'**/id_rsa',
'**/id_rsa.pub',
'checkstyle/suppressions.xml',
'streams/quickstart/java/src/test/resources/projects/basic/goal.txt',
'streams/streams-scala/logs/*',
'licenses/*',
'**/generated/**',
'clients/src/test/resources/serializedData/*',
'docker/test/fixtures/secrets/*',
'docker/examples/fixtures/secrets/*',
'docker/docker_official_images/.gitkeep'
])
}
} else {
rat.enabled = false
}
println("Starting build with version $version (commit id ${commitId == null ? "null" : commitId.take(8)}) using Gradle $versions.gradle, Java ${JavaVersion.current()} and Scala ${versions.scala}")
println("Build properties: ignoreFailures=$userIgnoreFailures, maxParallelForks=$maxTestForks, maxScalacThreads=$maxScalacThreads, maxTestRetries=$userMaxTestRetries")
subprojects {
// enable running :dependencies task recursively on all subprojects
// eg: ./gradlew allDeps
tasks.register('allDeps', DependencyReportTask) {}
// enable running :dependencyInsight task recursively on all subprojects
// eg: ./gradlew allDepInsight --configuration runtime --dependency com.fasterxml.jackson.core:jackson-databind
tasks.register('allDepInsight', DependencyInsightReportTask) {showingAllVariants = false}
apply plugin: 'java-library'
// Resolve conflict between testFixtures and shadow in clients:
// testFixtures(project(':clients)) depends on the raw main classpath for clients (apiElements) - see "Rewire
// test fixtures dependencies to avoid depending on the shadow JAR" in the clients project - and this creates
// a conflicting variant with the shadow jar. e.g. main classpath for streams depends the clients shadow jar,
// and the test classpath for streams depends on the client test fixtures, which transitively depends on
// clients raw main classpath (apiElements) conflicting with the shadow jar. To resolve this, we configure
// a resolution strategy for every other module that prefers the shadow jar. As an alternative to this general
// rule, each module that includes the test fixtures dependency could exclude the conflicting variant:
// testImplementation(testFixtures(project(':clients'))) { exclude group: 'org.apache.kafka', module: 'clients' }
if (project.name != 'clients') {
configurations.configureEach {
resolutionStrategy.capabilitiesResolution.withCapability('org.apache.kafka:clients') {
select(candidates.find { it.variantName.toLowerCase().contains('shadow') })
}
}
}
apply plugin: 'checkstyle'
apply plugin: "com.github.spotbugs"
apply plugin: 'org.apache.kafka.public-api-checker'
// We use the shadow plugin for the jmh-benchmarks module and the `-all` jar can get pretty large, so
// don't publish it
def shouldPublish = !project.name.equals('jmh-benchmarks')
def shouldPublishWithShadow = (['clients'].contains(project.name))
if (shouldPublish) {
apply plugin: 'maven-publish'
apply plugin: 'signing'
// Add aliases for the task names used by the maven plugin for backwards compatibility
// The maven plugin was replaced by the maven-publish plugin in Gradle 7.0
tasks.register('install').configure { dependsOn(publishToMavenLocal) }
tasks.register('uploadArchives').configure { dependsOn(publish) }
}
tasks.withType(AbstractArchiveTask).configureEach {
reproducibleFileOrder = false
preserveFileTimestamps = true
useFileSystemPermissions()
}
tasks.withType(AbstractTestTask).configureEach {
failOnNoDiscoveredTests = false
}
// apply the eclipse plugin only to subprojects that hold code. 'connect' is just a folder.
if (!project.name.equals('connect')) {
apply plugin: 'eclipse'
fineTuneEclipseClasspathFile(eclipse, project)
}
java {
consistentResolution {
// resolve the compileClasspath and then "inject" the result of resolution as strict constraints into the runtimeClasspath
useCompileClasspathVersions()
}
}
tasks.withType(JavaCompile) {
configureJavaCompiler(name, options, project.path)
}
if (shouldPublish) {
publishing {
repositories {
// To test locally, invoke gradlew with `-PmavenUrl=file:///some/local/path`
maven {
url = mavenUrl
credentials {
username = mavenUsername
password = mavenPassword
}
}
}
publications {
mavenJava(MavenPublication) {
if (!shouldPublishWithShadow) {
from components.java
} else {
apply plugin: 'com.gradleup.shadow'
from components.shadow
// Fix for avoiding inclusion of runtime dependencies marked as 'shadow' in MANIFEST Class-Path.
// https://github.com/GradleUp/shadow/issues/324
pom.withXml { xml ->
def dependenciesNode = xml.asNode().get('dependencies') ?: xml.asNode().appendNode('dependencies')
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 {
// testFixturesJar is automatically included by components.java when the java-test-fixtures
// plugin is applied, so it should only be added explicitly when publishing the shadow
// component (which does not include the test-fixtures variant).
def artifactTaskNames = ["srcJar", "javadocJar", "scaladocJar", "testJar", "testSrcJar"]
if (shouldPublishWithShadow) {
artifactTaskNames += "testFixturesJar"
}
artifactTaskNames.forEach { taskName ->
def task = tasks.findByName(taskName)
if (task != null)
artifact task
}
artifactId = base.archivesName.get()
pom {
name = 'Apache Kafka'
url = 'https://kafka.apache.org'
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
distribution = 'repo'
}
}
}
}
}
}
}
if (shouldSign) {
signing {
sign publishing.publications.mavenJava
}
}
}
def testLoggingEvents = ["passed", "skipped", "failed"]
def testShowStandardStreams = false
def testExceptionFormat = 'full'
// Gradle built-in logging only supports sending test output to stdout, which generates a lot
// of noise, especially for passing tests. We really only want output for failed tests. This
// hooks into the output and logs it (so we don't have to buffer it all in memory) and only
// saves the output for failing tests. Directory and filenames are such that you can, e.g.,
// create a Jenkins rule to collect failed test output.
def logTestStdout = {
def testId = { TestDescriptor descriptor ->
"${descriptor.className}.${descriptor.name}".toString()
}
def logFiles = new HashMap<String, File>()
def logStreams = new HashMap<String, FileOutputStream>()
beforeTest { TestDescriptor td ->
def tid = testId(td)
// truncate the file name if it's too long
def logFile = new File(
"${projectDir}/build/reports/testOutput/${tid.substring(0, Math.min(tid.size(),240))}.test.stdout"
)
logFile.parentFile.mkdirs()
logFiles.put(tid, logFile)
logStreams.put(tid, new FileOutputStream(logFile))
}
onOutput { TestDescriptor td, TestOutputEvent toe ->
def tid = testId(td)
// Some output can happen outside the context of a specific test (e.g. at the class level)
// and beforeTest/afterTest seems to not be invoked for these cases (and similarly, there's
// a TestDescriptor hierarchy that includes the thread executing the test, Gradle tasks,
// etc). We see some of these in practice and it seems like something buggy in the Gradle
// test runner since we see it *before* any tests and it is frequently not related to any
// code in the test (best guess is that it is tail output from last test). We won't have
// an output file for these, so simply ignore them. If they become critical for debugging,
// they can be seen with showStandardStreams.
if (td.name == td.className || td.className == null) {
// silently ignore output unrelated to specific test methods
return
} else if (logStreams.get(tid) == null) {
println "WARNING: unexpectedly got output for a test [${tid}]" +
" that we didn't previously see in the beforeTest hook." +
" Message for debugging: [" + toe.message + "]."
return
}
try {
logStreams.get(tid).write(toe.message.getBytes(StandardCharsets.UTF_8))
} catch (Exception e) {
println "ERROR: Failed to write output for test ${tid}"
e.printStackTrace()
}
}
afterTest { TestDescriptor td, TestResult tr ->
def tid = testId(td)
try {
logStreams.get(tid).close()
if (tr.resultType != TestResult.ResultType.FAILURE) {
logFiles.get(tid).delete()
} else {
def file = logFiles.get(tid)
println "${tid} failed, log available in ${file}"
}
} catch (Exception e) {
println "ERROR: Failed to close stdout file for ${tid}"
e.printStackTrace()
} finally {
logFiles.remove(tid)
logStreams.remove(tid)
}
}
}
// Workaround for Mockito Java Agent restrictions in Java 21+
// Starting with Java 21, the JDK restricts libraries from attaching a Java agent
// to their own JVM. As a result, Mockito’s inline mock maker (mockito-core)
// fails without explicit instrumentation, and the JVM consistently emits warnings.
// See also: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#mockito-instrumentation
afterEvaluate { subproject ->
def hasMockitoCore = subproject.configurations.findAll {
it.canBeResolved
}.any { config ->
config.incoming.dependencies.any { dependency ->
"$dependency" == libs.mockitoCore
}
}
if (hasMockitoCore) {
subproject.configurations {
mockitoAgent {
transitive = false
}
}
subproject.dependencies {
mockitoAgent libs.mockitoCore
}
}
}
// The suites are for running sets of tests in IDEs.
// Gradle will run each test class, so we exclude the suites to avoid redundantly running the tests twice.
def testsToExclude = ['**/*Suite.class']
// This task will copy JUnit XML files out of the sub-project's build directory and into
// a top-level build/junit-xml directory. This is necessary to avoid reporting on tests which
// were not run, but instead were restored via FROM-CACHE. See KAFKA-17479 for more details.
def copyTestXml = tasks.register('copyTestXml') {
onlyIf("Environment GITHUB_ACTIONS is set") { isGithubActions }
onlyIf("Project '${project.name}:test' has sources") { ! test.state.noSource }
onlyIf("Task '${project.name}:test' did work") { test.state.didWork }
ext {
output = project.findProperty("kafka.test.xml.output.dir")
}
// Never cache this task
outputs.cacheIf { false }
outputs.upToDateWhen { false }
doLast {
def moduleDirPath = projectToJUnitXmlPath(project)
def dest = rootProject.layout.buildDirectory.dir("junit-xml/${moduleDirPath}/${output}").get().asFile
println "Copy JUnit XML for ${project.name} to $dest"
ant.copy(todir: "$dest") {
ant.fileset(dir: "${test.reports.junitXml.entryPoint}") {
ant.include(name: "**/*.xml")
}
}
}
}
test {
doFirst {
def mockitoAgentConfig = configurations.findByName('mockitoAgent')
if (mockitoAgentConfig) {
jvmArgs("-javaagent:${mockitoAgentConfig.asPath}")
}
}
maxParallelForks = maxTestForks
ignoreFailures = userIgnoreFailures
maxHeapSize = "3g"
jvmArgs = defaultJvmArgs
// KAFKA-17433 Used by deflake.yml github action to repeat individual tests
systemProperty("kafka.cluster.test.repeat", project.findProperty("kafka.cluster.test.repeat"))
systemProperty("kafka.test.catalog.file", project.findProperty("kafka.test.catalog.file"))
systemProperty("kafka.test.run.new", project.findProperty("kafka.test.run.new"))
systemProperty("kafka.test.run.flaky", project.findProperty("kafka.test.run.flaky"))
systemProperty("kafka.test.verbose", project.findProperty("kafka.test.verbose"))
testLogging {
events = userTestLoggingEvents ?: testLoggingEvents
showStandardStreams = userShowStandardStreams ?: testShowStandardStreams
exceptionFormat = testExceptionFormat
displayGranularity = 0
}
logTestStdout.rehydrate(delegate, owner, this)()
exclude testsToExclude
useJUnitPlatform {
includeEngines 'junit-jupiter'
}
develocity {
testRetry {
maxRetries = userMaxTestRetries
maxFailures = userMaxTestRetryFailures
}
}
finalizedBy("copyTestXml")
}
tasks.register('integrationTest', Test) {
dependsOn compileJava
testClassesDirs = sourceSets.test.output.classesDirs
classpath = sourceSets.test.runtimeClasspath
maxParallelForks = maxTestForks
ignoreFailures = userIgnoreFailures
// Increase heap size for integration tests
maxHeapSize = "2560m"
jvmArgs = defaultJvmArgs
testLogging {
events = userTestLoggingEvents ?: testLoggingEvents
showStandardStreams = userShowStandardStreams ?: testShowStandardStreams
exceptionFormat = testExceptionFormat
displayGranularity = 0
}
logTestStdout.rehydrate(delegate, owner, this)()
exclude testsToExclude
useJUnitPlatform {
includeTags "integration"
includeEngines 'junit-jupiter'
}
develocity {
testRetry {
maxRetries = userMaxTestRetries
maxFailures = userMaxTestRetryFailures
}
}
}
tasks.register('unitTest', Test) {
dependsOn compileJava
testClassesDirs = sourceSets.test.output.classesDirs
classpath = sourceSets.test.runtimeClasspath
maxParallelForks = maxTestForks
ignoreFailures = userIgnoreFailures
maxHeapSize = defaultMaxHeapSize
jvmArgs = defaultJvmArgs
testLogging {
events = userTestLoggingEvents ?: testLoggingEvents
showStandardStreams = userShowStandardStreams ?: testShowStandardStreams
exceptionFormat = testExceptionFormat
displayGranularity = 0
}
logTestStdout.rehydrate(delegate, owner, this)()
exclude testsToExclude
useJUnitPlatform {
excludeTags "integration"
includeEngines 'junit-jupiter'
}
develocity {
testRetry {
maxRetries = userMaxTestRetries
maxFailures = userMaxTestRetryFailures
}
}
}
// remove test output from all test types
tasks.withType(Test).all { t ->
cleanTest {
delete t.reports.junitXml.outputLocation
delete t.reports.html.outputLocation
}
}
jar {
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
}
tasks.register('srcJar', Jar) {
archiveClassifier = 'sources'
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
from sourceSets.main.allSource
}
tasks.register('javadocJar', Jar) {
dependsOn javadoc
archiveClassifier = 'javadoc'
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
from javadoc.destinationDir
}
tasks.register('docsJar') { dependsOn javadocJar }
// Consumed by root aggregatedJavadoc; mirrors compileClasspath.
configurations {
javadocClasspathElements {
canBeConsumed = true
canBeResolved = false
extendsFrom configurations.compileClasspath
}
}
check.dependsOn('javadoc')
kafkaPublicApiChecker {
// Jars produced by this project — the surface that's actually validated.
projectJarFiles.from(jar.archiveFile)
// Sibling Kafka modules this project depends on (direct or transitive). Their classes
// are merged into the scanned surface so cross-module @InterfaceAudience.Public references
// resolve, but they don't contribute to this module's MISSING_JAVADOC or cascade
// iteration — each module checks its own surface.
referenceJarFiles.from(
configurations.compileClasspath.incoming.artifactView {
// Resolve project deps to their assembled JAR (not the classes-dir variant Gradle
// picks by default for compile-classpath), so the scanner only sees real jars.
attributes {
attribute(org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
objects.named(org.gradle.api.attributes.LibraryElements,
org.gradle.api.attributes.LibraryElements.JAR))
}
componentFilter { it instanceof org.gradle.api.artifacts.component.ProjectComponentIdentifier }
}.files
)
enabled = true
failOnViolation = true
}
tasks.register('systemTestLibs') { dependsOn jar }
if (!sourceSets.test.allSource.isEmpty()) {
tasks.register('testJar', Jar) {
archiveClassifier = 'test'
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
from sourceSets.test.output
// The junit-platform.properties file is used for configuring and customizing the behavior of the JUnit platform.
// It should only apply to Kafka's own JUnit tests, and should not exist in the test JAR.
// If we include it in the test JAR, it could lead to conflicts with user configurations.
exclude 'junit-platform.properties'
}
tasks.register('testSrcJar', Jar) {
dependsOn testJar
archiveClassifier = 'test-sources'
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
from sourceSets.test.allSource
}
}
plugins.withType(ScalaPlugin) {
scala {
zincVersion = versions.zinc
}
tasks.register('scaladocJar', Jar) {
dependsOn scaladoc
archiveClassifier = 'scaladoc'
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
from scaladoc.destinationDir
}
//documentation task should also trigger building scala doc jar
docsJar.dependsOn scaladocJar
}
tasks.withType(ScalaCompile) {
def releaseVersion = modulesNeedingJava11.any { project.path == it } ? minClientJavaVersion : minNonClientJavaVersion
scalaCompileOptions.keepAliveMode = userKeepAliveMode
scalaCompileOptions.additionalParameters = [
"-deprecation:false",
"-unchecked",
"-encoding", "utf8",
"-Xlog-reflective-calls",
"-feature",
"-language:postfixOps",
"-language:implicitConversions",
"-language:existentials",
"-Ybackend-parallelism", maxScalacThreads.toString(),
"-Xlint:constant",
"-Xlint:delayedinit-select",
"-Xlint:doc-detached",
"-Xlint:missing-interpolator",
"-Xlint:nullary-unit",
"-Xlint:option-implicit",
"-Xlint:package-object-classes",
"-Xlint:poly-implicit-overload",
"-Xlint:private-shadow",
"-Xlint:stars-align",
"-Xlint:type-parameter-shadow",
"-Xlint:unused"
]
// See README.md for details on this option and the meaning of each value
if (userScalaOptimizerMode.equals("method"))
scalaCompileOptions.additionalParameters += ["-opt:l:method"]
else if (userScalaOptimizerMode.startsWith("inline-")) {
List<String> inlineFrom = ["-opt-inline-from:org.apache.kafka.**"]
if (project.name.equals('core'))
inlineFrom.add("-opt-inline-from:kafka.**")
if (userScalaOptimizerMode.equals("inline-scala"))
inlineFrom.add("-opt-inline-from:scala.**")
scalaCompileOptions.additionalParameters += ["-opt:l:inline"]
scalaCompileOptions.additionalParameters += inlineFrom
}
scalaCompileOptions.additionalParameters += ["-opt-warnings", "-Xlint:strict-unsealed-patmat"]
// Scala 2.13.2 introduces compiler warnings suppression, which is a pre-requisite for -Xfatal-warnings
scalaCompileOptions.additionalParameters += ["-Xfatal-warnings"]
scalaCompileOptions.additionalParameters += ["--release", String.valueOf(releaseVersion)]
// Gradle does not support the `release` configuration when performing joint Java-Scala compilation.
// For more details, refer to https://github.com/gradle/gradle/issues/13762.
// As a result, we need to explicitly configure the Scala compiler with this setting.
options.compilerArgs += ["--release", String.valueOf(releaseVersion)]
configureJavaCompiler(name, options, project.path)
configure(scalaCompileOptions.forkOptions) {
memoryMaximumSize = defaultMaxHeapSize
jvmArgs = defaultJvmArgs
}
}
checkstyle {
configDirectory = rootProject.layout.projectDirectory.dir("checkstyle")
configProperties = checkstyleConfigProperties("import-control.xml")
toolVersion = versions.checkstyle
}
configure(checkstyleMain) {
group = 'Verification'
description = 'Run checkstyle on all main Java sources'
}
configure(checkstyleTest) {
group = 'Verification'
description = 'Run checkstyle on all test Java sources'
}
test.dependsOn('checkstyleMain', 'checkstyleTest')
spotbugs {
toolVersion = versions.spotbugs
excludeFilter = file("$rootDir/gradle/spotbugs-exclude.xml")
ignoreFailures = false
}
test.dependsOn('spotbugsMain')
tasks.withType(com.github.spotbugs.snom.SpotBugsTask).configureEach {
reports.configure {
// Continue supporting `xmlFindBugsReport` for compatibility
xml.enabled(project.hasProperty('xmlSpotBugsReport') || project.hasProperty('xmlFindBugsReport'))
html.enabled(!project.hasProperty('xmlSpotBugsReport') && !project.hasProperty('xmlFindBugsReport'))
}
maxHeapSize = defaultMaxHeapSize
jvmArgs = defaultJvmArgs
}
// Ignore core since its a scala project
if (it.path != ':core') {
if (userEnableTestCoverage) {
apply plugin: "jacoco"
jacoco {
toolVersion = versions.jacoco
}
jacocoTestReport {
dependsOn tasks.test
sourceSets sourceSets.main
reports {
html.required = true
xml.required = true
csv.required = false
}
}
}
}
if (userEnableTestCoverage) {
def coverageGen = it.path == ':core' ? 'reportTestScoverage' : 'jacocoTestReport'
tasks.register('reportCoverage').configure { dependsOn(coverageGen) }
}
dependencyCheck {
suppressionFile = "$rootDir/gradle/resources/dependencycheck-suppressions.xml"
skipProjects = [ ":jmh-benchmarks", ":trogdor" ]
skipConfigurations = [ "zinc" ]
}
apply plugin: 'com.diffplug.spotless'
spotless {
java {
targetExclude('**/generated/**/*.java','**/generated-test/**/*.java')
importOrder('kafka', 'org.apache.kafka', 'com', 'net', 'org', 'java', 'javax', '', '\\#')
// removeUnusedImports is intentionally omitted because its engines
// (google-java-format, cleanthat) can non-deterministically throw
// InvocationTargetException under parallel execution. Unused imports are
// still enforced by checkstyle (UnusedImports + RedundantImport).
// Re-enable once https://github.com/diffplug/spotless/issues/2850 is fixed.
}
}
tasks.register("checkJsonLicenseHeader") {
group = "Verification"
description = "Verify ASF License header in JSON files"
doLast {
def asfHeader = file("${rootProject.projectDir}/gradle/LICENSE.json").readLines()*.trim()
def incorrectFiles = fileTree(projectDir) {
include 'src/main/resources/**/*.json'
include 'src/test/resources/**/*.json'
}.findAll { f ->
f.readLines().take(asfHeader.size())*.trim() != asfHeader
}
if (incorrectFiles) {
println "\n${project.name}: Incorrect ASF license header in JSON files:"
incorrectFiles.each { println " - $it" }
throw new GradleException("${incorrectFiles.size()} JSON files with incorrect ASF license header")
}
}
}
check.dependsOn("checkJsonLicenseHeader")
}
gradle.taskGraph.whenReady { taskGraph ->
taskGraph.getAllTasks().findAll { it.name.contains('spotbugsScoverage') || it.name.contains('spotbugsTest') }.each { task ->
task.enabled = false
}
}
def fineTuneEclipseClasspathFile(eclipse, project) {
eclipse.classpath.file {
beforeMerged { cp ->
cp.entries.clear()
// for the core project add the directories defined under test/scala as separate source directories
if (project.name.equals('core')) {
cp.entries.add(new org.gradle.plugins.ide.eclipse.model.SourceFolder("src/test/scala/integration", null))
cp.entries.add(new org.gradle.plugins.ide.eclipse.model.SourceFolder("src/test/scala/other", null))
cp.entries.add(new org.gradle.plugins.ide.eclipse.model.SourceFolder("src/test/scala/unit", null))
}
}
whenMerged { cp ->
// for the core project exclude the separate sub-directories defined under test/scala. These are added as source dirs above
if (project.name.equals('core')) {
cp.entries.findAll { it.kind == "src" && it.path.equals("src/test/scala") }*.excludes = ["integration/", "other/", "unit/"]
}
/*
* Set all eclipse build output to go to 'build_eclipse' directory. This is to ensure that gradle and eclipse use different
* build output directories, and also avoid using the eclipse default of 'bin' which clashes with some of our script directories.
* https://discuss.gradle.org/t/eclipse-generated-files-should-be-put-in-the-same-place-as-the-gradle-generated-files/6986/2
*/
cp.entries.findAll { it.kind == "output" }*.path = "build_eclipse"
/*
* Some projects have explicitly added test output dependencies. These are required for the gradle build but not required
* in Eclipse since the dependent projects are added as dependencies. So clean up these from the generated classpath.
*/
cp.entries.removeAll { it.kind == "lib" && it.path.matches(".*/build/(classes|resources)/test") }
}
}
}
def checkstyleConfigProperties(configFileName) {
[importControlFile: "$configFileName"]
}
if (userEnableTestCoverage) {
tasks.register('reportCoverage').configure { dependsOn(subprojects.reportCoverage) }
}
def connectPkgs = [
'connect:api',
'connect:basic-auth-extension',
'connect:file',
'connect:json',
'connect:runtime',
'connect:test-plugins',
'connect:transforms',
'connect:mirror',
'connect:mirror-client'
]
tasks.create(name: "jarConnect", dependsOn: connectPkgs.collect { it + ":jar" }) {}
tasks.create(name: "testConnect", dependsOn: connectPkgs.collect { it + ":test" }) {}
project(':server') {
base {
archivesName = "kafka-server"
}
apply plugin: 'java-test-fixtures'
configurations {
// To prevent a UniqueResourceException due the same resource existing in both
// org.apache.directory.api/api-all and org.apache.directory.api/api-ldap-schema-data
testImplementation.exclude module: 'api-ldap-schema-data'
testFixturesImplementation.exclude module: 'api-ldap-schema-data'
testFixturesImplementation.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
testCompileClasspath.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
testRuntimeClasspath.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
// JUnit 4 is a transitive runtime dependency of mock-oauth2-server (via okhttp3 mockwebserver),
// keep it off the compile classpath so tests can't accidentally use JUnit 4 APIs.
testCompileClasspath.exclude group: 'junit', module: 'junit'
}
dependencies {
implementation libs.commonsValidator
implementation project(':clients')
implementation project(':metadata')
implementation project(':server-common')
implementation project(':storage')
implementation project(':group-coordinator')
implementation project(':group-coordinator:group-coordinator-api')
implementation project(':transaction-coordinator')
implementation project(':raft')
implementation project(':share-coordinator')
implementation project(':mirror-coordinator')
implementation project(':storage:storage-api')
implementation libs.jacksonDatabind
implementation libs.metrics
implementation libs.slf4jApi
implementation log4j2Libs
testImplementation testFixtures(project(':clients'))
testImplementation project(':coordinator-common')
testImplementation libs.mockitoCore
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testImplementation project(':test-common:test-common-internal-api')
testImplementation project(':test-common:test-common-runtime')
testImplementation testFixtures(project(':storage:storage-api'))
testImplementation testFixtures(project(':server-common'))
testImplementation testFixtures(project(':metadata'))
testImplementation libs.mockOAuth2Server
testFixturesImplementation project(':clients')
testFixturesImplementation testFixtures(project(':clients'))
testFixturesImplementation project(':metadata')
testFixturesImplementation project(':server-common')
testFixturesImplementation testFixtures(project(':server-common'))
testFixturesImplementation libs.junitJupiter
testFixturesImplementation(libs.apacheda) {
exclude group: 'xml-apis', module: 'xml-apis'
// `mina-core` is a transitive dependency for `apacheds` and `apacheda`.
// It is safer to use from `apacheds` since that is the implementation.
exclude module: 'mina-core'
}
testFixturesImplementation libs.apachedsCoreApi
testFixturesImplementation libs.apachedsInterceptorKerberos
testFixturesImplementation libs.apachedsProtocolShared
testFixturesImplementation libs.apachedsProtocolKerberos
testFixturesImplementation libs.apachedsProtocolLdap
testFixturesImplementation libs.apachedsLdifPartition
testFixturesImplementation libs.apachedsMavibotPartition
testFixturesImplementation libs.apachedsJdbmPartition
testRuntimeOnly runtimeTestLibs
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-server.xml")
}
javadoc {
enabled = false
}
}
project(':core') {
apply plugin: 'scala'
// scaladoc generation is configured at the sub-module level with an artifacts
// block (cf. see streams-scala). If scaladoc generation is invoked explicitly
// for the `core` module, this ensures the generated jar doesn't include scaladoc
// files since the `core` module doesn't include public APIs.
scaladoc {
enabled = false
}
if (userEnableTestCoverage)
apply plugin: "org.scoverage"
base {
archivesName = "kafka_${versions.baseScala}"
}
configurations {
// manually excludes some unnecessary dependencies
implementation.exclude module: 'javax'
implementation.exclude module: 'jline'
implementation.exclude module: 'jms'
implementation.exclude module: 'jmxri'
implementation.exclude module: 'jmxtools'
implementation.exclude module: 'mail'
releaseOnly
}
dependencies {
releaseOnly log4jReleaseLibs
// `core` is often used in users' tests, define the following dependencies as `api` for backwards compatibility
// even though the `core` module doesn't expose any public API
api project(':clients')
api libs.scalaLibrary
compileOnly log4j2Libs
implementation project(':server-common')
implementation project(':group-coordinator:group-coordinator-api')
implementation project(':group-coordinator')
implementation project(':transaction-coordinator')
implementation project(':metadata')
implementation project(':storage:storage-api')
// tools-api is automatically included in releaseTarGz via core's runtimeClasspath.
// If removed from here, remember to explicitly add it back in the releaseTarGz task.
implementation project(':tools:tools-api')
implementation project(':raft')
implementation project(':storage')
implementation project(':server')
implementation project(':coordinator-common')
implementation project(':share-coordinator')
implementation project(':mirror-coordinator')
implementation libs.argparse4j
implementation libs.jacksonDatabind
implementation libs.jacksonJDK8Datatypes
implementation libs.jacksonDataformatYaml
implementation libs.joptSimple
implementation libs.jose4j
implementation libs.metrics
// only needed transitively, but set it explicitly to ensure it has the same version as scala-library
implementation libs.scalaReflect
implementation libs.scalaLogging
implementation libs.slf4jApi
implementation libs.re2j
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':group-coordinator'))
testImplementation testFixtures(project(':share-coordinator'))
testImplementation testFixtures(project(':metadata'))
testImplementation testFixtures(project(':raft'))
testImplementation testFixtures(project(':server-common'))
testImplementation testFixtures(project(':storage:storage-api'))
// No source need - added for scala flattening/classpath presence so LocalTieredStorage lands in
// core/build/dependant-testlibs/ for ducktape system tests.
testImplementation testFixtures(project(':storage'))
testImplementation testFixtures(project(':server'))
testImplementation project(':streams')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':test-common:test-common-internal-api')
testImplementation project(':test-common:test-common-util')
testImplementation libs.apachedsCoreApi
testImplementation libs.bcpkix
testImplementation libs.mockitoCore
testImplementation(libs.apacheda) {
exclude group: 'xml-apis', module: 'xml-apis'
// `mina-core` is a transitive dependency for `apacheds` and `apacheda`.
// It is safer to use from `apacheds` since that is the implementation.
exclude module: 'mina-core'
}
testImplementation libs.apachedsInterceptorKerberos
testImplementation libs.apachedsProtocolShared
testImplementation libs.apachedsProtocolKerberos
testImplementation libs.apachedsProtocolLdap
testImplementation libs.apachedsLdifPartition
testImplementation libs.apachedsMavibotPartition
testImplementation libs.apachedsJdbmPartition
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testImplementation libs.mockOAuth2Server
configurations {
// To prevent a UniqueResourceException due the same resource existing in both
// org.apache.directory.api/api-all and org.apache.directory.api/api-ldap-schema-data
testRuntimeOnly.exclude module: 'api-ldap-schema-data'
testCompileClasspath.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
testRuntimeClasspath.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
// JUnit 4 is a transitive runtime dependency of mock-oauth2-server (via okhttp3 mockwebserver),
// keep it off the compile classpath so tests can't accidentally use JUnit 4 APIs.
testCompileClasspath.exclude group: 'junit', module: 'junit'
}
testRuntimeOnly(libs.apacheda) {
exclude group: 'xml-apis', module: 'xml-apis'
// `mina-core` is a transitive dependency for `apacheds` and `apacheda`.
// It is safer to use from `apacheds` since that is the implementation.
exclude module: 'mina-core'
}
testRuntimeOnly libs.apachedsInterceptorKerberos
testRuntimeOnly libs.apachedsProtocolKerberos
testRuntimeOnly libs.apachedsProtocolLdap
testRuntimeOnly libs.apachedsLdifPartition
testRuntimeOnly runtimeTestLibs
}
if (userEnableTestCoverage) {
scoverage {
scoverageVersion = versions.scoverage
scoverageScalaVersion = versions.scala
reportDir = file("${layout.buildDirectory.get().asFile.path}/scoverage")
highlighting = false
minimumRate = 0.0
}
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
tasks.register('genProtocolErrorDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.common.protocol.Errors'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "protocol_errors.html").newOutputStream()
}
tasks.register('genProtocolTypesDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.common.protocol.types.Type'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "protocol_types.html").newOutputStream()
}
tasks.register('genProtocolApiKeyDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.common.protocol.ApiKeys'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "protocol_api_keys.html").newOutputStream()
}
tasks.register('genProtocolMessageDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.common.protocol.Protocol'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "protocol_messages.html").newOutputStream()
}
tasks.register('genAdminClientConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.clients.admin.AdminClientConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "admin_client_config.html").newOutputStream()
}
tasks.register('genProducerConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.clients.producer.ProducerConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "producer_config.html").newOutputStream()
}
tasks.register('genConsumerConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.clients.consumer.ConsumerConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "consumer_config.html").newOutputStream()
}
tasks.register('genKafkaConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'kafka.server.KafkaConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "kafka_config.html").newOutputStream()
}
tasks.register('genTopicConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.storage.internals.log.LogConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "topic_config.html").newOutputStream()
}
tasks.register('genGroupConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.coordinator.group.GroupConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "group_config.html").newOutputStream()
}
tasks.register('genConsumerMetricsDocs', JavaExec) {
classpath = sourceSets.test.runtimeClasspath
mainClass = 'org.apache.kafka.clients.consumer.internals.FetchMetricsRegistry'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "consumer_metrics.html").newOutputStream()
}
tasks.register('genProducerMetricsDocs', JavaExec) {
classpath = sourceSets.test.runtimeClasspath
mainClass = 'org.apache.kafka.clients.producer.internals.ProducerMetrics'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "producer_metrics.html").newOutputStream()
}
tasks.register('siteDocsTar', Tar) {
dependsOn = ['genProtocolErrorDocs', 'genProtocolTypesDocs', 'genProtocolApiKeyDocs', 'genProtocolMessageDocs',
'genAdminClientConfigDocs', 'genProducerConfigDocs', 'genConsumerConfigDocs',
'genKafkaConfigDocs', 'genTopicConfigDocs', 'genGroupConfigDocs',
':connect:runtime:genConnectConfigDocs', ':connect:runtime:genConnectTransformationDocs',
':connect:runtime:genConnectPredicateDocs',
':connect:runtime:genSinkConnectorConfigDocs', ':connect:runtime:genSourceConnectorConfigDocs',
':streams:genStreamsConfigDocs', 'genConsumerMetricsDocs', 'genProducerMetricsDocs',
':connect:runtime:genConnectMetricsDocs', ':connect:runtime:genConnectOpenAPIDocs',
':connect:mirror:genMirrorSourceConfigDocs', ':connect:mirror:genMirrorCheckpointConfigDocs',
':connect:mirror:genMirrorHeartbeatConfigDocs', ':connect:mirror:genMirrorConnectorConfigDocs',
':storage:genRemoteLogManagerConfigDoc', ':storage:genRemoteLogMetadataManagerConfigDoc']
archiveClassifier = 'site-docs'
compression = Compression.GZIP
from project.file("$rootDir/docs")
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
into 'site-docs'
duplicatesStrategy = 'exclude'
}
tasks.register('releaseTarGz', Tar) {
dependsOn = configurations.archives.artifacts
into "kafka_${versions.baseScala}-${archiveVersion.get()}"
compression = Compression.GZIP
from(project.file("$rootDir/bin")) { into "bin/" }
from(project.file("$rootDir/config")) { into "config/" }
from(project.file("$rootDir/licenses")) { into "licenses/" }
from "$rootDir/LICENSE-binary" rename {String filename -> filename.replace("-binary", "")}
from "$rootDir/NOTICE-binary" rename {String filename -> filename.replace("-binary", "")}
from(configurations.runtimeClasspath) { into("libs/") }
from(configurations.archives.artifacts.files) { into("libs/") }
from(configurations.releaseOnly) { into("libs/") }
from(project.siteDocsTar) { into("site-docs/") }
from(project(':tools').jar) { into("libs/") }
from(project(':tools').configurations.runtimeClasspath) { into("libs/") }
from(project(':trogdor').jar) { into("libs/") }
from(project(':trogdor').configurations.runtimeClasspath) { into("libs/") }
from(project(':shell').jar) { into("libs/") }
from(project(':shell').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:api').jar) { into("libs/") }
from(project(':connect:api').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:runtime').jar) { into("libs/") }
from(project(':connect:runtime').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:transforms').jar) { into("libs/") }
from(project(':connect:transforms').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:json').jar) { into("libs/") }
from(project(':connect:json').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:file').jar) { into("libs/") }
from(project(':connect:file').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:basic-auth-extension').jar) { into("libs/") }
from(project(':connect:basic-auth-extension').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:mirror').jar) { into("libs/") }
from(project(':connect:mirror').configurations.runtimeClasspath) { into("libs/") }
from(project(':connect:mirror-client').jar) { into("libs/") }
from(project(':connect:mirror-client').configurations.runtimeClasspath) { into("libs/") }
from(project(':streams').jar) { into("libs/") }
from(project(':streams').configurations.runtimeClasspath) { into("libs/") }
from(project(':streams:streams-scala').jar) { into("libs/") }
from(project(':streams:streams-scala').configurations.runtimeClasspath) { into("libs/") }
from(project(':streams:test-utils').jar) { into("libs/") }
from(project(':streams:test-utils').configurations.runtimeClasspath) { into("libs/") }
from(project(':streams:examples').jar) { into("libs/") }
from(project(':streams:examples').configurations.runtimeClasspath) { into("libs/") }
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
jar.manifest {
attributes(
'Version': "${version}"
)
}
test {
useJUnitPlatform {
includeEngines 'junit-jupiter'
}
}
tasks.register('copyDependantTestLibs', Copy) {
from (configurations.testRuntimeClasspath) {
include('*.jar')
}
from (configurations.releaseOnly)
into "${layout.buildDirectory.get().asFile.path}/dependant-testlibs"
//By default gradle does not handle test dependencies between the sub-projects
//This line is to include clients project test jar to dependant-testlibs
from (project(':clients').testJar ) { "${layout.buildDirectory.get().asFile.path}/dependant-testlibs" }
duplicatesStrategy = 'exclude'
}
systemTestLibs.dependsOn('jar', 'testJar', 'copyDependantTestLibs')
checkstyle {
configProperties = checkstyleConfigProperties("import-control-core.xml")
}
sourceSets {
// Set java/scala source folders in the `scala` block to enable joint compilation
main {
java {
srcDirs = []
}
scala {
srcDirs = ["src/main/java", "src/main/scala"]
}
}
test {
java {
srcDirs = []
}
scala {
srcDirs = ["src/test/java", "src/test/scala"]
}
}
}
}
project(':metadata') {
base {
archivesName = "kafka-metadata"
}
apply plugin: 'java-test-fixtures'
configurations {
generator
}
dependencies {
implementation project(':server-common')
implementation project(':clients')
implementation project(':raft')
implementation libs.jacksonDatabind
implementation libs.metrics
implementation libs.slf4jApi
testImplementation testLog4j2Libs
testFixturesImplementation testFixtures(project(':server-common'))
testFixturesImplementation project(':raft')
testFixturesImplementation libs.junitJupiter
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':raft'))
testImplementation testFixtures(project(':server-common'))
testImplementation project(':test-common:test-common-util')
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.common.metadata",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/common/metadata",
"-i", "src/main/resources/common/metadata",
"-m", "MessageDataGenerator", "JsonConverterGenerator",
"-t", "MetadataRecordTypeGenerator", "MetadataJsonConvertersGenerator"
]
inputs.dir("src/main/resources/common/metadata")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/common/metadata")
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
javadoc {
enabled = false
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-metadata.xml")
}
}
project(':group-coordinator:group-coordinator-api') {
base {
archivesName = "kafka-group-coordinator-api"
}
dependencies {
implementation project(':clients')
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
javadoc {
include "**/org/apache/kafka/coordinator/group/api/**"
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-group-coordinator.xml")
}
}
project(':group-coordinator') {
base {
archivesName = "kafka-group-coordinator"
}
apply plugin: 'java-test-fixtures'
configurations {
generator
}
dependencies {
implementation project(':server-common')
implementation project(':clients')
implementation project(':metadata')
implementation project(':group-coordinator:group-coordinator-api')
implementation project(':storage')
implementation project(':coordinator-common')
implementation libs.jacksonDatabind
implementation libs.metrics
implementation libs.re2j
implementation libs.slf4jApi
implementation libs.hash4j
testFixturesImplementation project(':clients')
testFixturesImplementation project(':coordinator-common')
testFixturesImplementation project(':server-common')
testFixturesImplementation libs.junitJupiter
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':server-common'))
testImplementation testFixtures(project(':coordinator-common'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
javadoc {
enabled = false
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-group-coordinator.xml")
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.coordinator.group.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/group/generated",
"-i", "src/main/resources/common/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator",
"-t", "CoordinatorRecordTypeGenerator", "CoordinatorRecordJsonConvertersGenerator"
]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/group/generated")
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
}
project(':test-common:test-common-internal-api') {
// Interfaces, config classes, and other test APIs. Java 17 is the minimum Java version.
base {
archivesName = "kafka-test-common-internal-api"
}
dependencies {
implementation project(':server-common') // Only project dependency allowed
implementation libs.junitJupiterApi
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-test-common-internal-api.xml")
}
javadoc {
enabled = false
}
}
project(':test-common:test-common-util') {
// Runtime-only JUnit extensions for entire project. Java 11 is the minimum Java version required.
base {
archivesName = "kafka-test-common-util"
}
dependencies {
implementation libs.junitPlatformLauncher
implementation libs.junitJupiterApi
implementation libs.junitJupiter
implementation libs.slf4jApi
testImplementation testLog4j2Libs
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-test-common-util.xml")
}
javadoc {
enabled = false
}
}
project(':test-common:test-common-runtime') {
// Runtime-only JUnit extensions for integration tests. Java 17 is the minimum Java version.
base {
archivesName = "kafka-test-common-runtime"
}
dependencies {
api project(':core')
api project(':clients')
implementation project(':server')
implementation project(':server-common')
implementation project(':group-coordinator')
implementation project(':test-common:test-common-internal-api')
implementation project(':metadata')
implementation project(':raft')
implementation project(':storage')
implementation libs.junitPlatformLauncher
implementation libs.junitJupiter
implementation libs.jacksonDataformatYaml
implementation libs.slf4jApi
implementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-test-common-runtime.xml")
}
javadoc {
enabled = false
}
}
project(':transaction-coordinator') {
base {
archivesName = "kafka-transaction-coordinator"
}
configurations {
generator
}
dependencies {
implementation libs.jacksonDatabind
implementation project(':clients')
implementation project(':server-common')
implementation project(':coordinator-common')
implementation libs.slf4jApi
testImplementation testLog4j2Libs
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testFixtures(project(':clients'))
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':test-common:test-common-internal-api')
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-transaction-coordinator.xml")
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.coordinator.transaction.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/transaction/generated",
"-i", "src/main/resources/common/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator",
"-t", "CoordinatorRecordTypeGenerator", "CoordinatorRecordJsonConvertersGenerator"
]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/transaction/generated")
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
javadoc {
enabled = false
}
}
project(':coordinator-common') {
base {
archivesName = "kafka-coordinator-common"
}
apply plugin: 'java-test-fixtures'
dependencies {
implementation project(':clients')
implementation project(':server-common')
implementation project(':metadata')
implementation project(':storage')
implementation libs.slf4jApi
implementation libs.metrics
implementation libs.hdrHistogram
testFixturesImplementation project(':clients')
testFixturesImplementation project(':metadata')
testFixturesImplementation libs.junitJupiter
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':server-common'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-coordinator-common.xml")
}
javadoc {
enabled = false
}
}
project(':share-coordinator') {
base {
archivesName = "kafka-share-coordinator"
}
apply plugin: 'java-test-fixtures'
configurations {
generator
}
dependencies {
implementation libs.jacksonDatabind
implementation project(':clients')
implementation project(':coordinator-common')
implementation project(':metadata')
implementation project(':server-common')
implementation libs.metrics
implementation libs.slf4jApi
testFixturesImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':server-common'))
testImplementation testFixtures(project(':coordinator-common'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-share-coordinator.xml")
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.coordinator.share.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/share/generated",
"-i", "src/main/resources/common/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator",
"-t", "CoordinatorRecordTypeGenerator", "CoordinatorRecordJsonConvertersGenerator"
]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/share/generated")
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
javadoc {
enabled = false
}
}
project(':mirror-coordinator') {
base {
archivesName = "kafka-mirror-coordinator"
}
configurations {
generator
}
dependencies {
implementation libs.re2j
implementation libs.jacksonDatabind
implementation project(':clients')
implementation project(':server-common')
implementation project(':coordinator-common')
testImplementation project(':server-common')
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-mirror-coordinator.xml")
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.coordinator.mirror.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/mirror/generated",
"-i", "src/main/resources/common/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator",
"-t", "CoordinatorRecordTypeGenerator", "CoordinatorRecordJsonConvertersGenerator"
]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/coordinator/mirror/generated")
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
javadoc {
enabled = false
}
}
project(':examples') {
base {
archivesName = "kafka-examples"
}
dependencies {
implementation project(':clients')
}
javadoc {
enabled = false
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-examples.xml")
}
}
project(':generator') {
dependencies {
implementation libs.argparse4j
implementation libs.jacksonDatabind
implementation libs.jacksonJDK8Datatypes
implementation libs.jgit
implementation libs.jgitSshApache
implementation libs.jgitGpgBc
testImplementation libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
}
project(':clients') {
base {
archivesName = "kafka-clients"
}
apply plugin: 'java-test-fixtures'
configurations {
generator
shadowed
}
dependencies {
implementation libs.zstd
implementation libs.lz4
implementation libs.snappy
implementation libs.opentelemetryProto
implementation libs.protobuf
implementation libs.slf4jApi
// commons-io is a transitive dependency not needed by SubnetUtils/SubnetUtils6
implementation(libs.commonsNet) {
exclude group: 'commons-io', module: 'commons-io'
}
// libraries which should be added as runtime dependencies in generated pom.xml should be defined here:
shadowed libs.zstd
shadowed libs.lz4
shadowed libs.snappy
shadowed libs.slf4jApi
compileOnly libs.jacksonDatabind // for SASL/OAUTHBEARER bearer token parsing
compileOnly libs.jose4j // for SASL/OAUTHBEARER JWT validation; only used by broker
testFixturesImplementation project(':test-common:test-common-util')
testFixturesImplementation libs.bcpkix
testFixturesImplementation libs.junitJupiter
testFixturesImplementation testLog4j2Libs
testImplementation libs.bcpkix
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testImplementation project(':test-common:test-common-util')
testImplementation libs.jacksonJakartarsJsonProvider
testImplementation libs.jose4j
testImplementation libs.mockitoCore
testImplementation libs.mockitoJunitJupiter // supports MockitoExtension
testImplementation libs.testcontainersKeycloak
testRuntimeOnly libs.jacksonDatabind
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
tasks.withType(GenerateModuleMetadata) {
enabled = false
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
shadowJar {
dependsOn createVersionFile
// archiveClassifier defines the classifier for the shadow jar, the default is 'all'.
// We don't want to use the default classifier because it will cause the shadow jar to
// overwrite the original jar. We also don't want to use the 'shadow' classifier because
// it will cause the shadow jar to be named kafka-clients-shadow.jar. We want to use the
// same name as the original jar, kafka-clients.jar.
archiveClassifier = null
// KIP-714: move shaded dependencies to a shaded location
relocate('io.opentelemetry.proto', 'org.apache.kafka.shaded.io.opentelemetry.proto')
relocate('com.google.protobuf', 'org.apache.kafka.shaded.com.google.protobuf')
relocate('org.apache.commons.net', 'org.apache.kafka.shaded.org.apache.commons.net')
// dependencies excluded from the final jar, since they are declared as runtime dependencies
dependencies {
project.configurations.shadowed.allDependencies.each {
exclude(dependency(it))
}
// exclude proto files from the jar
exclude "**/opentelemetry/proto/**/*.proto"
exclude "**/google/protobuf/*.proto"
}
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
from "$rootDir/LICENSE"
from "$rootDir/NOTICE"
}
jar {
enabled = false
dependsOn 'shadowJar'
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.common.message",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/common/message",
"-i", "src/main/resources/common/message",
"-t", "ApiMessageTypeGenerator",
"-m", "MessageDataGenerator", "JsonConverterGenerator"
]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/common/message")
}
tasks.register('processTestMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.common.message",
"-o", "${projectDir}/build/generated/test/java/org/apache/kafka/common/message",
"-i", "src/test/resources/common/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator"
]
inputs.dir("src/test/resources/common/message")
.withPropertyName("testMessages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/test/java/org/apache/kafka/common/message")
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java", "${projectDir}/build/generated/test/java"]
}
}
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
compileTestJava.dependsOn 'processTestMessages'
javadoc {
include "**/org/apache/kafka/clients/admin/*"
include "**/org/apache/kafka/clients/consumer/*"
include "**/org/apache/kafka/clients/producer/*"
include "**/org/apache/kafka/common/*"
include "**/org/apache/kafka/common/acl/*"
include "**/org/apache/kafka/common/annotation/*"
include "**/org/apache/kafka/common/config/*"
include "**/org/apache/kafka/common/config/provider/*"
include "**/org/apache/kafka/common/config/types/*"
include "**/org/apache/kafka/common/errors/*"
include "**/org/apache/kafka/common/header/*"
include "**/org/apache/kafka/common/metrics/*"
include "**/org/apache/kafka/common/metrics/stats/*"
include "**/org/apache/kafka/common/quota/*"
include "**/org/apache/kafka/common/record/*"
include "**/org/apache/kafka/common/resource/*"
include "**/org/apache/kafka/common/security/auth/*"
include "**/org/apache/kafka/common/security/oauthbearer/*"
include "**/org/apache/kafka/common/security/plain/*"
include "**/org/apache/kafka/common/security/scram/*"
include "**/org/apache/kafka/common/security/token/delegation/*"
include "**/org/apache/kafka/common/serialization/*"
include "**/org/apache/kafka/common/utils/Bytes.java"
include "**/org/apache/kafka/server/authorizer/*"
include "**/org/apache/kafka/server/policy/*"
include "**/org/apache/kafka/server/quota/*"
include "**/org/apache/kafka/server/telemetry/*"
exclude(
'org/apache/kafka/common/errors/ReadOnlyTopicException.java',
'org/apache/kafka/common/errors/ClusterMirrorAuthorizationException.java',
'org/apache/kafka/common/errors/UnknownClusterMirrorException.java',
'org/apache/kafka/common/errors/TopicAlreadyInClusterMirrorException.java',
'org/apache/kafka/common/errors/MirrorConfigNotAvailableException.java',
'org/apache/kafka/common/errors/ClusterMirrorAlreadyExistsException.java',
'org/apache/kafka/common/errors/SourceMetadataNotAvailableException.java',
'org/apache/kafka/common/errors/TopicNotInClusterMirrorException.java',
'org/apache/kafka/common/errors/InvalidMirrorStateException.java'
)
}
}
project(':clients:clients-integration-tests') {
base {
archivesName = "kafka-clients-integration-tests"
}
configurations {
// To prevent a UniqueResourceException due the same resource existing in both
// org.apache.directory.api/api-all and org.apache.directory.api/api-ldap-schema-data
testImplementation.exclude module: 'api-ldap-schema-data'
testCompileClasspath.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
testRuntimeClasspath.exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on'
}
dependencies {
testImplementation libs.metrics
testImplementation libs.slf4jApi
testImplementation project(':test-common:test-common-internal-api')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':metadata')
testImplementation project(':raft')
testImplementation project(':server')
testImplementation testFixtures(project(':server'))
testImplementation project(':storage')
testImplementation testFixtures(project(':storage'))
testImplementation testFixtures(project(':clients'))
implementation project(':server-common')
testImplementation testFixtures(project(':server-common'))
implementation project(':group-coordinator')
implementation project(':group-coordinator:group-coordinator-api')
implementation project(':transaction-coordinator')
testImplementation project(':test-common:test-common-util')
testImplementation libs.bcpkix
testImplementation(libs.apacheda) {
exclude group: 'xml-apis', module: 'xml-apis'
exclude module: 'mina-core'
}
testImplementation libs.apachedsCoreApi
testImplementation libs.apachedsInterceptorKerberos
testImplementation libs.apachedsProtocolShared
testImplementation libs.apachedsProtocolKerberos
testImplementation libs.apachedsProtocolLdap
testImplementation libs.apachedsLdifPartition
testImplementation libs.apachedsJdbmPartition
testImplementation libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-clients-integration-tests.xml")
}
}
project(':raft') {
base {
archivesName = "kafka-raft"
}
apply plugin: 'java-test-fixtures'
configurations {
generator
}
dependencies {
implementation project(':server-common')
implementation project(':clients')
implementation project(':storage')
implementation libs.jacksonDatabind
implementation libs.slf4jApi
testFixturesImplementation project(':clients')
testFixturesImplementation testFixtures(project(':clients'))
testFixturesImplementation project(':server-common')
testFixturesImplementation libs.junitJupiter
testFixturesImplementation libs.mockitoCore
testFixturesImplementation libs.slf4jApi
testImplementation project(':server-common')
testImplementation testFixtures(project(':server-common'))
testImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.raft.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/raft/generated",
"-i", "src/main/resources/common/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator"]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/raft/generated")
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
test {
useJUnitPlatform {
includeEngines 'junit-jupiter'
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
javadoc {
enabled = false
}
}
project(':server-common') {
base {
archivesName = "kafka-server-common"
}
apply plugin: 'java-test-fixtures'
dependencies {
api project(':clients')
implementation libs.metrics
implementation libs.joptSimple
implementation libs.jacksonDatabind
implementation libs.pcollections
implementation libs.re2j
implementation libs.slf4jApi
testFixturesImplementation testFixtures(project(':clients'))
testFixturesImplementation libs.slf4jApi
testFixturesImplementation libs.metrics
testFixturesImplementation libs.mockitoCore
testFixturesImplementation libs.junitJupiter
testImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-server-common.xml")
}
javadoc {
enabled = false
}
}
project(':storage:storage-api') {
base {
archivesName = "kafka-storage-api"
}
apply plugin: 'java-test-fixtures'
dependencies {
implementation project(':clients')
implementation project(':server-common')
implementation libs.metrics
implementation libs.slf4jApi
testFixturesImplementation project(':clients')
testImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
javadoc {
include "**/org/apache/kafka/server/log/remote/storage/*"
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-storage.xml")
}
}
project(':storage') {
base {
archivesName = "kafka-storage"
}
apply plugin: 'java-test-fixtures'
configurations {
generator
}
dependencies {
implementation project(':storage:storage-api')
implementation project(':server-common')
implementation project(':clients')
implementation(libs.caffeine) {
exclude group: 'org.checkerframework', module: 'checker-qual'
exclude group: 'com.google.errorprone', module: 'error_prone_annotations'
}
implementation libs.slf4jApi
implementation libs.jacksonDatabind
implementation libs.metrics
testFixturesImplementation project(':storage:storage-api')
testFixturesImplementation project(':clients')
testFixturesImplementation testFixtures(project(':clients'))
testFixturesImplementation project(':server-common')
testFixturesImplementation libs.slf4jApi
testImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation project(':core')
testImplementation testFixtures(project(':storage:storage-api'))
testImplementation project(':metadata')
testImplementation project(':test-common:test-common-internal-api')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':test-common:test-common-util')
testImplementation project(':server')
testImplementation testFixtures(project(':server'))
testImplementation project(':server-common')
testImplementation testFixtures(project(':server-common'))
testImplementation testFixtures(project(':metadata'))
testImplementation project(':transaction-coordinator')
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.server.log.remote.metadata.storage.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/server/log/remote/metadata/storage/generated",
"-i", "src/main/resources/message",
"-m", "MessageDataGenerator", "JsonConverterGenerator",
"-t", "MetadataRecordTypeGenerator", "MetadataJsonConvertersGenerator" ]
inputs.dir("src/main/resources/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/server/log/remote/metadata/storage/generated")
}
tasks.register('genRemoteLogManagerConfigDoc', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.server.log.remote.storage.RemoteLogManagerConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "remote_log_manager_config.html").newOutputStream()
}
tasks.register('genRemoteLogMetadataManagerConfigDoc', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.server.log.remote.metadata.storage.TopicBasedRemoteLogMetadataManagerConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "remote_log_metadata_manager_config.html").newOutputStream()
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
javadoc {
enabled = false
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-storage.xml")
}
}
project(':tools:tools-api') {
base {
archivesName = "kafka-tools-api"
}
dependencies {
implementation project(':clients')
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
tasks.register('createVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
outputs.cacheIf { true }
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
jar {
dependsOn createVersionFile
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildVersionFileName"
}
}
clean.doFirst {
delete "${layout.buildDirectory.get().asFile.path}/kafka/"
}
javadoc {
include "**/org/apache/kafka/tools/api/*"
}
}
project(':tools') {
base {
archivesName = "kafka-tools"
}
configurations {
releaseOnly
}
dependencies {
releaseOnly log4jReleaseLibs
implementation project(':clients')
implementation project(':metadata')
implementation project(':storage')
implementation project(':storage:storage-api')
implementation project(':server')
implementation project(':server-common')
implementation project(':connect:runtime')
implementation project(':tools:tools-api')
implementation project(':transaction-coordinator')
implementation project(':group-coordinator')
implementation project(':coordinator-common')
implementation project(':share-coordinator')
implementation project(':raft')
implementation libs.argparse4j
implementation libs.jacksonDatabind
implementation libs.jacksonDataformatCsv
implementation libs.joptSimple
implementation libs.slf4jApi
implementation libs.re2j
implementation libs.jose4j // for SASL/OAUTHBEARER JWT validation
testImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation project(':server')
testImplementation project(':core')
testImplementation testFixtures(project(':server'))
testImplementation project(':test-common:test-common-internal-api')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':server-common')
testImplementation testFixtures(project(':server-common'))
testImplementation project(':connect:api')
testImplementation project(':connect:runtime')
testImplementation testFixtures(project(':connect:runtime'))
testImplementation testFixtures(project(':storage'))
testImplementation project(':streams')
testImplementation testFixtures(project(':streams'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation libs.mockitoJunitJupiter // supports MockitoExtension
testImplementation(libs.jfreechart) {
exclude group: 'junit', module: 'junit'
}
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
}
from (configurations.releaseOnly)
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn 'copyDependantLibs'
}
}
project(':trogdor') {
base {
archivesName = "trogdor"
}
dependencies {
implementation project(':clients')
implementation libs.argparse4j
implementation libs.jacksonDatabind
implementation libs.jacksonJDK8Datatypes
implementation libs.slf4jApi
implementation libs.jacksonJakartarsJsonProvider
implementation libs.jerseyContainerServlet
implementation libs.jerseyHk2
implementation (libs.jettyServer) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyServlet) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyServlets) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation project(':group-coordinator')
implementation project(':group-coordinator:group-coordinator-api')
testImplementation project(':clients')
testImplementation testFixtures(project(':clients'))
testImplementation project(':group-coordinator')
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn 'copyDependantLibs'
}
}
project(':shell') {
base {
archivesName = "kafka-shell"
}
dependencies {
implementation libs.argparse4j
implementation libs.jacksonDatabind
implementation libs.jline
implementation libs.slf4jApi
implementation project(':server-common')
implementation project(':clients')
implementation project(':core')
implementation project(':metadata')
implementation project(':raft')
implementation project(':server')
testImplementation project(':clients')
testImplementation project(':core')
testImplementation project(':server-common')
testImplementation testFixtures(project(':server-common'))
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
include('jline-*jar')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn 'copyDependantLibs'
}
}
project(':streams') {
base {
archivesName = "kafka-streams"
}
apply plugin: 'java-test-fixtures'
ext.buildStreamsVersionFileName = "kafka-streams-version.properties"
configurations {
generator
}
dependencies {
api project(path: ':clients', configuration: 'shadow')
// `org.rocksdb.Options` is part of Kafka Streams public api via `RocksDBConfigSetter`
api libs.rocksDBJni
implementation libs.jacksonAnnotations
implementation libs.jacksonDatabind
implementation libs.slf4jApi
testFixturesImplementation testFixtures(project(':clients'))
testFixturesImplementation libs.junitJupiter
testFixturesImplementation libs.mockitoCore
testFixturesImplementation libs.slf4jApi
// testCompileOnly prevents streams from exporting a dependency on test-utils, which would cause a dependency cycle
testCompileOnly project(':streams:test-utils')
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation libs.mockitoJunitJupiter // supports MockitoExtension
testImplementation libs.junitPlatformSuiteEngine // supports suite test
testImplementation testLog4j2Libs
testRuntimeOnly project(':streams:test-utils')
testRuntimeOnly runtimeTestLibs
generator project(':generator')
}
tasks.register('processMessages', JavaExec) {
mainClass = "org.apache.kafka.message.MessageGenerator"
classpath = configurations.generator
args = [ "-p", "org.apache.kafka.streams.internals.generated",
"-o", "${projectDir}/build/generated/main/java/org/apache/kafka/streams/internals/generated",
"-i", "src/main/resources/common/message",
"-m", "MessageDataGenerator"
]
inputs.dir("src/main/resources/common/message")
.withPropertyName("messages")
.withPathSensitivity(PathSensitivity.RELATIVE)
outputs.cacheIf { true }
outputs.dir("${projectDir}/build/generated/main/java/org/apache/kafka/streams/internals/generated")
}
sourceSets {
main {
java {
srcDirs = ["src/main/java", "${projectDir}/build/generated/main/java"]
}
}
test {
java {
srcDirs = ["src/test/java"]
}
}
}
compileJava.dependsOn 'processMessages'
srcJar.dependsOn 'processMessages'
javadoc {
include "**/org/apache/kafka/streams/**"
exclude "**/org/apache/kafka/streams/internals/**", "**/org/apache/kafka/streams/**/internals/**"
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
tasks.register('createStreamsVersionFile') {
def receiptFile = file("${layout.buildDirectory.get().asFile.path}/kafka/$buildStreamsVersionFileName")
inputs.property "commitId", commitId
inputs.property "version", version
outputs.file receiptFile
doLast {
def data = [
commitId: commitId,
version: version,
]
receiptFile.parentFile.mkdirs()
def content = data.entrySet().collect { "$it.key=$it.value" }.sort().join("\n")
receiptFile.setText(content, "ISO-8859-1")
}
}
jar {
dependsOn 'createStreamsVersionFile'
from("${layout.buildDirectory.get().asFile.path}") {
include "kafka/$buildStreamsVersionFileName"
}
dependsOn 'copyDependantLibs'
}
systemTestLibs {
dependsOn testJar
dependsOn testFixturesJar
}
tasks.register('genStreamsConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.streams.StreamsConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "streams_config.html").newOutputStream()
}
tasks.register('testAll') {
dependsOn = [
':streams:test',
':streams:integration-tests:test',
':streams:test-utils:test',
':streams:streams-scala:test',
':streams:upgrade-system-tests-0110:test',
':streams:upgrade-system-tests-10:test',
':streams:upgrade-system-tests-11:test',
':streams:upgrade-system-tests-20:test',
':streams:upgrade-system-tests-21:test',
':streams:upgrade-system-tests-22:test',
':streams:upgrade-system-tests-23:test',
':streams:upgrade-system-tests-24:test',
':streams:upgrade-system-tests-25:test',
':streams:upgrade-system-tests-26:test',
':streams:upgrade-system-tests-27:test',
':streams:upgrade-system-tests-28:test',
':streams:upgrade-system-tests-30:test',
':streams:upgrade-system-tests-31:test',
':streams:upgrade-system-tests-32:test',
':streams:upgrade-system-tests-33:test',
':streams:upgrade-system-tests-34:test',
':streams:upgrade-system-tests-35:test',
':streams:upgrade-system-tests-36:test',
':streams:upgrade-system-tests-37:test',
':streams:upgrade-system-tests-38:test',
':streams:upgrade-system-tests-39:test',
':streams:upgrade-system-tests-40:test',
':streams:upgrade-system-tests-41:test',
':streams:upgrade-system-tests-42:test',
':streams:upgrade-system-tests-43:test',
':streams:upgrade-system-tests-44:test',
':streams:examples:test'
]
}
}
project(':streams:streams-scala') {
apply plugin: 'scala'
base {
archivesName = "kafka-streams-scala_${versions.baseScala}"
}
dependencies {
api project(':streams')
api libs.scalaLibrary
testImplementation testFixtures(project(':clients'))
testImplementation project(':streams:test-utils')
testImplementation libs.junitJupiter
testImplementation libs.mockitoJunitJupiter // supports MockitoExtension
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
include "**/org/apache/kafka/streams/scala/**"
}
scaladoc {
scalaDocOptions.additionalParameters = ["-no-link-warnings"]
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-streams*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn 'copyDependantLibs'
}
apply plugin: 'com.diffplug.spotless'
spotless {
scala {
target '**/*.scala'
// Skip scalafmt while Spotless is affected by https://github.com/diffplug/spotless/issues/2850.
licenseHeaderFile '../../checkstyle/java.header', 'package'
}
}
}
project(':streams:integration-tests') {
base {
archivesName = "kafka-streams-integration-tests"
}
dependencies {
implementation libs.slf4jApi
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':streams'))
testImplementation project(':group-coordinator')
testImplementation project(':group-coordinator:group-coordinator-api')
testImplementation project(':server')
testImplementation project(':server-common')
testImplementation testFixtures(project(':server-common'))
testImplementation project(':storage')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':tools')
testImplementation project(':transaction-coordinator')
testImplementation libs.junitJupiter
testImplementation libs.junitPlatformSuiteEngine // supports suite test
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testImplementation project(':streams:test-utils')
testRuntimeOnly runtimeTestLibs
}
}
project(':streams:test-utils') {
base {
archivesName = "kafka-streams-test-utils"
}
dependencies {
api project(':streams')
api project(':clients')
implementation libs.slf4jApi
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-streams*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn 'copyDependantLibs'
}
}
project(':streams:examples') {
base {
archivesName = "kafka-streams-examples"
}
dependencies {
implementation project(':streams')
implementation libs.slf4jApi
implementation libs.jacksonDatabind
implementation libs.jacksonAnnotations
testImplementation project(':streams:test-utils')
testImplementation testFixtures(project(':clients'))
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-streams*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs-${versions.scala}"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn 'copyDependantLibs'
}
}
project(':streams:upgrade-system-tests-0110') {
base{
archivesName = "kafka-streams-upgrade-system-tests-0110"
}
dependencies {
testImplementation libs.kafkaStreams_0110
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-10') {
base {
archivesName = "kafka-streams-upgrade-system-tests-10"
}
dependencies {
testImplementation libs.kafkaStreams_10
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-11') {
base {
archivesName = "kafka-streams-upgrade-system-tests-11"
}
dependencies {
testImplementation libs.kafkaStreams_11
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-20') {
base {
archivesName = "kafka-streams-upgrade-system-tests-20"
}
dependencies {
testImplementation libs.kafkaStreams_20
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-21') {
base {
archivesName = "kafka-streams-upgrade-system-tests-21"
}
dependencies {
testImplementation libs.kafkaStreams_21
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-22') {
base {
archivesName = "kafka-streams-upgrade-system-tests-22"
}
dependencies {
testImplementation libs.kafkaStreams_22
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-23') {
base {
archivesName = "kafka-streams-upgrade-system-tests-23"
}
dependencies {
testImplementation libs.kafkaStreams_23
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-24') {
base {
archivesName = "kafka-streams-upgrade-system-tests-24"
}
dependencies {
testImplementation libs.kafkaStreams_24
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-25') {
base {
archivesName = "kafka-streams-upgrade-system-tests-25"
}
dependencies {
testImplementation libs.kafkaStreams_25
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-26') {
base {
archivesName = "kafka-streams-upgrade-system-tests-26"
}
dependencies {
testImplementation libs.kafkaStreams_26
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-27') {
base {
archivesName = "kafka-streams-upgrade-system-tests-27"
}
dependencies {
testImplementation libs.kafkaStreams_27
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-28') {
base {
archivesName = "kafka-streams-upgrade-system-tests-28"
}
dependencies {
testImplementation libs.kafkaStreams_28
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-30') {
base {
archivesName = "kafka-streams-upgrade-system-tests-30"
}
dependencies {
testImplementation libs.kafkaStreams_30
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-31') {
base {
archivesName = "kafka-streams-upgrade-system-tests-31"
}
dependencies {
testImplementation libs.kafkaStreams_31
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-32') {
base {
archivesName = "kafka-streams-upgrade-system-tests-32"
}
dependencies {
testImplementation libs.kafkaStreams_32
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-33') {
base {
archivesName = "kafka-streams-upgrade-system-tests-33"
}
dependencies {
testImplementation libs.kafkaStreams_33
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-34') {
base {
archivesName = "kafka-streams-upgrade-system-tests-34"
}
dependencies {
testImplementation libs.kafkaStreams_34
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-35') {
base {
archivesName = "kafka-streams-upgrade-system-tests-35"
}
dependencies {
testImplementation libs.kafkaStreams_35
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-36') {
base {
archivesName = "kafka-streams-upgrade-system-tests-36"
}
dependencies {
testImplementation libs.kafkaStreams_36
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-37') {
base {
archivesName = "kafka-streams-upgrade-system-tests-37"
}
dependencies {
testImplementation libs.kafkaStreams_37
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-38') {
base {
archivesName = "kafka-streams-upgrade-system-tests-38"
}
dependencies {
testImplementation libs.kafkaStreams_38
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-39') {
base {
archivesName = "kafka-streams-upgrade-system-tests-39"
}
dependencies {
testImplementation libs.kafkaStreams_39
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-40') {
base {
archivesName = "kafka-streams-upgrade-system-tests-40"
}
dependencies {
testImplementation libs.kafkaStreams_40
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-41') {
base {
archivesName = "kafka-streams-upgrade-system-tests-41"
}
dependencies {
testImplementation libs.kafkaStreams_41
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-42') {
base {
archivesName = "kafka-streams-upgrade-system-tests-42"
}
dependencies {
testImplementation libs.kafkaStreams_42
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-43') {
base {
archivesName = "kafka-streams-upgrade-system-tests-43"
}
dependencies {
testImplementation libs.kafkaStreams_43
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':streams:upgrade-system-tests-44') {
base {
archivesName = "kafka-streams-upgrade-system-tests-44"
}
dependencies {
testImplementation libs.kafkaStreams_44
testRuntimeOnly libs.junitJupiter
testRuntimeOnly runtimeTestLibs
}
systemTestLibs {
dependsOn testJar
}
}
project(':jmh-benchmarks') {
apply plugin: 'com.gradleup.shadow'
shadowJar {
archiveBaseName = 'kafka-jmh-benchmarks'
}
dependencies {
implementation(project(':core')) {
// jmh requires jopt 4.x while `core` depends on 5.0, they are not binary compatible
exclude group: 'net.sf.jopt-simple', module: 'jopt-simple'
}
implementation project(':server-common')
implementation project(':server')
implementation project(':raft')
implementation project(':clients')
implementation project(':coordinator-common')
implementation testFixtures(project(':coordinator-common'))
implementation project(':group-coordinator')
implementation project(':group-coordinator:group-coordinator-api')
implementation project(':metadata')
implementation project(':share-coordinator')
implementation project(':storage')
implementation project(':streams')
implementation project(':transaction-coordinator')
implementation project(':core')
implementation project(':connect:api')
implementation project(':connect:transforms')
implementation project(':connect:json')
implementation testFixtures(project(':clients'))
implementation testFixtures(project(':server-common'))
implementation testFixtures(project(':metadata'))
implementation libs.jmhCore
annotationProcessor libs.jmhGeneratorAnnProcess
implementation libs.jacksonDatabind
implementation libs.metrics
implementation libs.mockitoCore
implementation libs.scalaLibrary
implementation libs.slf4jApi
}
tasks.withType(JavaCompile) {
// Suppress warning caused by code generated by jmh: `warning: [cast] redundant cast to long`
options.compilerArgs << "-Xlint:-cast"
}
jar {
manifest {
attributes "Main-Class": "org.openjdk.jmh.Main"
}
}
checkstyle {
configProperties = checkstyleConfigProperties("import-control-jmh-benchmarks.xml")
}
tasks.register('jmh', JavaExec) {
dependsOn = [':jmh-benchmarks:clean', ':jmh-benchmarks:shadowJar']
mainClass = "-jar"
doFirst {
if (System.getProperty("jmhArgs")) {
args System.getProperty("jmhArgs").split(' ')
}
args = [shadowJar.archiveFile.get().asFile, *args]
}
}
javadoc {
enabled = false
}
}
project(':connect:api') {
base {
archivesName = "connect-api"
}
dependencies {
api project(':clients')
implementation libs.jakartaRsApi
implementation libs.slf4jApi
testImplementation libs.junitJupiter
testImplementation testFixtures(project(':clients'))
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
include "**/org/apache/kafka/connect/**" // needed for the `aggregatedJavadoc` task
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:transforms') {
base {
archivesName = "connect-transforms"
}
dependencies {
api project(':connect:api')
implementation libs.slf4jApi
testImplementation libs.junitJupiter
testImplementation testFixtures(project(':clients'))
testImplementation testLog4j2Libs
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:json') {
base {
archivesName = "connect-json"
}
dependencies {
api project(':connect:api')
api libs.jacksonDatabind
api libs.jacksonBlackbird
implementation libs.slf4jApi
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testImplementation testFixtures(project(':clients'))
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:runtime') {
apply plugin: 'java-test-fixtures'
configurations {
swagger
}
base {
archivesName = "connect-runtime"
}
dependencies {
// connect-runtime is used in tests, use `api` for modules below for backwards compatibility even though
// applications should generally not depend on `connect-runtime`
api project(':connect:api')
api project(':clients')
api project(':connect:json')
api project(':connect:transforms')
compileOnly log4j2Libs
implementation libs.slf4jApi
implementation libs.jose4j // for SASL/OAUTHBEARER JWT validation
implementation libs.jacksonAnnotations
implementation libs.jacksonJakartarsJsonProvider
implementation libs.jerseyContainerServlet
implementation libs.jerseyHk2
implementation (libs.jettyServer) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyServlet) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyServlets) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyClient) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation libs.classgraph
implementation libs.mavenArtifact
implementation libs.swaggerAnnotations
// We use this library to generate OpenAPI docs for the REST API, but we don't want or need it at compile
// or run time. So, we add it to a separate configuration, which we use later on during docs generation
swagger libs.jakartaServletApi
swagger libs.jaxrs2Jakarta
testFixturesImplementation testFixtures(project(':clients'))
testFixturesImplementation project(':core')
testFixturesImplementation project(':metadata')
testFixturesImplementation project(':server')
testFixturesImplementation project(':server-common')
testFixturesImplementation project(':group-coordinator')
testFixturesImplementation project(':test-common:test-common-runtime')
testFixturesImplementation libs.jettyClient
testFixturesImplementation libs.jacksonDatabind
testFixturesImplementation libs.jakartaRsApi
testFixturesImplementation libs.slf4jApi
testFixturesImplementation libs.junitJupiter
testImplementation testFixtures(project(':clients'))
testImplementation project(':core')
testImplementation project(':server')
testImplementation project(':metadata')
testImplementation project(':server-common')
testImplementation project(':test-common:test-common-internal-api')
testImplementation project(':test-common:test-common-util')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':raft')
testImplementation project(':group-coordinator')
testImplementation project(':storage')
testImplementation project(':connect:test-plugins')
testImplementation testFixtures(project(':server-common'))
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation libs.mockitoJunitJupiter
testImplementation libs.httpclient
testImplementation testLog4j2Libs
testRuntimeOnly libs.bcpkix
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
tasks.register('genConnectConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.runtime.distributed.DistributedConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "connect_config.html").newOutputStream()
}
tasks.register('genSinkConnectorConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.runtime.SinkConnectorConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "sink_connector_config.html").newOutputStream()
}
tasks.register('genSourceConnectorConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.runtime.SourceConnectorConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "source_connector_config.html").newOutputStream()
}
tasks.register('genConnectTransformationDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.tools.TransformationDoc'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "connect_transforms.html").newOutputStream()
}
tasks.register('genConnectPredicateDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.tools.PredicateDoc'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "connect_predicates.html").newOutputStream()
}
tasks.register('genConnectMetricsDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.runtime.ConnectMetrics'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "connect_metrics.html").newOutputStream()
}
tasks.register('setVersionInOpenAPISpec', Copy) {
from "$rootDir/gradle/openapi.template"
into "${layout.buildDirectory.get().asFile.path}/resources/docs"
rename ('openapi.template', 'openapi.yaml')
expand(kafkaVersion: "$rootProject.version")
}
tasks.register('genConnectOpenAPIDocs', io.swagger.v3.plugins.gradle.tasks.ResolveTask) {
dependsOn setVersionInOpenAPISpec
classpath = sourceSets.main.runtimeClasspath
buildClasspath = classpath + configurations.swagger
outputFileName = 'connect_rest'
outputFormat = 'YAML'
prettyPrint = true
sortOutput = true
encoding = 'UTF-8'
alwaysResolveAppPath = false
skipResolveAppPath = false
readAllResources = true
openApiFile = file("${layout.buildDirectory.get().asFile.path}/resources/docs/openapi.yaml")
resourcePackages = ['org.apache.kafka.connect.runtime.rest.resources']
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
outputDir = file(generatedDocsDir)
}
}
project(':connect:file') {
base {
archivesName = "connect-file"
}
dependencies {
implementation project(':connect:api')
implementation libs.slf4jApi
testImplementation testLog4j2Libs
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testFixtures(project(':clients'))
testImplementation project(':connect:runtime')
testImplementation testFixtures(project(':connect:runtime'))
testImplementation project(':core')
testImplementation project(':test-common:test-common-runtime')
testImplementation testFixtures(project(':server-common'))
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:basic-auth-extension') {
base {
archivesName = "connect-basic-auth-extension"
}
dependencies {
implementation project(':connect:api')
implementation libs.slf4jApi
implementation libs.jakartaRsApi
implementation libs.jakartaAnnotationApi
testImplementation libs.mockitoCore
testImplementation libs.junitJupiter
testImplementation testLog4j2Libs
testImplementation testFixtures(project(':clients'))
testRuntimeOnly libs.jerseyContainerServlet
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:mirror') {
base {
archivesName = "connect-mirror"
}
dependencies {
implementation project(':connect:api')
implementation project(':connect:runtime')
implementation project(':connect:mirror-client')
implementation project(':clients')
implementation libs.argparse4j
implementation libs.slf4jApi
implementation libs.jerseyContainerServlet
implementation libs.jerseyHk2
implementation (libs.jettyServer) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyServlet) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyServlets) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation (libs.jettyClient) {
exclude group: 'org.slf4j', module: 'slf4j-api'
}
implementation libs.swaggerAnnotations
testImplementation testLog4j2Libs
testImplementation libs.junitJupiter
testImplementation libs.mockitoCore
testImplementation testFixtures(project(':clients'))
testImplementation testFixtures(project(':connect:runtime'))
testImplementation project(':core')
testImplementation project(':test-common:test-common-runtime')
testImplementation project(':raft')
testImplementation project(':server')
testImplementation project(':server-common')
testRuntimeOnly project(':connect:runtime')
testRuntimeOnly libs.bcpkix
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = false
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
tasks.register('genMirrorConnectorConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.mirror.MirrorConnectorConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "mirror_connector_config.html").newOutputStream()
}
tasks.register('genMirrorSourceConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.mirror.MirrorSourceConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "mirror_source_config.html").newOutputStream()
}
tasks.register('genMirrorCheckpointConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.mirror.MirrorCheckpointConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "mirror_checkpoint_config.html").newOutputStream()
}
tasks.register('genMirrorHeartbeatConfigDocs', JavaExec) {
classpath = sourceSets.main.runtimeClasspath
mainClass = 'org.apache.kafka.connect.mirror.MirrorHeartbeatConfig'
if( !generatedDocsDir.exists() ) { generatedDocsDir.mkdirs() }
standardOutput = new File(generatedDocsDir, "mirror_heartbeat_config.html").newOutputStream()
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:mirror-client') {
base {
archivesName = "connect-mirror-client"
}
dependencies {
implementation project(':clients')
implementation libs.slf4jApi
testImplementation testLog4j2Libs
testImplementation libs.junitJupiter
testImplementation testFixtures(project(':clients'))
testRuntimeOnly runtimeTestLibs
}
javadoc {
enabled = true
}
tasks.register('copyDependantLibs', Copy) {
from (configurations.runtimeClasspath) {
exclude('kafka-clients*')
exclude('connect-*')
}
into "${layout.buildDirectory.get().asFile.path}/dependant-libs"
duplicatesStrategy = 'exclude'
}
jar {
dependsOn copyDependantLibs
}
}
project(':connect:test-plugins') {
base {
archivesName = "connect-test-plugins"
}
dependencies {
api project(':connect:api')
implementation project(':server-common')
implementation libs.slf4jApi
implementation libs.jacksonDatabind
testImplementation testLog4j2Libs
}
}
// Gradle 9+ forbids resolving a subproject's Configuration from the root.
// Consume each subproject's javadocClasspathElements via project dependencies instead.
configurations {
aggregatedJavadocClasspath {
canBeConsumed = false
canBeResolved = true
}
}
tasks.register('aggregatedJavadoc', Javadoc) {
destinationDir = file("${layout.buildDirectory.get().asFile.path}/docs/javadoc")
}
gradle.projectsEvaluated {
// Validate that no module depends on test output directly
def protectedModules = [
'clients': ':clients',
'server-common': ':server-common',
'server': ':server',
'storage/api': ':storage:storage-api',
'coordinator-common': ':coordinator-common',
'storage': ':storage',
'group-coordinator': ':group-coordinator',
'share-coordinator': ':share-coordinator',
'metadata': ':metadata',
'raft': ':raft',
'connect/runtime': ':connect:runtime',
'core': ':core',
'streams': ':streams',
'streams/integration-tests': ':streams:integration-tests',
]
allprojects { proj ->
proj.configurations.all { config ->
config.dependencies.each { dep ->
if (dep instanceof FileCollectionDependency) {
dep.files.files.each { file ->
protectedModules.each { dir, projectPath ->
if (file.absolutePath.endsWith("/${dir}/build/classes/java/test")) {
throw new GradleException("""
ERROR: Dependency on ${projectPath} test output is not allowed.
Found in project ${proj.path} configuration '${config.name}'.
Use `testFixtures(project('${projectPath}'))` instead of `project('${projectPath}').sourceSets.test.output`
""")
}
}
}
}
}
}
}
def projectsWithJavadoc = subprojects.findAll { it.javadoc.enabled }
projectsWithJavadoc.each { sp ->
dependencies.add('aggregatedJavadocClasspath',
dependencies.project(path: sp.path, configuration: 'javadocClasspathElements'))
}
tasks.named('aggregatedJavadoc').configure {
dependsOn projectsWithJavadoc.collect { "${it.path}:compileJava" }
source projectsWithJavadoc.collect { it.sourceSets.main.allJava }
classpath = configurations.aggregatedJavadocClasspath
includes = projectsWithJavadoc.collectMany { it.javadoc.getIncludes() }
excludes = projectsWithJavadoc.collectMany { it.javadoc.getExcludes() }
}
}
// Helper to get version targets and expected patterns
ext.getVersionTargets = { rawVersion ->
// Python Package Version (PEP 440): 4.3.0.dev0
def pythonVersion = rawVersion.contains("SNAPSHOT") ?
rawVersion.replace("-SNAPSHOT", ".dev0") :
rawVersion
def baseVersion = rawVersion.replace("-SNAPSHOT", "")
return [
// 1. kafka-merge-pr.py
[
path: "committer-tools/kafka-merge-pr.py",
// Regex: match DEFAULT_FIX_VERSION = os.environ.get("DEFAULT_FIX_VERSION", "...")
pattern: /DEFAULT_FIX_VERSION\s*=\s*os\.environ\.get\("DEFAULT_FIX_VERSION",\s*".*?"\)/,
replace: "DEFAULT_FIX_VERSION = os.environ.get(\"DEFAULT_FIX_VERSION\", \"${baseVersion}\")"
],
// 2. version.py
[
path: "tests/kafkatest/version.py",
pattern: /DEV_VERSION\s*=\s*KafkaVersion\(".*"\)/,
replace: "DEV_VERSION = KafkaVersion(\"${rawVersion}\")"
],
// 3. __init__.py
[
path: "tests/kafkatest/__init__.py",
pattern: /__version__\s*=\s*'.*'/,
replace: "__version__ = '${pythonVersion}'"
],
// 4. Maven POMs
[
path: "streams/quickstart/pom.xml",
pattern: /(?s)(<artifactId>streams-quickstart<\/artifactId>.*?<version>)([^<]+)(<\/version>)/,
replace: { "\$1${rawVersion}\$3" }
],
[
path: "streams/quickstart/java/pom.xml",
pattern: /(?s)(<artifactId>streams-quickstart<\/artifactId>.*?<version>)([^<]+)(<\/version>)/,
replace: { "\$1${rawVersion}\$3" }
],
[
path: "streams/quickstart/java/src/main/resources/archetype-resources/pom.xml",
pattern: /(<kafka\.version>)([^<]+)(<\/kafka\.version>)/,
replace: { "\$1${rawVersion}\$3" }
]
]
}
def updateVersionTask = tasks.register('updateVersion') {
group = "Release"
description = "Syncs python, pom, and script versions with gradle.properties. Fails if files or patterns are missing. Use -PnewVersion=X.Y.Z to set a new version."
doLast {
def rawVersion
if (project.hasProperty('newVersion')) {
rawVersion = newVersion
if (!rawVersion.matches(/^[0-9]+\.[0-9]+\.[0-9]+(-SNAPSHOT)?$/)) {
throw new GradleException("Invalid version format: '${rawVersion}'. Expected format: X.Y.Z or X.Y.Z-SNAPSHOT")
}
// Update gradle.properties
def gradlePropsFile = file("${project.rootDir}/gradle.properties")
if (gradlePropsFile.exists()) {
def propsContent = gradlePropsFile.text
def newPropsContent = propsContent.replaceAll(/(?m)^version\s*=.*/, "version=${rawVersion}")
if (propsContent != newPropsContent) {
gradlePropsFile.text = newPropsContent
println "Updated gradle.properties to version ${rawVersion}"
}
}
} else {
rawVersion = project.version.toString()
}
def targets = getVersionTargets(rawVersion)
targets.each { item ->
def f = file("${project.rootDir}/${item.path}")
// Check 1: file must exist
if (!f.exists()) {
throw new GradleException("File not found: ${item.path}")
}
def content = f.text
// Check 2: regex must match
def matcher = (content =~ item.pattern)
if (!matcher.find()) {
throw new GradleException("Pattern not found in ${item.path}.\nExpected pattern: ${item.pattern}")
}
def replacementStr = item.replace instanceof Closure ? item.replace.call() : item.replace
def newContent = content.replaceAll(item.pattern, replacementStr)
if (content != newContent) {
f.text = newContent
println "Updated ${item.path}"
}
}
}
}
def verifyVersionConsistencyTask = tasks.register('verifyVersionConsistency') {
group = "Verification"
description = "Verifies that python, pom, and script versions match gradle.properties."
doLast {
def rawVersion = project.version.toString()
def targets = getVersionTargets(rawVersion)
def inconsistentFiles = []
targets.each { item ->
def f = file("${project.rootDir}/${item.path}")
if (!f.exists()) {
throw new GradleException("File not found: ${item.path}")
}
def content = f.text
// Check if regex matches current content "as is"
// Note: We need to see if the file content *already* matches what we want it to be.
// One way is to simulate the replacement and see if it changes nothing.
def replacementStr = item.replace instanceof Closure ? item.replace.call() : item.replace
def newContent = content.replaceAll(item.pattern, replacementStr)
if (content != newContent) {
inconsistentFiles.add(item.path)
}
}
if (!inconsistentFiles.isEmpty()) {
throw new GradleException("Found inconsistent versions in the following files:\n" +
inconsistentFiles.join("\n") +
"\n\nPlease run './gradlew updateVersion -PnewVersion=...' to fix them.")
}
println "All versions are consistent."
}
}
check.dependsOn verifyVersionConsistencyTask
def verifyLatestStableMetadataVersionTask = tasks.register('verifyLatestStableMetadataVersion') {
group = "Verification"
description = "Verifies that LATEST_STABLE_METADATA_VERSION in version.py matches LATEST_PRODUCTION in MetadataVersion.java"
doLast {
// Extract enum constant name that LATEST_PRODUCTION points to, e.g. LATEST_PRODUCTION = IBP_4_3_IV0 -> IBP_4_3_IV0
def mvContent = file("${project.rootDir}/server-common/src/main/java/org/apache/kafka/server/common/MetadataVersion.java").text
def pyContent = file("${project.rootDir}/tests/kafkatest/version.py").text
def latestProductionEnumName = mvContent =~ /LATEST_PRODUCTION\s*=\s*(IBP_\w+)/
if (!latestProductionEnumName) throw new GradleException("Could not find LATEST_PRODUCTION in MetadataVersion.java")
def latestProductionEnumConstant = latestProductionEnumName[0][1] // e.g. "IBP_4_3_IV0"
// Extract version from enum constant, e.g. IBP_4_3_IV0(30, "4.3", "IV0", true) -> 4.3-IV0
def enumMatch = mvContent =~ /${latestProductionEnumConstant}\(\d+,\s*"(\d+\.\d+)",\s*"(IV\d+)"/
if (!enumMatch) throw new GradleException("Could not find enum definition for ${latestProductionEnumConstant} in MetadataVersion.java")
def javaVersion = "${enumMatch[0][1]}-${enumMatch[0][2]}" // e.g. "4.3-IV0"
def pyMatch = pyContent =~ /LATEST_STABLE_METADATA_VERSION\s*=\s*"([^"]+)"/
if (!pyMatch) throw new GradleException("LATEST_STABLE_METADATA_VERSION not found in version.py")
def pyVersion = pyMatch[0][1] // e.g. "4.3-IV0"
if (javaVersion != pyVersion) {
throw new GradleException(
"LATEST_STABLE_METADATA_VERSION mismatch: MetadataVersion.java LATEST_PRODUCTION=${javaVersion}, " +
"tests/kafkatest/version.py LATEST_STABLE_METADATA_VERSION=${pyVersion}. " +
"Make sure LATEST_PRODUCTION in MetadataVersion.java and LATEST_STABLE_METADATA_VERSION in tests/kafkatest/version.py are in sync."
)
}
println "MetadataVersion.java LATEST_PRODUCTION=${latestProductionEnumConstant} (${javaVersion}) matches version.py LATEST_STABLE_METADATA_VERSION=${pyVersion}"
}
}
check.dependsOn verifyLatestStableMetadataVersionTask