You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
InjectorHolder builds its injector during class initialization, so one failed build breaks it for the rest of the JVM #376
InjectorHolder builds its injector in the enum constructor, that is during class initialization, from the GuiceModuleLoader that InjectorConfiguration holds at that moment. It never reads the loader again. If that build throws, the IllegalStateException fails class initialization. Every later use of the class in the same JVM then throws NoClassDefFoundError: Could not initialize class org.forgerock.guice.core.InjectorHolder, without the original cause.
GuiceTestCase.setupGuiceModules() triggers that build too. It calls InjectorHolder.getInjector() only to save oldInjector before it registers the test's own injector, and that first call initializes the class. So a GuiceTestCase subclass depends on whichever loader was installed when the first class in the JVM touched the holder, although it never uses the root injector.
In OpenAM this makes test results depend on class order wherever the default loader cannot build an injector from the test classpath (in openam-scripting it fails with No implementation for NotificationBroker was bound). Each such test module has to install a loader before any class touches the holder: a @BeforeSuite hook in openam-core-rest (OpenIdentityPlatform/OpenAM#1186) and a TestNG execution listener in openam-scripting (OpenIdentityPlatform/OpenAM#1188). The openam-core-rest failure only showed up on CI after ubuntu-latest moved to ubuntu-26.04, which runs the test classes in a different order.
A possible direction:
build the root injector lazily, on the first getInstance, injectMembers or createChildInjector call that finds no injector, instead of in the constructor;
have getInjector() return the current injector without building one, so GuiceTestCase saves and restores "no injector" instead of forcing a build;
report a failed build to each caller with its cause, instead of failing class initialization.
With that, a GuiceTestCase subclass would no longer depend on the loader at all, and a failed root build would show its real cause.
Activity
[OpenIdentityPlatform#376] InjectorHolderTest: check the root injecto…