Airflow Java SDK 贡献者指南(AIP-108)。Java SDK 让 Airflow 任务能够执行 JVM 代码(Java、Kotlin 或任意 JVM 语言)。该技能帮助贡献者在以下两个位置之一或同时工作:java-sdk/,即 JVM 侧库(Kotlin 源码,发布到 Maven);task-sdk/src/airflow/sdk/coordinators/java/,即启动 JVM 子进程的 Python 协调器。
每次会话应尽早阅读两份文档,它们包含权威参考资料:airflow-core/docs/authoring-and-scheduling/language-sdks/java.rst,面向用户的指南,涵盖注解式与接口式 API、XCom 类型映射、Gradle/Maven 步骤、协调器配置;java-sdk/README.md,贡献者指南,涵盖仓库布局、详细执行流程、Gradle + Breeze 测试命令、编码约定、常见任务和 PR 检查清单。
SDK 包架构:JVM 侧库分为两个具有不同可见性规则的包。org.apache.airflow.sdk 是公开的、面向用户的 API,其中的类(如 Client、Bundle、BundleBuilder、Server)是稳定契约,DAG 作者和任务实现者直接导入,对该包的更改属于破坏性更改。org.apache.airflow.sdk.execution 是内部实现细节,该包中的所有内容(CoordinatorComm、LogSender、Log、execution/ 中的 Client、生成的 schema 模型等)都不打算被用户导入,可能在版本之间无通知地变化。在审查或编写代码时应强制这一边界:用户任务代码和 BundleBuilder 子类只能从 org.apache.airflow.sdk 导入;面向用户 API 表面中出现任何 org.apache.airflow.sdk.execution.* 的导入都是危险信号。
Bundle 组成与协调器发现:bundle 是放置在协调器 jars_root 上的 JAR 文件目录(通常为 build/bundle/)。协调器在任务分发时扫描该目录以查找:Main-Class(标准 JAR manifest 属性),即协调器以 java -classpath … <Main-Class> --comm … --logs … 调用的入口点的全限定类名,该类必须具有 public static void main(String[] args) 方法,Gradle 插件 org.apache.airflow.sdk 会根据 airflowBundle { mainClass = "…" } 自动写入,并在构建时验证该类存在且签名正确;Airflow-Supervisor-Schema-Version(Airflow 专用 manifest 属性),即 JVM 侧与 Python supervisor 通信时预期的线协议版本,在 fat-JAR 模式(默认)下,Gradle 插件从 runtimeClasspath 中的 airflow-sdk JAR 读取该值并复制到 shadow JAR manifest,在 thin-JAR 模式(fatJar = false)下,该值保留在与 bundle JAR 一起部署的 airflow-sdk JAR 中。Python 协调器(JavaCoordinator)使用 _JarInfo.find() 扫描 jars_root 下的每个 JAR,从每个 ZIP 中读取 META-INF/MANIFEST.MF,并从携带它们的 JAR 中收集 Main-Class 和 Airflow-Supervisor-Schema-Version。解析出的 schema 版本随后作为 _build_execute_task_command 的 schema_version 返回值传递,基类 SubprocessCoordinator 用它协商 supervisor 线协议。如果在 JavaCoordinator 实例上显式设置了 main_class(通过 [sdk] coordinators kwargs),扫描会将其用作过滤器;否则第一个带 Main-Class 属性的 JAR 胜出。无论哪种方式,jars_root 中至少一个 JAR 必须存在 Airflow-Supervisor-Schema-Version,否则启动失败。
关键文件:java-sdk/sdk/.../Client.kt 为公开 API(Variables、Connections、XCom);java-sdk/sdk/.../execution/Client.kt 为 Supervisor 线调用;java-sdk/sdk/.../execution/Comm.kt 为 4 字节前缀 MessagePack 分帧;java-sdk/sdk/.../Server.kt 为入口点,驱动执行循环;java-sdk/processor/.../BuilderProcessor.kt 为 Kapt 注解处理器;java-sdk/plugin/.../AirflowSdkPlugin.kt 为 Gradle bundle 插件;task-sdk/.../coordinators/java/coordinator.py 为 Python 侧,启动 JVM;task-sdk/.../schema/schema.json 为线协议定义(两侧共用)。
运行测试:始终在 java-sdk/ 内使用 ./gradlew,切勿通过 apt 的 gradle 运行 Gradle。完整 Gradle 命令列表见 java-sdk/README.md#testing。对于 Python 协调器,使用 Breeze(切勿在宿主机上直接运行 pytest):breeze testing task-sdk-tests -- task_sdk/coordinators/java。端到端测试套件:E2E_TEST_MODE=java_sdk uv run --project airflow-e2e-tests pytest tests/airflow_e2e_tests/java_sdk_tests/ -xvs。
更新 Python 协调器:coordinator.py 继承 SubprocessCoordinator。子类必须实现的唯一方法是 _build_execute_task_command,它返回 (argv, schema_version)。可参考现有实现了解 jars_root、java_executable、jvm_args 和 main_class 如何组装成命令。不要从 Python 越过该方法提供的能力去触及 JVM 进程。
升级 Supervisor Schema 客户端:升级到更新的 Supervisor Schema 版本时,使用 ./gradlew generateJsonSchema2Pojo 重新生成模型;修改 execution/Client.kt 以处理变更;java-sdk/README.md#contributing 部分逐步介绍了完整的“添加新 Client 方法”流程。