Skip to content

Parse native Java Dags and show their source - #74036

Merged
jason810496 merged 30 commits into
mainfrom
jason/lang-sdk-e2e/04-java-dag-importer
Oct 6, 2026
Merged

jason810496 merged 30 commits into
mainfrom
jason/lang-sdk-e2e/04-java-dag-importer

Conversation

@jason810496

@jason810496 jason810496 commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Stack (bottom to top): #74042, #74035, #74043, #74036, #74037, #73845, #73846, #73847

Why

With this PR, JavaCoordinator parses the native Dags a bundle JAR declares and runs their tasks from that JAR, and the Code view shows their Java source.

What changes

  • Which JARs. Once a JavaCoordinator is configured, each .jar whose manifest sets Main-Class (matching main_class if set) is parsed in every Dag bundle. An unreadable JAR is kept so its parse reports the error.
  • Parse command. The task command, java -classpath <bundle JARs> <jvm_args> <Main-Class>, with the same schema version lookup. A JAR it cannot run gets an import error.
  • Native tasks. A native Dag's task runs the JAR its Dag was parsed from, at the run's bundle version, on the JavaCoordinator its queue routes to. task_handler_bundle_name does not apply.
  • Launch failures. A coordinator's execute_task raises the new TaskLaunchError when a native Dag's JAR cannot run, and the supervisor fails the task with the reason in its task log. A routing mistake, such as a queue routed to another kind of coordinator, fails without retries.
  • Manifest reader. Tasks and parses now read manifests per the JAR specification (CR, LF or CRLF, folded lines, main section only). The old email parser broke a folded Main-Class.
  • Dag source. get_source_code reads the sources.json index the Gradle plugin packs (Java SDK: Pack each native Dag's source file into the bundle JAR #74096), named by the Airflow-Java-SDK-Sources manifest attribute, and returns the entrypoint (Main-Class) source, up to 1 MiB per file, or a placeholder. The index also maps each Java Dag to its own file for a per-Dag lookup.

The Java runtime is unchanged here. The Java SDK layer above makes it answer the parse request, with a payload that passes validate_serialized_dag.

[sdk]
coordinators = {
  "java-native": {
    "classpath": "airflow.sdk.coordinators.java.JavaCoordinator",
    "kwargs": {"java_executable": "/usr/lib/jvm/java-17-openjdk/bin/java"}
  }
}
queue_to_coordinator = {"java-native": "java-native"}

Deviations and limitations


Was generative AI tooling used to co-author this PR?

@jason810496
jason810496 added this pull request to stack #74038 October 1, 2026 13:38
@jason810496
jason810496 removed this pull request from stack #74038 October 1, 2026 15:13
@jason810496
jason810496 changed the base branch from jason/lang-sdk-e2e/03-native-dag-parse to jason/lang-sdk-e2e/03e-lang-sdk-dag-bag October 1, 2026 15:16
@jason810496
jason810496 force-pushed the jason/lang-sdk-e2e/04-java-dag-importer branch from 8ffd19e to fce2457 Compare October 1, 2026 15:16
@jason810496
jason810496 added this pull request to stack #74044 October 1, 2026 15:18
Comment thread task-sdk/src/airflow/sdk/coordinators/java/coordinator.py Outdated
Comment thread task-sdk/src/airflow/sdk/coordinators/java/coordinator.py Outdated
Comment thread airflow-core/docs/authoring-and-scheduling/language-sdks/java.rst Outdated
Comment thread airflow-core/docs/authoring-and-scheduling/language-sdks/java.rst
Comment thread task-sdk/src/airflow/sdk/coordinators/java/coordinator.py Outdated
Comment thread task-sdk/tests/task_sdk/coordinators/java/test_coordinator.py Outdated
@jason810496
jason810496 force-pushed the jason/lang-sdk-e2e/04-java-dag-importer branch from fce2457 to 5a8f7c4 Compare October 2, 2026 00:54
@jason810496
jason810496 force-pushed the jason/lang-sdk-e2e/04-java-dag-importer branch 2 times, most recently from 47500af to b045547 Compare October 2, 2026 05:44
@pierrejeambrun
pierrejeambrun force-pushed the jason/lang-sdk-e2e/04-java-dag-importer branch from b045547 to 81f9527 Compare October 2, 2026 09:00
@jason810496
jason810496 force-pushed the jason/lang-sdk-e2e/04-java-dag-importer branch from 81f9527 to 51198c6 Compare October 2, 2026 11:41
@jason810496
jason810496 force-pushed the jason/lang-sdk-e2e/04-java-dag-importer branch from 51198c6 to b3a04e2 Compare October 2, 2026 14:07
JavaDagImporter now names its coordinator class and is registered in a
Dag bundle when [sdk] coordinators has a JavaCoordinator, instead of
being handed out by each coordinator. The importer asks the coordinator
that parses its bundle for main_class, and keeps a JAR when there is
none, so that parsing the JAR reports why.
A coordinator can raise TaskLaunchError from execute_task before it
starts the runtime. The supervisor then starts the task instance, writes
the reason to the task log, and puts the task up for retry or fails it,
instead of letting the error escape without a state or a log. An error
that is not retryable fails the task even when retries are left.
A task whose Dag file a coordinator Dag importer claims runs that file,
at the version of the run, on a coordinator of the importer's class. It
no longer scans the bundle for a JAR, so it cannot run another JAR, and
a coordinator that cannot run it raises TaskLaunchError before the
runtime starts. A task routed to a coordinator of another class, or in a
bundle whose importers cannot be built, fails without retries.

JavaCoordinator builds the command for a Dag JAR and for parsing it
with one method, so both reject a JAR whose Main-Class another JAR sets.
Stub tasks keep the scan and the bundle rules they have on main, so the
Dag file plumbing of _build_execute_task_command is removed.
…load

An unreadable Dag file and an importer whose coordinator class cannot be
imported now raise TaskLaunchError, so the supervisor fails the task with
the reason instead of leaking a raw OSError or ImportError.
airflow tasks list parses a native Java Dag, so it is not among the
commands that refuse one. Also break the new Java SDK text only at
sentence or clause ends.
The Dag processor and the CLI only run the JAR, so they need a JRE, as
the prerequisites already say. The artifact bundle tests go back to
main's MagicMock(spec=BundleInfo), which they no longer needed to drop.
Comment thread task-sdk/src/airflow/sdk/coordinators/java/coordinator.py Outdated
Comment thread task-sdk/src/airflow/sdk/coordinators/java/_dag_importer.py Outdated
Comment thread task-sdk/src/airflow/sdk/coordinators/java/coordinator.py
Comment thread airflow-core/docs/authoring-and-scheduling/language-sdks/java.rst Outdated
Comment thread task-sdk/tests/task_sdk/coordinators/test_subprocess.py Outdated
Comment thread task-sdk/tests/task_sdk/coordinators/test_subprocess.py Outdated
Comment thread task-sdk/tests/task_sdk/execution_time/test_supervisor.py Outdated
Comment thread airflow-core/docs/authoring-and-scheduling/language-sdks/java.rst
Two JARs that both shade the SDK classes must load the one `_build_jar_command` runs, not whichever
sorts first alphabetically.
…dZipFile

A corrupt deflate stream or an unsupported compression method on META-INF/MANIFEST.MF escaped both
`might_contain_dag` and `_JarMetadata.from_jar`. `might_contain_dag` now keeps the JAR for any
exception, like `ZipImporter` does; `from_jar` also catches `zlib.error` and `NotImplementedError`,
while still letting `PermissionError` propagate.
`_JarInfo.find` kept overwriting `progress.main_class` on every matching JAR until one also carried
the schema version, so a schema-only JAR appearing later could make a later Main-Class win.
`queue_coordinator` was a local instance the manager never builds, so comparing it by identity could
not fail. Patching `get_parsing_coordinator` and asserting it is never called pins what the test
promises.
Bare MagicMocks and unspecced patches let a typo'd bundle attribute or a renamed start() keyword pass
silently, unlike TestExecuteTaskBundleWiring just above.
A bare * only hides everything safely when the JAR has its own bundle, and it is not valid regexp
syntax, so dag_ignore_file_syntax = regexp silently drops it and still parses the JAR.
@jason810496
jason810496 requested review from kaxil and phanikumv October 6, 2026 14:52
@jason810496

jason810496 commented Oct 6, 2026 •

Copy link
Copy Markdown
Member Author

Thanks for the review, I addressed them all in the latest commits.

Update: I will merge this with #74037 as soon as the CI pass there, so that we won't waste another CI run.

@jason810496
jason810496 merged commit 5aa12d3 into main Oct 6, 2026
108 checks passed
@jason810496
jason810496 deleted the jason/lang-sdk-e2e/04-java-dag-importer branch October 6, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants