Skip to content

Remove thread-context-classloader hack in Weld BDA; rely on per-BDA ResourceLoader SPI - #26090

Merged
dmatej merged 1 commit into
eclipse-ee4j:mainfrom
renatsaf:code-cleanup-issue-25593-weld-classloader
Aug 2, 2026
Merged

Remove thread-context-classloader hack in Weld BDA; rely on per-BDA ResourceLoader SPI#26090
dmatej merged 1 commit into
eclipse-ee4j:mainfrom
renatsaf:code-cleanup-issue-25593-weld-classloader

Conversation

@renatsaf

Copy link
Copy Markdown
Contributor

Summary

Fixes #25593.

BeanDeploymentArchiveImpl.getBeanClasses() set the thread context classloader (TCL) to the BDA's module classloader as a side effect — a long-standing workaround for WELD-781, introduced back in #18152, from before Weld offered an SPI to control the classloader per bean deployment archive.

That side effect is fragile: a getter mutates global thread state, so it leaks into any caller (e.g. toString()), and when a BDA uses a custom classloader the TCL stays set for the rest of the Weld deployment because GlassFish only restores it at the end of WeldDeployer.enable().

The SPI has long since landed and GlassFish already uses it:

  • per-BDA ResourceLoader — registered in WeldDeployer.enable() with getModuleClassLoaderForBDA(), so Weld loads each archive's classes/resources with the correct classloader;
  • ProxyServices — resolves the bean's own classloader for proxy generation.

The TCL manipulation is therefore redundant.

Changes

  • BeanDeploymentArchiveImpl.getBeanClasses() is now a pure getter (no TCL side effect).
  • Removed the dependent machinery: the deploymentComplete flag and its is/set accessors, the originalClassLoader save/restore and deploymentComplete() call in WeldDeployer.enable(), and the now-orphaned AS-CDI-00001 "Setting Context Class Loader" log message.

Notes / risk

Behavioral change: during Weld bootstrap the TCL is no longer mutated to each BDA's module classloader; it stays as the deployment-time classloader. ProxyServicesImpl still falls back to the TCL only for non-application beans (e.g. UserTransaction proxies), which now resolve against the application classloader — a reasonable choice. As the issue notes there is no functional reproducer today, so correctness rests on the CDI/Weld TCKs (multi-module EARs, RARs, WEB-INF/lib bean archives, built-in-bean proxies).

🤖 Generated with Claude Code

@dmatej
dmatej requested a review from a team July 1, 2026 22:28
@dmatej dmatej added this to the 8.0.4 milestone Jul 1, 2026
…esourceLoader SPI

BeanDeploymentArchiveImpl.getBeanClasses() set the thread context
classloader to the BDA's module classloader as a side effect, a
workaround for WELD-781 from before Weld offered an SPI to control the
classloader per bean deployment archive. The side effect leaked into any
caller of this getter (e.g. toString()) and, when the BDA classloader is
a custom one, remained set for the rest of the Weld deployment because
GlassFish only reset it at the end of WeldDeployer.enable().

Weld now resolves classes and resources of each archive through the
per-BDA ResourceLoader SPI, which GlassFish already registers in
WeldDeployer.enable() using getModuleClassLoaderForBDA(); proxy
generation goes through ProxyServices. The TCL manipulation is therefore
redundant.

Make getBeanClasses() a pure getter and drop the dependent machinery:
the deploymentComplete flag with its accessors, the originalClassLoader
save/restore and deploymentComplete() call in WeldDeployer.enable(), and
the now-orphaned AS-CDI-00001 "Setting Context Class Loader" log message.

Fixes eclipse-ee4j#25593

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dmatej
dmatej force-pushed the code-cleanup-issue-25593-weld-classloader branch from 91c9cf1 to a004867 Compare August 2, 2026 21:12
@dmatej

dmatej commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Rebased, I hope now Jenkins will like it :)

@dmatej

dmatej commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Weird failure in GHA Ubuntu ... I will retry, so just for the record.

[ERROR] Failures: 
66914
[ERROR] org.glassfish.main.test.app.monitoring.ThreadPoolMonitoringTest.testThreadPoolSizeDecrease
66915
[INFO]   Run 1: PASS
66916
[ERROR]   Run 2: ThreadPoolMonitoringTest.testThreadPoolSizeDecrease:466 afterDecrease (2 failures)
66917
	java.lang.AssertionError: current threads
66918
Expected: <0>
66919
     but: was <22>
66920
	java.lang.AssertionError: busy threads
66921
Expected: <0>
66922
     but: was <10>
66923
[INFO] 
66924
[ERROR] Errors: 
66925
[ERROR]   ManagedExecutorDefinitionWebTest.testCopyCompletableFutureTwice:72 » Socket Unexpected end of file from server
66926
[ERROR]   ManagedExecutorTasksSubmittedDuringDeploymentTest.testSubmittedTaskExecuted:70 » Socket Unexpected end of file from server
66927
[INFO] 
66928
[ERROR] Tests run: 100, Failures: 1, Errors: 2, Skipped: 3

@dmatej
dmatej merged commit 86bd93b into eclipse-ee4j:main Aug 2, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Instruct Weld to use a specific classloader instead of hacky solution with thread context classloader

2 participants