Skip to content

Add Java SDK interface-design ADRs for mixed-lang and native Dags - #72019

Merged
jason810496 merged 8 commits into
apache:mainfrom
jason810496:docs/java-sdk/adr-interface-design
Sep 16, 2026
Merged

jason810496 merged 8 commits into
apache:mainfrom
jason810496:docs/java-sdk/adr-interface-design

Conversation

@jason810496

@jason810496 jason810496 commented Aug 24, 2026 •

Copy link
Copy Markdown
Member

Write the design for TaskFlow and native Dag for the Java-SDK up front, to settle the design early and surface as much context as possible for reviewers on the actual implementation PRs.


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

@jason810496
jason810496 requested a review from uranusjr as a code owner August 24, 2026 07:45
@jason810496 jason810496 self-assigned this Aug 24, 2026
@jason810496 jason810496 added this to the Java SDK 1.0 GA milestone Aug 24, 2026
Comment thread java-sdk/adr/0001-mixed-lang-dag-interface.md Outdated
@jason810496 jason810496 added the type:doc-only Changelog: Doc Only label Aug 25, 2026
@jason810496
jason810496 marked this pull request as draft September 7, 2026 02:14
Review on apache#72019 asked for TaskArgs to leave the public surface, and
following that through reshaped more than one interface. Positional,
untyped access is right for code a processor emits and wrong for code a
person writes and later reads, so an interface task now binds through a
TaskInput, and TaskArgs is reached only from generated code.

The native Dag interface changed for a different reason. Its wiring
expression composed a generated twin rather than the task methods
themselves, so a Dag author read one set of signatures and ran another.
Making Client and Context getters removes that mismatch at the source:
the methods the wiring composes are the methods that run, and javac
checks them against each other with nothing generated in between.

An annotation also no longer calls a mixed-language body a task. Python
declares that task and Java supplies only its body, which is what
@builder.StubHandler names.

@jason810496 jason810496 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The primary change (also sync the term with the overall one -- #72765 ).

  • mixed lang task: StubHandler
  • rename the BundleBuilder to just Bundle
  • native Dag: I keep the getter functions to match the type shape for now, please feel free to take over this to the generated class approach that you mentioned earier.

@jason810496
jason810496 marked this pull request as ready for review September 9, 2026 08:20
jason810496 and others added 3 commits September 9, 2026 08:38
The name should say what the SDK registers, and what it registers is a
task: Python declares it with @task.stub, gives it a task_id, and the SDK
supplies only its body. "Handler" described the callable rather than the
thing it stands for, leaving these docs using a word no other part of
Airflow uses for a task.
Python declares the task; an SDK supplies only its body. Naming the SDK
object after the task overloads a word the native surface already uses for
something the user creates with dag.Task, so it names the role the SDK
actually plays instead.
The native Java Dag interface previously took Client and Context from getters
on a Tasks base class. Switch to injecting them as method arguments, matching
the mixed-language surface, so one injection rule spans the SDK, no ambient
getter exists, and the Dag class keeps its single inheritance slot free.

ADR-0001 (mixed-lang):
- Flatten the @Builder.TaskHandler parameters from dagId/taskId to
  dag/task, and note client/context are injected as arguments,
  consistent with the native surface.

ADR-0002 (native):
- Wiring moves to a nested @Builder.Deps class implementing a generated
  <Dag>Deps wiring-view interface: injected args stripped, data args as
  Arg<T>, returns as TaskRef<T>.
- depends() is executed once in recording mode rather than read as a
  syntax tree, so it needs no com.sun.source.util.Trees and works under
  any compiler; a TaskRef carries node identity, so a result reused in a
  local just works.
- Ordering-only ("non-TaskFlow") edges use then/after on Chain plus
  Flow.of; literal data args use lit(...). The chain/fanOut/fanIn
  shorthands are dropped as redundant with the two verbs.
- Getters, syntax-tree reading, and subclass capture are recorded under
  Alternatives with their rejection rationale. The interface-based
  surface and the Bundle/register/Server flow are kept.

@jason810496 jason810496 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. The interface of the new TaskFlow wiring LGTM.

Comment thread java-sdk/adr/0002-native-dag-interface.md
Comment thread java-sdk/adr/0002-native-dag-interface.md
Comment thread java-sdk/adr/0002-native-dag-interface.md

@jason810496 jason810496 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks, but I can't self approve.

@uranusjr uranusjr left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to merge!

@jason810496
jason810496 merged commit 1efcf23 into apache:main Sep 16, 2026
67 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants