fix: deserialize Java records when Multi-Release classes are unavailable - #2131
Open
arimu1 wants to merge 1 commit into
Open
fix: deserialize Java records when Multi-Release classes are unavailable#2131arimu1 wants to merge 1 commit into
arimu1 wants to merge 1 commit into
Conversation
maven-shade-plugin (and similar fat-jar tools) often rewrite the jar manifest and drop Multi-Release: true while leaving META-INF/versions/16 in place. The JVM then loads the base RecordJsonAdapter stub, which returned null and fell through to ClassJsonAdapter — causing AssertionError for Java records (square#2117). Implement record support in the base adapter via reflective access to Class.isRecord / getRecordComponents so records work even without Multi-Release selection. The typed java16 implementation remains preferred when Multi-Release is intact. Fixes square#2117
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.
Summary
Fixes #2117 —
AssertionErrorwhen deserializing Java records after packaging withmaven-shade-plugin.Root cause
Moshi ships
RecordJsonAdapteras a Multi-Release JAR:RecordJsonAdapter): stub whose factory always returnednullMETA-INF/versions/16/: real record supportmaven-shade-plugincommonly rewrites the jar manifest (e.g. only settingMain-Class) and dropsMulti-Release: true, while still copyingMETA-INF/versions/16/. Without that manifest flag the JVM ignores the versioned classes and loads the stub. The factory returnsnull, Moshi falls through toClassJsonAdapter, and field assignment on a record fails withIllegalAccessException→ bareAssertionError.Confirmed: the same shaded jar works once
Multi-Release: trueis restored on the manifest.Fix
Implement record support in the base
RecordJsonAdapterusing reflective access toClass.isRecord()/getRecordComponents()(and related APIs). That keeps--release 8compilation while making records work on JDK 16+ even when Multi-Release classes are not selected.The typed implementation under
src/main/java16is unchanged and remains preferred when Multi-Release packaging is intact.Test plan
./gradlew :moshi:records-tests:test(includes newsimpleRecordFromJson)./gradlew :moshi:test./gradlew spotlessCheckMulti-Releasein fat-jar manifest):AssertionErroratClassJsonAdapter.fromJson2.0.0-SNAPSHOTvia mavenLocal): printsFoo[bar=baz]Notes
Preserving
Multi-Release: truein shade config remains a good practice (selects the typed JDK 16 implementation), but is no longer required for record deserialization to work.