jason810496 opened a new pull request, #71188:
URL: https://github.com/apache/airflow/pull/71188
related: AIP-108
depends on: #69757, #71057
## Why
For a stub-backed Dag, the Python file's `@task.stub` call site is the graph
the scheduler actually orders the run by — so it should also be what feeds each
Java task its inputs. Until now the Java side re-declared that data flow
itself, with `@Builder.XCom(task = "extract")` naming the upstream to pull.
That is the same wiring written twice, in two languages, with nothing keeping
the copies honest: rename or re-wire a task in the Dag file and the Java
annotation keeps pulling the old upstream, silently. It also cannot express a
literal written at the call site at all.
The 2026-10-30 supervisor schema delivers the call site's argument bindings
with every task run, so the Java runtime can read the real wiring instead of
restating a guess at it.
## How
- Binding is **positional**: a task method's data parameters — everything
other than the injected `Client` and `Context` — resolve the binding at their
index, in declaration order. This matches the Go SDK's flat-parameter contract,
and it is deliberate: Java parameter names are not API, so an IDE rename must
never rebind an input.
- Keyword-style calls bind **by name** only through an explicit `TaskInput`
bundle parameter, whose public fields declare their wire names
(`@ArgName("region_code")`, or the verbatim field name). That is the one tagged
place where the stub's `snake_case` argument names cross into `camelCase` Java
fields, rather than an implicit convention applied everywhere.
- A task declares flat data parameters **or** one bundle, never both, and
never two bundles — otherwise field names and flat positions could shift each
other. Both cases fail at compile time.
- A primitive parameter cannot hold `null`, so it fails with
`MissingXComException` when its binding resolves to nothing; boxed and
reference types receive `null`. Declaring more data parameters than the call
site bound fails the task rather than running it with missing inputs.
- Interface-API tasks get the same information imperatively, through
`Client.hasArgs` / `hasArg` / `getArg`, by position or by name.
- `@Builder.XCom` is removed outright rather than deprecated — the SDK is
pre-1.0, and leaving a second, diverging way to declare the same data flow is
the problem this change fixes.
- jsonSchema2Pojo cannot express the `kind`-discriminated binding union, so
the generated `TIRunContext` carries the raw payload and a small hand-written
decoder materializes the typed view.
## What
- Bump the pinned supervisor schema to `2026-10-30` and refresh the schema
snapshot, which adds `TIRunContext.arg_bindings`.
- Add `ArgBinding` + `decodeArgBindings`, `TaskInput`, `@ArgName`,
`internal.ArgValues`, and `Client.hasArgs` / `hasArg` / `getArg`.
- `BuilderProcessor` classifies each `@Builder.Task` parameter as `Client`,
`Context`, a `TaskInput` bundle, or a flat data parameter, and emits the
matching `ArgValues` resolution; `@Builder.XCom` and its codegen are gone.
- Migrate the Java examples and their Python stub Dag to TaskFlow-style
calls, including a `TaskInput` bundle bound from keyword arguments, and
document argument binding in the Java SDK docs.
---
##### Was generative AI tooling used to co-author this PR?
- [x] Yes, with help of Claude Code Opus 5 following [the
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]