Skip to content

Fall back to the library class loader for classpath resources (2.x) - #1266

Merged
stevehu merged 1 commit into
networknt:2.xfrom
joaodinissf:classpath-resource-loader-fallback-2.x
Jul 7, 2026
Merged

stevehu merged 1 commit into
networknt:2.xfrom
joaodinissf:classpath-resource-loader-fallback-2.x

Conversation

@joaodinissf

Copy link
Copy Markdown
Contributor

Backport of #1265 to 2.x; closes #1264. Identical patch and test, Java 8 compatible.

In OSGi runtimes the thread context class loader cannot see
this library's bundled meta-schemas, so resolution fails with
FileNotFoundException: classpath:draft/2020-12/schema. The 1.x
ClasspathURLStreamHandler chained class loaders; the chain was not
carried over in the schema retrieval refactor (#931).

The fallback runs only after the TCCL misses, so flat classpath
behavior is unchanged, and it is skipped when a custom class loader
source is supplied.
@stevehu

stevehu commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

No blocking findings on PR 1266.

Risk: medium-low. Same reason as PR 1265: the patch is small, but it touches ClasspathResourceLoader#getResource, which is on schema/meta-schema loading paths. GitNexus maps the direct
callers to SchemaLoader.getSchemaResource, SchemaLoader.getClasspathResource, and Schema.getInputResource, with impact centered on loadSchema.

Backport quality looks good:

  • The production and test files are byte-equivalent to PR 1265’s versions.
  • 2.x is Java 8 / Jackson 2.18.4, and the new test uses Java 8-compatible APIs.
  • The CRLF-aware whitespace check passes: git -c core.whitespace=cr-at-eol diff --check origin/2.x...review-pr-1266.

Coverage is appropriate:

  • fallback when TCCL cannot see bundled resources: json-schema-validator/src/test/java/com/networknt/schema/resource/ClasspathResourceLoaderTcclTest.java:66
  • TCCL precedence: json-schema-validator/src/test/java/com/networknt/schema/resource/ClasspathResourceLoaderTcclTest.java:74
  • custom supplier remains isolated: json-schema-validator/src/test/java/com/networknt/schema/resource/ClasspathResourceLoaderTcclTest.java:95

Non-blocking gap: this restores the important bundled-resource fallback, but not the full old 1.0.x classpath URL chain’s final system-classloader lookup. I would not block on that for
issue #1264, since the failing resource is bundled in this library jar and the new fallback covers it.

Verification run under Corretto 8:

  • mvn -q -Dtest=ClasspathResourceLoaderTcclTest test passed.
  • mvn -q test passed.
  • mvn -q -DskipTests package passed.
  • Built json-schema-validator-2.0.3.jar contains draft/2020-12/schema.

CI/check-runs are not reported on GitHub for the PR head, so local Java 8 verification is the meaningful gate. Recommendation: approve after CI if required by process; otherwise this
backport is safe to merge.

@stevehu

stevehu commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

I have reviewed the pull request diff for PR #1266 in the networknt/json-schema-validator repository.

Summary

This PR addresses a common classloading issue in environments like OSGi or application servers, where the Thread Context Class Loader (TCCL) is set but unable to see the bundled resources of the library itself. The fix introduces a fallback mechanism to use the library's own class loader (ResourceLoader.class.getClassLoader()) when the TCCL fails to locate a classpath resource.

Code Review

1. ClasspathResourceLoader.java

  • Safe Fallback: The fallback logic is cleanly implemented. It first attempts to load with the default classLoader (TCCL), and only falls back to ownClassLoader if the resource isn't found.
  • Optimization: The condition ownClassLoader != null && ownClassLoader != classLoader correctly prevents redundant lookups if the TCCL and the library's class loader are identical, and safely handles cases where the class might be loaded by the bootstrap classloader (which returns null).
  • Backward Compatibility: The introduction of a private constructor ClasspathResourceLoader(Supplier<ClassLoader> classLoaderSource, boolean fallbackToOwnClassLoader) ensures that the fallback is only enabled by default for the no-args constructor. If a user explicitly provided a custom classLoaderSource, the fallback is disabled (false), preserving the exact explicit behavior they requested.

2. ClasspathResourceLoaderTcclTest.java

  • The test coverage is excellent and verifies all critical execution paths:
    • metaSchemaLoadsWhenContextClassLoaderCannotSeeResources: Verifies the fix itself using a blind TCCL.
    • contextClassLoaderStillWinsWhenItCanSeeTheResource: Ensures that the TCCL takes precedence if both loaders can find a resource with the same name.
    • explicitCustomClassLoaderSourceIsNotOverridden: Verifies that providing a custom class loader supplier does not trigger the fallback, matching the intended design.
  • The utility withContextClassLoader correctly restores the original TCCL in a finally block to prevent test pollution.

Conclusion

Status: Approved / LGTM (Looks Good To Me)

The code is well-structured, correctly addresses the OSGi visibility edge cases, maintains backward compatibility, and includes solid unit tests. There are no bugs, concurrency issues, or architectural concerns. You can safely merge this PR!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants