Files
airflow/java-sdk
PoAn Yang 2ab01dae67 Java SDK: Read the Dag run conf into a class with typed fields (#75542)
* Java SDK: Read the Dag run conf into a class with typed fields

Signed-off-by: PoAn Yang <payang@apache.org>

* Document the clashing field names case of getConf

Signed-off-by: PoAn Yang <payang@apache.org>

* Reject nulls for primitives in getConf and document JsonProperty

Signed-off-by: PoAn Yang <payang@apache.org>

* Move getConf details from the Java SDK guide to the API reference

Signed-off-by: PoAn Yang <payang@apache.org>

---------

Signed-off-by: PoAn Yang <payang@apache.org>
2026-11-04 11:31:49 +08:00
..

Airflow Java SDK

Write Apache Airflow Dags and tasks in Java, Kotlin, Scala or any other JVM language.

Status: Beta · Java 11+

Installation

Apply the Gradle plugin, and add the SDK and its annotation processor:

plugins {
    id("org.apache.airflow.sdk") version "<version>"
}

dependencies {
    annotationProcessor("org.apache.airflow:airflow-sdk-processor:<version>")
    implementation("org.apache.airflow:airflow-sdk:<version>")
}

airflowBundle {
    mainClass = "com.mycompany.airflow.hello.Main"
}

Replace <version> with a release from Maven Central. See the guide for Maven.

Quick start

Declare a Dag:

package com.mycompany.airflow.hello;

import org.apache.airflow.sdk.*;

@Airflow.Dag(id = "java_hello", schedule = "@daily", queue = "java")
public class HelloDag {

  @Airflow.Task
  public long extract() {
    return 42L;
  }

  @Airflow.Task
  public void report(long rows) {
    System.out.println("extracted " + rows + " rows");
  }

  @Airflow.Deps
  static class Wiring implements HelloDagDeps {
    void depends() {
      report(extract());
    }
  }
}

Serve it from the main class:

package com.mycompany.airflow.hello;

import org.apache.airflow.sdk.Bundle;
import org.apache.airflow.sdk.Server;

public class Main {
  public static void main(String[] args) {
    Server.create(args).serve(new Bundle().register(HelloDag.class));
  }
}

Build the bundle into build/bundle/:

./gradlew bundle

Copy build/bundle/ into a Dag bundle, such as the default dags-folder bundle, and send the java queue to the Java coordinator in airflow.cfg:

[sdk]
coordinators = {"java": {"classpath": "airflow.sdk.coordinators.java.JavaCoordinator"}}
queue_to_coordinator = {"java": "java"}

Airflow reads the bundle like any other Dag file: java_hello shows up in the UI, runs on its schedule, and report receives the value extract returned.

Learn more

The Java SDK guide covers:

Topic Guide section
Task inputs, options, order-only dependencies, task groups, branching, triggering another Dag Declaring a Dag in Java
@Airflow.TaskHandler for the @task.stub tasks of a Python Dag, and how arguments bind Implementing stub tasks of a Python Dag
Client, Context, and what a task returns Writing tasks
Building a bundle with Gradle or Maven Building a bundle
Where to deploy a bundle, and the JavaCoordinator options Deploying
What a Dag declared in Java cannot do yet Limitations

See example/ for a working project.

Compatibility matrix

Which Airflow TaskInstance states and capabilities this SDK supports. This table is generated from capabilities.yaml; the conformance dimensions are defined in the Language SDK conformance spec. Do not edit the table by hand — edit capabilities.yaml and let the update-java-sdk-readme-matrix prek hook regenerate it.

Min. Airflow version: 3.4.0 · supervisor schema: 2026-10-30

Dimension Tier Supported Since (Airflow) Since (SDK) Notes
TaskInstance states
state: success MUST ✓ 3.4.0 1.0.0
state: failed MUST ✓ 3.4.0 1.0.0
state: up_for_retry MUST ✓ 3.4.0 1.0.0 RetryTask
state: skipped SHOULD ✓ 3.4.0 1.0.0 a TriggerDagRun task that skips an existing run
state: deferred MAY ✓ 3.4.0 1.0.0 a TriggerDagRun task that waits with deferrable
state: up_for_reschedule MAY ✗ – – runtime does not emit RescheduleTask yet
state: awaiting_input MAY ✗ – – runtime does not emit AwaitInputTask yet
state: removed MAY ✓ 3.4.0 1.0.0
Task runtime
capability: task-logging MUST ✓ 3.4.0 1.0.0 SLF4J + JPL bridged to the task log
capability: xcom-read-write MUST ✓ 3.4.0 1.0.0
capability: connection-read MUST ✓ 3.4.0 1.0.0
capability: variable-read-write MUST ✓ 3.4.0 1.0.0
capability: self-contained-bundle MUST ✓ 3.4.0 1.0.0 Airflow metadata embedded in the jar artifact
capability: retry-policy MAY ✗ – – no task-facing retry-policy API yet
capability: task-state-store MAY ✓ 3.4.0 1.0.0 Client.getTaskStateStore() get/set/delete/clear
capability: asset-state-store MAY ✗ – – no task-facing asset state-store API yet
capability: asset-event-emit MAY ✗ – – runtime does not emit asset events yet
capability: asset-event-read MAY ✗ – – no task-facing asset-event API yet
capability: object-store MAY ✗ – – no object-storage API yet
capability: listeners MAY ✗ – – no hook into the Python listener API, so a task emits no OpenLineage facets of its own
Dag definition
capability: dag-definition-authoring SHOULD ✓ 3.4.0 1.0.0
capability: dag-args MUST † ✓ 3.4.0 1.0.0
capability: task-args MUST † ✓ 3.4.0 1.0.0
capability: dag-params MUST † ✗ – –
capability: dag-callbacks MAY † ✗ – –
capability: explicit-dependencies MUST † ✓ 3.4.0 1.0.0 before / after, or @Airflow.Deps
capability: edge-labels MAY † ✓ 3.4.0 1.0.0 Label.of(text).on(task)
capability: taskflow-dependencies MUST † ✓ 3.4.0 1.0.0
capability: task-group MAY † ✓ 3.4.0 1.0.0
capability: task-loops MAY † ✗ – –
capability: if-else-branching SHOULD † ✓ 3.4.0 1.0.0 DagDef.If or @Airflow.If
capability: switch-case-branching SHOULD † ✓ 3.4.0 1.0.0 DagDef.Switch or @Airflow.Switch
capability: trigger-dag-run MAY † ✓ 3.4.0 1.0.0 TriggerDagRun
capability: dynamic-dag-generation MAY † ✓ 3.4.0 1.0.0
capability: human-in-the-loop MAY † ✗ – –
capability: dag-test SHOULD † ✗ – –
capability: asset-definition MAY † ✗ – –
capability: asset-scheduling MAY † ✗ – –
capability: mapped-tasks MAY † ✗ – –
capability: asset-inlets-outlets MAY † ✗ – –
capability: task-callbacks MAY † ✗ – – no SDK-defined task callbacks
Python Dag with stub TaskHandler
capability: mixed-lang-stub-target MUST ✓ 3.4.0 1.0.0 @task.stub
capability: taskflow-binding MUST ✓ 3.4.0 1.0.0 mapped stubs excluded
capability: mapped-tasks MAY ✗ – – Airflow does not bind arguments to mapped stubs yet
capability: asset-inlets-outlets MAY ✗ – – runtime does not report task outlets yet
capability: task-callbacks MAY ✗ – – a Python-declared task callback does not run for a stub task

Marks: ✓ supported · ✗ not supported · n/a not applicable. A tier marked † applies only when dag-definition-authoring is supported.