diff --git a/api/src/main/java/javax/jdo/JDOHelper.java b/api/src/main/java/javax/jdo/JDOHelper.java index aa1d0601..fa6883e6 100644 --- a/api/src/main/java/javax/jdo/JDOHelper.java +++ b/api/src/main/java/javax/jdo/JDOHelper.java @@ -1579,7 +1579,11 @@ public static JDOEnhancer getEnhancer(ClassLoader loader) { int numberOfJDOEnhancers = 0; Enumeration urls = null; try { - urls = getResources(loader, Constants.SERVICE_LOOKUP_ENHANCER_RESOURCE_NAME); + // Use ctrLoader (falls back to the context class loader when the caller + // passed null) for the service-resource lookup, matching the class + // loading below; passing the original loader made getEnhancer(null) + // always fail with an NPE inside the resource lookup. + urls = getResources(ctrLoader, Constants.SERVICE_LOOKUP_ENHANCER_RESOURCE_NAME); } catch (Exception ex) { exceptions.add(ex); } diff --git a/api/src/test/java/javax/jdo/JDOHelperTest.java b/api/src/test/java/javax/jdo/JDOHelperTest.java index 4da79f1a..eba112a8 100644 --- a/api/src/test/java/javax/jdo/JDOHelperTest.java +++ b/api/src/test/java/javax/jdo/JDOHelperTest.java @@ -540,4 +540,20 @@ public static PersistenceManagerFactory getPersistenceManagerFactory(Map p return null; } } + + /** + * Test that getEnhancer(null) falls back to the thread context class loader for the + * META-INF/services resource lookup as well as for the class loading. Previously the resource + * lookup used the original null loader, so getEnhancer(null) always threw JDOFatalUserException + * ("no enhancer available") even though a TCCL-visible enhancer exists. + */ + @Test + void testGetEnhancerNullLoaderUsesContextClassLoader() { + JDOEnhancer enhancer = JDOHelper.getEnhancer(null); + Assertions.assertNotNull(enhancer, "getEnhancer(null) returned null"); + Assertions.assertEquals( + MockEnhancer.class, + enhancer.getClass(), + "getEnhancer(null) did not load the enhancer visible to the context class loader"); + } }