[736] Make the bundled xtable-utilities jar runnable again#840
Merged
Conversation
2f77b1a to
0fabba7
Compare
Running the bundled utilities jar the way the docs describe (java -jar xtable-utilities_2.12-*-bundled.jar --datasetConfig config.yaml) failed on a chain of NoClassDefFoundErrors, and syncing *to* Hudi was silently skipped. Two upstream changes caused this: apache#822 replaced the maven-shade "bundle everything" default with an explicit artifactSet allowlist, and the Hudi 1.x bump split hudi-common into hudi-common + hudi-io + hudi-hadoop-common. Runtime dependencies dropped from the shaded jar: org.slf4j:slf4j-api -> org/slf4j/LoggerFactory org.apache.hudi:hudi-hadoop-common -> org/apache/hudi/hadoop/fs/HadoopFSUtils org.apache.hudi:hudi-io -> (runtime transitive, not allowlisted) org.openjdk.jol:jol-core -> org/openjdk/jol/info/GraphLayout (apache#736) Fixes: - Add slf4j-api, hudi-io and jol-core to the shade allowlist. - jol-core is pinned to test scope by the parent dependencyManagement, so override it to runtime (Hudi's ObjectSizeCalculator loads it at runtime). - hudi-hadoop-common is only a provided/test transitive, so declare it as a runtime dependency of the standalone bundle and allowlist it. - hudi-java-client was declared twice (compile + a redundant test-scoped copy); Maven's last-declaration-wins downgraded it to test scope, so the shade plugin excluded the Hudi write client (HoodieJavaEngineContext) and RunSync skipped HudiConversionTarget. Remove the redundant test declaration so the compile one takes effect and the write client is bundled. Verified end-to-end via java -jar against real tables: - Hudi (table v9, metadata table enabled) -> Delta + Iceberg: reads the Hudi metadata table (the ObjectSizeCalculator/jol path from this issue) and reports "Sync is successful for the following formats ICEBERG,DELTA". - Iceberg -> Hudi: writes a real Hudi table (.hoodie timeline with a completed replacecommit) and reports "Sync is successful ... HUDI". Closes apache#736. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0fabba7 to
3c96411
Compare
the-other-tim-brown
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the purpose of the pull request
Make the bundled
xtable-utilitiesjar runnable again via the documented flow(the Hudi docs):
Fixes #736. Building
mainand running that command today fails with a chain ofNoClassDefFoundErrors — #736 (the missingorg.openjdk.jol) is only the lastlink in that chain — and syncing to Hudi is silently skipped.
Root cause
Two upstream changes dropped several runtime dependencies from the shaded jar:
maven-shade bundle-everything default with an explicit
<artifactSet>allowlist. Anything not on the list is no longer bundled.
hudi-commonintohudi-common+hudi-io+hudi-hadoop-common, andxtable-corecompilesagainst these with the Hudi Spark bundle in
providedscope (a real Sparkcluster supplies them). The standalone utilities jar has no such runtime.
Net effect —
RunSyncdies before doing any work:org.slf4j:slf4j-apiNoClassDefFoundError: org/slf4j/LoggerFactory(at first HadoopConfigurationinit)org.apache.hudi:hudi-hadoop-commonNoClassDefFoundError: org/apache/hudi/hadoop/fs/HadoopFSUtilsorg.apache.hudi:hudi-ioorg.openjdk.jol:jol-coreNoClassDefFoundError: org/openjdk/jol/info/GraphLayout(#736, at the Hudi metadata-table read)Separately, syncing to Hudi was silently skipped:
hudi-java-client(theHudi write client, incl.
HoodieJavaEngineContext) was declared twice —once at
compile, and again with<scope>test</scope>in the test block.Maven's last-declaration-wins downgraded the effective scope to
test, so theshade plugin excluded it (even though it's on the allowlist — the allowlist only
filters what's eligible, it can't promote a test-scoped artifact back in).
ConversionTargetFactorythen loggedWARN … Skipping a registered ConversionTarget whose engine library is not on the classpathand droppedHudiConversionTarget.Brief change log
xtable-utilities/pom.xmlonly:org.slf4j:slf4j-api,org.apache.hudi:hudi-io, andorg.openjdk.jol:jol-coreto the shade<includes>allowlist.jol-coreis pinned totestby the parentdependencyManagement, sooverride it to
runtime(Hudi'sObjectSizeCalculatorloads it at runtime,not only in tests).
hudi-hadoop-commonis only aprovided/testtransitive, so declare it asan explicit
runtimedependency of the bundle and allowlist it.test-scopedhudi-java-clientdeclaration so thecompileone takes effect and the Hudi write client is bundled.Why utilities isn't published to Maven (context for reviewers)
xtable-utilitiesis not published to Maven and is excluded from the ASFrelease process — see the dev@ thread "[DISCUSS] Excluding xtable-utilities
from the release process" and #536. It is an unshaded, un-relocated ~1 GB fat
jar that bundles the full transitive closure of Spark/Hadoop/Hive/etc.; that
form can't be released under ASF licensing/release guidelines. Because there's
no published artifact, users build the bundle locally — which is exactly the
path where these
test/provided-scoped-but-runtime-needed gaps surface. ThisPR keeps that local build working.
The maintained, long-term replacement is
xtable-spark-runtime(#836): athin, relocated, config-only drop-in Spark bundle that runs incremental
ConversionController.sync(...)in-job (implementation in #838 / #839). This PRis a targeted fix for the existing utilities jar in the meantime, not a
substitute for that effort.
Verify this pull request
Built the bundle locally and ran the documented command against real tables:
Hudi → Delta + Iceberg (Hudi 1.2.0 source, table version 9, MDT enabled,
150 rows) — previously a
NoClassDefFoundError:_delta_log/00000000000000000000.jsonand Icebergv{1,2,3}.metadata.jsonwritten; all 150 records committed.Iceberg → Hudi (200-row path-based Iceberg source) — previously skipped:
A real Hudi table is written (
.hoodie/….replacecommitCOMPLETED +hoodie.properties+ metadata table); no "Skipping … ConversionTarget" warning.🤖 Generated with Claude Code