From bd8a3e25ac4b4dd4cf5a78849850d7650eca460f Mon Sep 17 00:00:00 2001 From: Bauke Scholtz Date: Mon, 11 May 2026 10:47:43 -0400 Subject: [PATCH 1/2] Scope java:global/ resource pools per declaring app MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ComponentEnvManagerImpl.getResourceId returned "" for ScopeType.GLOBAL, so deriveResourceName produced an un-prefixed pool name and every app declaring the same java:global/X (e.g. @DataSourceDefinition) shared one physical connection pool. Connections opened against the first app's classloader stayed in the shared pool after that app undeployed, blowing up the next app's lookups with "ClassLoader is not in expected state" wrapped as SQLException: GeneralError. Return the application name for GLOBAL too, matching the behaviour already in place for APP scope. Each app now gets its own physical pool keyed under __SYSTEM/...//java:global/X — symmetric with __SYSTEM/...//java:app/X. The empty fall-through has been there since the helper was introduced in 1230a81f8f (2012-07-25, Java EE 7 Mail Resource Annotation); GLOBAL was simply omitted from the COMPONENT/MODULE/APP cascade. No deliberate semantics to preserve. Discovered while debugging recurring "GeneralError" failures in jakartaee/security#368 (Jakarta Security TCK arquillian-glassfish-server-pool migration), where multiple app-db-* modules each declare @DataSourceDefinition(name = "java:global/securityAPIDB", ...). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../common/impl/ComponentEnvManagerImpl.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/appserver/common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java b/appserver/common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java index 5497a7770b3..ea74f172caf 100644 --- a/appserver/common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java +++ b/appserver/common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java @@ -314,10 +314,13 @@ private String getResourceId(JndiNameEnvironment env, Descriptor desc) { if (dependencyAppliesToScope(desc, ScopeType.MODULE)) { return getApplicationName(env) + "/" + getModuleName(env); } - if (dependencyAppliesToScope(desc, ScopeType.APP)) { - return getApplicationName(env); - } - return ""; + // APP and GLOBAL scopes: scope the underlying physical resource (pool + // name, etc.) to the declaring app. For java:global/ this is what + // prevents two apps declaring the same name from sharing one physical + // pool — which would let connections opened against the first app's + // classloader linger after that app undeploys, blowing up the next + // app's lookups with "ClassLoader is not in expected state". + return getApplicationName(env); } private void addAllDescriptorBindings(JndiNameEnvironment jndiEnv, ScopeType scope, Collection jndiBindings) { From 7262d9ab43ed742c9a8ee17673b818b106d6509d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Wed, 13 May 2026 21:55:10 +0200 Subject: [PATCH 2/2] Fixed imports + bit of formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- ...akartaPersistenceIntegrationExtension.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/JakartaPersistenceIntegrationExtension.java b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/JakartaPersistenceIntegrationExtension.java index 72e358d96cd..a4495b248fb 100644 --- a/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/JakartaPersistenceIntegrationExtension.java +++ b/appserver/persistence/jnosql-integration/src/main/java/org/glassfish/main/jnosql/jakartapersistence/JakartaPersistenceIntegrationExtension.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Contributors to the Eclipse Foundation + * Copyright (c) 2025, 2026 Contributors to the Eclipse Foundation * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -29,13 +29,12 @@ import java.util.Collection; import java.util.List; import java.util.Set; -import java.util.logging.Logger; +import org.eclipse.jnosql.extensions.sql.repository.spi.AbstractRepositoryPersistenceBean; import org.eclipse.jnosql.jakartapersistence.communication.EntityManagerProvider; import org.eclipse.jnosql.jakartapersistence.communication.PersistenceDatabaseManagerProvider; import org.eclipse.jnosql.jakartapersistence.mapping.EnsureTransactionInterceptor; import org.eclipse.jnosql.jakartapersistence.mapping.cache.PersistenceUnitCacheProvider; -import org.eclipse.jnosql.jakartapersistence.mapping.repository.AbstractRepositoryPersistenceBean; import org.eclipse.jnosql.jakartapersistence.mapping.spi.MethodInterceptor; import org.eclipse.jnosql.mapping.core.Converters; import org.eclipse.jnosql.mapping.core.spi.AbstractBean; @@ -70,13 +69,15 @@ // TODO - activate this extension and JNoSQL extensions from a sniffer only if interfaces with @Repository annotation exist in the app public class JakartaPersistenceIntegrationExtension implements Extension { - private static final Logger LOGGER = Logger.getLogger(JakartaPersistenceIntegrationExtension.class.getName()); - - /* Must be triggered before the JakartaPersistenceExtension from JNoSQL to register the GlassFishClassScanner - before it's used there + /* + * Must be triggered before the JakartaPersistenceExtension from JNoSQL to register + * the GlassFishClassScanner before it's used there */ - void afterBeanDiscovery(@Observes @Priority(Interceptor.Priority.LIBRARY_BEFORE) AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) { - + void afterBeanDiscovery( + @Observes + @Priority(Interceptor.Priority.LIBRARY_BEFORE) + AfterBeanDiscovery afterBeanDiscovery, + BeanManager beanManager) { boolean jpaEnabled = new GlassFishJakartaPersistenceClassScanner().isEnabled(); boolean noSqlEnabled = new GlassFishNoSqlClassScanner().isEnabled(); @@ -164,5 +165,4 @@ public T getBy(Class type, String string) { }; } - }