Skip to content

[Flink] Fix Flink SQL job submission failures on the client path - #4496

Open
88fantasy wants to merge 1 commit into
apache:devfrom
88fantasy:fix/flink-sql-remote-submit-path
Open

[Flink] Fix Flink SQL job submission failures on the client path#4496
88fantasy wants to merge 1 commit into
apache:devfrom
88fantasy:fix/flink-sql-remote-submit-path

Conversation

@88fantasy

Copy link
Copy Markdown
Contributor

What is the purpose of the change

Six defects on the path that turns a saved Flink SQL application into a submitted job. They are independent of each other, but each one only becomes reachable after the previous is fixed, which is why they are together here — each was found by submitting a real Flink SQL job to a standalone cluster and fixing whatever failed next.

Closes #4483
Closes #4488
Closes #4489
Closes #4490

Brief change log

  1. ClassLoaderUtils.runAsClassLoader restores the caller's own context classloader ([Bug] ClassLoaderUtils.runAsClassLoader restores a stale context classloader captured at class-init time #4489). It previously restored a static final field captured at class-initialisation time — whichever thread first loaded the class. On pooled threads that silently installs an unrelated classloader and leaves it there. ORIGINAL_CLASS_LOADER stays, since cloneClassLoader() still uses it.

  2. FlinkClientTrait.getCustomCommandLines and RemoteClient.getStandAloneClusterDescriptor run under their own class's classloader ([Bug] PipelineExecutorFactory ServiceConfigurationError when submitting a Flink job (ChildFirstClassLoader / console baseline Flink version conflict) #4483). Both call Flink classes bound to the Flink version bundled with this module, while the calling thread's context classloader is FlinkShimsProxy's target-version shims classloader. Their internal ServiceLoader lookups therefore resolved providers from a different Flink version than the interfaces bundled here, throwing ServiceConfigurationError: ... not a subtype.

  3. Build-response getters carry @JsonProperty ([Bug] Build result paths are silently dropped when persisted, breaking every subsequent job start #4488). They do not follow JavaBean naming, so Jackson silently omitted them: every persisted build result lost shadedJarPath/workspacePath, and only pass appeared to survive — by the coincidence that its field default is already true. Method names are unchanged, so no caller is affected. The K8s and Docker build responses had the same defect and are fixed with it.

  4. SubmitRequest.userJarFile() tolerates a null shadedJarPath instead of passing it to new File(...).

  5. streampark-console-service depends on streampark-flink-shims-base-v2 ([Bug] All Flink 2.x SQL jobs fail with NoClassDefFoundError: FlinkTableInitializerV2 #4490), so FlinkTableInitializerV2 reaches the console's lib/. Only the v1 module was declared, so every Flink 2.x SQL job failed with NoClassDefFoundError.

  6. setUserClassPaths is re-enabled for FLINK_SQL jobs only. It was disabled wholesale for [Bug] Demo Flink SQL can not be run on yarn-per-job mode with flink 1.16 and flink 1.17 #3761, whose reported scenario is a different deploy mode; a SQL job needs its connector jars on the client classpath. Every other job type keeps the current behaviour.

Verifying this change

  • Verified by submitting real Flink SQL jobs to a standalone Flink cluster, one defect at a time: each fix was built, deployed, and confirmed to make its specific failure disappear before the next one was investigated.
  • ShadedBuildResponse serialisation was checked by round-tripping it through a plain ObjectMapper in jshell against the built jar — shadedJarPath is absent from the JSON before the change and present after.
  • mvn install over streampark-common, streampark-flink-client-api, streampark-flink-client-core and streampark-flink-packer passes, spotless/checkstyle/scalastyle included.

Does this pull request potentially affect one of the following parts

  • Dependencies (does it add or upgrade a dependency): no
  • The public API: no (method names and signatures unchanged; only annotations and call-site classloader scoping)
  • The runtime per-record code paths (performance sensitive): no
  • Anything that affects deployment: yesstreampark-flink-shims-base-v2 is now packaged into the console distribution.

Documentation

  • Does this pull request introduce a new feature? no

Six defects on the path that turns a saved Flink SQL application into a
submitted job. Each was found by submitting a real Flink SQL job to a
standalone cluster and fixing whatever failed next; they are independent
of each other but all sit on this one path.

1. ClassLoaderUtils.runAsClassLoader restored the context classloader
   captured in a static field when the class was first initialized —
   whichever thread happened to load it — instead of the one the calling
   thread had on entry. On pooled threads that silently replaces an
   unrelated thread's context classloader.

2. FlinkClientTrait.getCustomCommandLines and
   RemoteClient.getStandAloneClusterDescriptor call into Flink classes
   bound to the Flink version bundled with this module, while the calling
   thread's context classloader is FlinkShimsProxy's target-version shims
   classloader. Their internal ServiceLoader lookups therefore resolved
   providers from a different Flink version than the interfaces bundled
   here, failing with ServiceConfigurationError ("not a subtype"). Both
   call sites now run under their own class's classloader. Closes apache#4483.

3. The build-response getters (workspacePath, pass, shadedJarPath,
   flinkBaseImage, mainJarPath, extraLibJarPaths, flinkImageTag,
   podTemplatePaths, dockerInnerMainJarPath) do not follow JavaBean
   getter naming and carried no @JsonProperty, so Jackson silently
   skipped them: every build result persisted to t_flink_app's
   buildResultJson lost its paths, and only pass survived — by the
   coincidence that its field default is already true. A later submit
   then read back shadedJarPath == null and failed with an NPE, an
   "entry point class not found", or "flinkJobJar is null", depending on
   which downstream path consumed it.

4. SubmitRequest.userJarFile() passed shadedJarPath() straight to
   new File(...), which throws NPE when it is legitimately null.

5. streampark-console-service declared a compile dependency on
   streampark-flink-shims-base but not on streampark-flink-shims-base-v2,
   so FlinkTableInitializerV2 never reached the console's lib/ and every
   Flink 2.x SQL job failed with NoClassDefFoundError. Flink 1.x was
   unaffected, which is why this went unnoticed.

6. PackagedProgram's setUserClassPaths, disabled wholesale for apache#3761, is
   re-enabled for FLINK_SQL jobs only, so a SQL job's connector jars reach
   the client classpath. Verified against a real cluster not to reproduce
   the ClassCastException apache#3761 describes, and it leaves every other job
   type on the existing behaviour.
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment