diff --git a/appserver/admingui/pom.xml b/appserver/admingui/pom.xml
index 4647f11eb29..c8f87d96899 100644
--- a/appserver/admingui/pom.xml
+++ b/appserver/admingui/pom.xml
@@ -161,4 +161,12 @@
+
+
+ dev
+
+ false
+
+
+
diff --git a/appserver/admingui/web/pom.xml b/appserver/admingui/web/pom.xml
index d8bcdf3166b..104b98a6266 100644
--- a/appserver/admingui/web/pom.xml
+++ b/appserver/admingui/web/pom.xml
@@ -86,5 +86,4 @@
-
diff --git a/appserver/admingui/web/src/main/resources/configuration/threadPoolAttrs.inc b/appserver/admingui/web/src/main/resources/configuration/threadPoolAttrs.inc
index 8666ec48a53..4c24b57ad13 100644
--- a/appserver/admingui/web/src/main/resources/configuration/threadPoolAttrs.inc
+++ b/appserver/admingui/web/src/main/resources/configuration/threadPoolAttrs.inc
@@ -30,8 +30,12 @@
-
-
+
+
+
+
+
+
diff --git a/appserver/admingui/web/src/main/resources/configuration/threadPoolEdit.jsf b/appserver/admingui/web/src/main/resources/configuration/threadPoolEdit.jsf
index f131d2ca7c4..d183716d03d 100644
--- a/appserver/admingui/web/src/main/resources/configuration/threadPoolEdit.jsf
+++ b/appserver/admingui/web/src/main/resources/configuration/threadPoolEdit.jsf
@@ -39,6 +39,7 @@
setPageSessionAttribute(key="selfUrl", value="#{pageSession.parentUrl}/#{pageSession.childType}/#{pageSession.encodedName}");
setPageSessionAttribute(key="rest-api" value="true");
gf.getEntityAttrs(endpoint="#{pageSession.selfUrl}.json", valueMap="#{pageSession.valueMap}");
+ setPageSessionAttribute(key="convertToFalseList" value={"virtual"});
//set the following for including buttons.inc
setPageSessionAttribute(key="edit" value="#{true}" );
setPageSessionAttribute(key="showDefaultButton" value="#{true}" );
diff --git a/appserver/admingui/web/src/main/resources/configuration/threadPoolNew.jsf b/appserver/admingui/web/src/main/resources/configuration/threadPoolNew.jsf
index bb1dd843974..e2104f08048 100644
--- a/appserver/admingui/web/src/main/resources/configuration/threadPoolNew.jsf
+++ b/appserver/admingui/web/src/main/resources/configuration/threadPoolNew.jsf
@@ -35,7 +35,9 @@
setPageSessionAttribute(key="rest-api" value="true");
gf.getDefaultValues(endpoint="#{pageSession.selfUrl}", valueMap="#{pageSession.valueMap}");
mapPut(map="#{pageSession.valueMap}" key="target" value="#{pageSession.configName}");
- setPageSessionAttribute(key="skipAttrsList" value={"classname"});
+ setPageSessionAttribute(key="skipAttrsList" value={});
+ setPageSessionAttribute(key="convertToFalseList" value={"virtual"});
+ setPageSessionAttribute(key="convertToFalseList" value={"virtual"});
//set the following for including buttons.inc
setPageSessionAttribute(key="edit" value="#{false}" );
setPageSessionAttribute(key="showDefaultButton" value="#{true}" );
diff --git a/appserver/admingui/web/src/main/resources/org/glassfish/web/admingui/Strings.properties b/appserver/admingui/web/src/main/resources/org/glassfish/web/admingui/Strings.properties
index 78e80b592e3..b75ed8b3cb6 100644
--- a/appserver/admingui/web/src/main/resources/org/glassfish/web/admingui/Strings.properties
+++ b/appserver/admingui/web/src/main/resources/org/glassfish/web/admingui/Strings.properties
@@ -154,6 +154,10 @@ threadPool.threadPoolIdCol=Thread Pool ID
threadPool.nameHelp=Name of the thread pool
threadPool.classname=Class Name:
threadPool.classnameHelp=The name of the class that implements the thread pool
+threadPool.virtual=Use Virtual Threads:
+threadPool.virtualHelp=Enable virtual threads for this thread pool. When enabled, the thread pool will use virtual threads if no custom class name is specified.
+threadPool.virtual=Use Virtual Threads:
+threadPool.virtualHelp=Enable virtual threads for this thread pool. When enabled, the thread pool will use virtual threads if no custom class name is specified.
threadPool.timeoutCol=Idle Thread Timeout
threadPool.timeout=Idle Thread Timeout:
threadPool.timeoutHelp=The maximum amount of time that a thread can remain idle in the pool. After this time expires, the thread is removed from the pool.
diff --git a/appserver/distributions/glassfish/src/main/java/org/eclipse/krazo/cdi/types/AnnotatedTypeProcessor.java b/appserver/distributions/glassfish/src/main/java/org/eclipse/krazo/cdi/types/AnnotatedTypeProcessor.java
index 9ceda50d89b..05d1d3045cd 100644
--- a/appserver/distributions/glassfish/src/main/java/org/eclipse/krazo/cdi/types/AnnotatedTypeProcessor.java
+++ b/appserver/distributions/glassfish/src/main/java/org/eclipse/krazo/cdi/types/AnnotatedTypeProcessor.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2025 Contributors to the Eclipse Foundation.
* Copyright (c) 2018, 2025 Eclipse Krazo committers and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,14 +16,12 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
-package org.eclipse.krazo.cdi.types;
-import org.eclipse.krazo.binding.validate.ValidationInterceptorBinding;
-import org.eclipse.krazo.cdi.AroundController;
-import org.eclipse.krazo.util.ControllerUtils;
+package org.eclipse.krazo.cdi.types;
import jakarta.enterprise.inject.spi.AnnotatedMethod;
import jakarta.enterprise.inject.spi.AnnotatedType;
+
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.LinkedHashSet;
@@ -31,6 +30,10 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.eclipse.krazo.binding.validate.ValidationInterceptorBinding;
+import org.eclipse.krazo.cdi.AroundController;
+import org.eclipse.krazo.util.ControllerUtils;
+
/**
* This class can create a modified version of a AnnotatedType to inject custom behavior
* into controllers.
@@ -110,4 +113,4 @@ private static boolean isOneOf(T object, T... objects) {
return false;
}
-}
\ No newline at end of file
+}
diff --git a/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/DistributedEJBTimerService.java b/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/DistributedEJBTimerService.java
index 3b953811a34..0fe8c4c7aa6 100644
--- a/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/DistributedEJBTimerService.java
+++ b/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/DistributedEJBTimerService.java
@@ -20,10 +20,6 @@
import com.sun.ejb.containers.EJBTimerService;
import com.sun.ejb.containers.EjbContainerUtil;
import com.sun.ejb.containers.EjbContainerUtilImpl;
-import com.sun.enterprise.ee.cms.core.CallBack;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
-import com.sun.enterprise.ee.cms.core.PlannedShutdownSignal;
-import com.sun.enterprise.ee.cms.core.Signal;
import com.sun.enterprise.transaction.api.RecoveryResourceRegistry;
import com.sun.enterprise.transaction.spi.RecoveryEventListener;
@@ -35,6 +31,10 @@
import org.glassfish.gms.bootstrap.GMSAdapter;
import org.glassfish.gms.bootstrap.GMSAdapterService;
import org.glassfish.hk2.api.PostConstruct;
+import org.glassfish.shoal.gms.api.core.CallBack;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
+import org.glassfish.shoal.gms.api.core.PlannedShutdownSignal;
+import org.glassfish.shoal.gms.api.core.Signal;
import org.jvnet.hk2.annotations.Service;
@Service
diff --git a/appserver/grizzly/glassfish-grizzly-extra-all/pom.xml b/appserver/grizzly/glassfish-grizzly-extra-all/pom.xml
index 1fde953451f..774ad471cba 100644
--- a/appserver/grizzly/glassfish-grizzly-extra-all/pom.xml
+++ b/appserver/grizzly/glassfish-grizzly-extra-all/pom.xml
@@ -28,7 +28,6 @@
glassfish-grizzly-extra-all
- jar
Glassfish Grizzly extra jars Combining
combining of all glassfish grizzly extra jars
diff --git a/appserver/ha/ha-shoal-store/src/main/java/org/shoal/ha/store/GlassFishKeyMapper.java b/appserver/ha/ha-shoal-store/src/main/java/org/glassfish/main/shoal/ha/store/GlassFishKeyMapper.java
similarity index 65%
rename from appserver/ha/ha-shoal-store/src/main/java/org/shoal/ha/store/GlassFishKeyMapper.java
rename to appserver/ha/ha-shoal-store/src/main/java/org/glassfish/main/shoal/ha/store/GlassFishKeyMapper.java
index ad47b55a18c..a13b73d2894 100644
--- a/appserver/ha/ha-shoal-store/src/main/java/org/shoal/ha/store/GlassFishKeyMapper.java
+++ b/appserver/ha/ha-shoal-store/src/main/java/org/glassfish/main/shoal/ha/store/GlassFishKeyMapper.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
* Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -14,12 +15,12 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-package org.shoal.ha.store;
+package org.glassfish.main.shoal.ha.store;
import org.glassfish.ha.common.GlassFishHAReplicaPredictor;
import org.glassfish.ha.common.HACookieInfo;
import org.glassfish.ha.common.HACookieManager;
-import org.shoal.ha.mapper.DefaultKeyMapper;
+import org.glassfish.shoal.ha.cache.mapper.DefaultKeyMapper;
/**
* @author Mahesh Kannan
@@ -29,18 +30,18 @@ public class GlassFishKeyMapper
extends DefaultKeyMapper
implements GlassFishHAReplicaPredictor {
- private static final String[] _EMPTY_TARGETS = new String[] {null, null};
-
- public GlassFishKeyMapper(String instanceName, String groupName) {
- super(instanceName, groupName);
+ public GlassFishKeyMapper(String instanceName) {
+ super(instanceName);
}
+ @Override
public HACookieInfo makeCookie(String groupName, Object key, String oldReplicaCookie) {
- String cookieStr = null;
-
- if (key != null) {
- cookieStr = super.getMappedInstance(groupName, key);// super.getReplicaChoices(groupName, key);
+ final String cookieStr;
+ if (key == null) {
+ cookieStr = null;
+ } else {
+ cookieStr = super.getMappedInstance(groupName, key);
}
HACookieInfo ha = new HACookieInfo(cookieStr, oldReplicaCookie);
return ha;
@@ -49,22 +50,9 @@ public HACookieInfo makeCookie(String groupName, Object key, String oldReplicaCo
@Override
public String getMappedInstance(String groupName, Object key1) {
HACookieInfo cookieInfo = HACookieManager.getCurrent();
- if (cookieInfo.getNewReplicaCookie() != null) {
- return cookieInfo.getNewReplicaCookie();
- } else {
+ if (cookieInfo.getNewReplicaCookie() == null) {
return super.getMappedInstance(groupName, key1);
}
+ return cookieInfo.getNewReplicaCookie();
}
-
- /*
- @Override
- public String getReplicaChoices(String groupName, Object key) {
- HACookieInfo cookieInfo = HACookieManager.getCurrent();
- if (cookieInfo.getOldReplicaCookie() != null) {
- return cookieInfo.getOldReplicaCookie();
- } else {
- return super.getReplicaChoices(groupName, key);
- }
- }
- */
}
diff --git a/appserver/ha/ha-shoal-store/src/main/java/org/shoal/ha/store/ReplicatedBackingStoreFactory.java b/appserver/ha/ha-shoal-store/src/main/java/org/glassfish/main/shoal/ha/store/ReplicatedBackingStoreFactory.java
similarity index 73%
rename from appserver/ha/ha-shoal-store/src/main/java/org/shoal/ha/store/ReplicatedBackingStoreFactory.java
rename to appserver/ha/ha-shoal-store/src/main/java/org/glassfish/main/shoal/ha/store/ReplicatedBackingStoreFactory.java
index 7ae9a2e4d86..23ec122e9b3 100644
--- a/appserver/ha/ha-shoal-store/src/main/java/org/shoal/ha/store/ReplicatedBackingStoreFactory.java
+++ b/appserver/ha/ha-shoal-store/src/main/java/org/glassfish/main/shoal/ha/store/ReplicatedBackingStoreFactory.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -14,7 +15,7 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
-package org.shoal.ha.store;
+package org.glassfish.main.shoal.ha.store;
import java.io.Serializable;
@@ -26,17 +27,16 @@
import org.glassfish.ha.store.api.BackingStoreFactory;
import org.glassfish.ha.store.api.BackingStoreTransaction;
import org.glassfish.ha.store.api.Storeable;
+import org.glassfish.shoal.ha.cache.mapper.KeyMapper;
+import org.glassfish.shoal.ha.cache.store.backing.ReplicatedBackingStore;
+import org.glassfish.shoal.ha.cache.store.backing.StoreableReplicatedBackingStore;
import org.jvnet.hk2.annotations.Service;
-import org.shoal.adapter.store.ReplicatedBackingStore;
-import org.shoal.adapter.store.StoreableReplicatedBackingStore;
-import org.shoal.ha.mapper.KeyMapper;
/**
* @author Mahesh Kannan
*/
@Service(name="shoal-backing-store-factory")
-public class ReplicatedBackingStoreFactory
- implements BackingStoreFactory {
+public class ReplicatedBackingStoreFactory implements BackingStoreFactory {
public ReplicatedBackingStoreFactory() {
}
@@ -48,20 +48,19 @@ public ReplicatedBackingStoreFactory(Properties p) {
public BackingStore createBackingStore(BackingStoreConfiguration conf)
throws BackingStoreException {
- KeyMapper keyMapper = new GlassFishKeyMapper(conf.getInstanceName(), conf.getClusterName());
+ KeyMapper keyMapper = new GlassFishKeyMapper(conf.getInstanceName());
conf.getVendorSpecificSettings().put("key.mapper", keyMapper);
Class vClazz = conf.getValueClazz();
if (Storeable.class.isAssignableFrom(vClazz)) {
- StoreableReplicatedBackingStore srbs = new StoreableReplicatedBackingStore();
+ StoreableReplicatedBackingStore srbs = new StoreableReplicatedBackingStore<>();
srbs.initialize(conf);
return srbs;
- } else {
- ReplicatedBackingStore bStore = new ReplicatedBackingStore();
- bStore.initialize(conf);
- System.out.println("GlassFish2ShoalBackingStoreFactory:: CREATED an instance of: " + bStore.getClass().getName());
- return bStore;
}
+ ReplicatedBackingStore bStore = new ReplicatedBackingStore();
+ bStore.initialize(conf);
+ System.out.println("GlassFish2ShoalBackingStoreFactory:: CREATED an instance of: " + bStore.getClass().getName());
+ return bStore;
}
@Override
diff --git a/appserver/orb/orb-iiop/src/main/java/org/glassfish/enterprise/iiop/impl/IiopFolbGmsClient.java b/appserver/orb/orb-iiop/src/main/java/org/glassfish/enterprise/iiop/impl/IiopFolbGmsClient.java
index 6b77d0227d8..f907df8ee40 100644
--- a/appserver/orb/orb-iiop/src/main/java/org/glassfish/enterprise/iiop/impl/IiopFolbGmsClient.java
+++ b/appserver/orb/orb-iiop/src/main/java/org/glassfish/enterprise/iiop/impl/IiopFolbGmsClient.java
@@ -32,13 +32,6 @@
import com.sun.enterprise.config.serverbeans.Nodes;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.Servers;
-import com.sun.enterprise.ee.cms.core.CallBack;
-import com.sun.enterprise.ee.cms.core.FailureNotificationSignal;
-import com.sun.enterprise.ee.cms.core.JoinedAndReadyNotificationSignal;
-import com.sun.enterprise.ee.cms.core.PlannedShutdownSignal;
-import com.sun.enterprise.ee.cms.core.Signal;
-import com.sun.enterprise.ee.cms.core.SignalAcquireException;
-import com.sun.enterprise.ee.cms.core.SignalReleaseException;
import com.sun.logging.LogDomains;
import java.net.InetAddress;
@@ -57,6 +50,13 @@
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.orb.admin.config.IiopListener;
import org.glassfish.orb.admin.config.IiopService;
+import org.glassfish.shoal.gms.api.core.CallBack;
+import org.glassfish.shoal.gms.api.core.FailureNotificationSignal;
+import org.glassfish.shoal.gms.api.core.JoinedAndReadyNotificationSignal;
+import org.glassfish.shoal.gms.api.core.PlannedShutdownSignal;
+import org.glassfish.shoal.gms.api.core.Signal;
+import org.glassfish.shoal.gms.api.core.SignalAcquireException;
+import org.glassfish.shoal.gms.api.core.SignalReleaseException;
import org.omg.CORBA.ORBPackage.InvalidName;
diff --git a/appserver/persistence/entitybean-container/src/main/java/org/glassfish/persistence/ejb/entitybean/container/distributed/ReadOnlyBeanMessageCallBack.java b/appserver/persistence/entitybean-container/src/main/java/org/glassfish/persistence/ejb/entitybean/container/distributed/ReadOnlyBeanMessageCallBack.java
index 61bf2a2d069..38af342031e 100755
--- a/appserver/persistence/entitybean-container/src/main/java/org/glassfish/persistence/ejb/entitybean/container/distributed/ReadOnlyBeanMessageCallBack.java
+++ b/appserver/persistence/entitybean-container/src/main/java/org/glassfish/persistence/ejb/entitybean/container/distributed/ReadOnlyBeanMessageCallBack.java
@@ -17,10 +17,6 @@
package org.glassfish.persistence.ejb.entitybean.container.distributed;
import com.sun.ejb.containers.EjbContainerUtil;
-import com.sun.enterprise.ee.cms.core.CallBack;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
-import com.sun.enterprise.ee.cms.core.MessageSignal;
-import com.sun.enterprise.ee.cms.core.Signal;
import com.sun.logging.LogDomains;
import jakarta.inject.Inject;
@@ -30,6 +26,10 @@
import org.glassfish.gms.bootstrap.GMSAdapter;
import org.glassfish.gms.bootstrap.GMSAdapterService;
+import org.glassfish.shoal.gms.api.core.CallBack;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
+import org.glassfish.shoal.gms.api.core.MessageSignal;
+import org.glassfish.shoal.gms.api.core.Signal;
import org.jvnet.hk2.annotations.Service;
@Service
diff --git a/appserver/pom.xml b/appserver/pom.xml
index 97bccc19be2..07b6741eb1e 100644
--- a/appserver/pom.xml
+++ b/appserver/pom.xml
@@ -93,7 +93,7 @@
2.2.0
- 2.2.1
+ 2.2.2
3.1.1
diff --git a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/monitoring/LockServlet.java b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/monitoring/LockServlet.java
index 331a9f5b81c..56f94597d0e 100644
--- a/appserver/tests/application/src/main/java/org/glassfish/main/test/app/monitoring/LockServlet.java
+++ b/appserver/tests/application/src/main/java/org/glassfish/main/test/app/monitoring/LockServlet.java
@@ -18,32 +18,30 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicBoolean;
@WebServlet("/lock")
public class LockServlet extends HttpServlet {
- private static final ConcurrentHashMap LOCKS = new ConcurrentHashMap<>();
+ private static final ConcurrentHashMap> LOCKS = new ConcurrentHashMap<>();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
String idLock = req.getParameter("idLock");
if ("lock".equals(action)) {
- AtomicBoolean lock = new AtomicBoolean(true);
+ CompletableFuture lock = new CompletableFuture<>();
LOCKS.put(idLock, lock);
- while (lock.get() && !Thread.currentThread().isInterrupted()) {
- Thread.onSpinWait();
- }
+ lock.join();
sendResponse("Unlocked " + idLock + ". Still locked around " + LOCKS.size() + " requests.", resp);
} else if ("unlock".equals(action)) {
- AtomicBoolean lock = LOCKS.remove(idLock);
+ CompletableFuture lock = LOCKS.remove(idLock);
if (lock == null) {
throw new ServletException("Unknown lock: " + lock);
}
// Release another thread trapped in the loop
- lock.set(false);
+ lock.complete(null);
sendResponse("Unlocking " + idLock + ".", resp);
} else if ("count".equals(action)) {
sendResponse(LOCKS.size(), resp);
diff --git a/appserver/tests/application/src/test/java/org/glassfish/main/test/app/monitoring/ThreadPoolMonitoringTest.java b/appserver/tests/application/src/test/java/org/glassfish/main/test/app/monitoring/ThreadPoolMonitoringTest.java
index 1100e23ec46..8f7fe884cc2 100644
--- a/appserver/tests/application/src/test/java/org/glassfish/main/test/app/monitoring/ThreadPoolMonitoringTest.java
+++ b/appserver/tests/application/src/test/java/org/glassfish/main/test/app/monitoring/ThreadPoolMonitoringTest.java
@@ -30,6 +30,7 @@
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.MethodName;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
@@ -77,9 +78,11 @@ public class ThreadPoolMonitoringTest {
}
};
private ThreadPoolMetrics http1Baseline;
+ private static boolean useVirtualThreads = false;
@BeforeAll
static void beforeAll() throws Exception {
+ useVirtualThreads(false);
deploy();
// Enable monitoring
assertThat(
@@ -99,6 +102,14 @@ static void beforeAll() throws Exception {
assertThat("admin listener busy threads", adminBaseline.currentThreadsBusy(), greaterThanOrEqualTo(0));
}
+ private static void useVirtualThreads(boolean useVirtualThreads) {
+ assertThat(ASADMIN.exec("set",
+ "configs.config.server-config.thread-pools.thread-pool.http-thread-pool.virtual=" + useVirtualThreads),
+ asadminOK());
+ ThreadPoolMonitoringTest.useVirtualThreads = useVirtualThreads;
+ }
+
+
@AfterAll
static void afterAll() {
ASADMIN.exec("undeploy", APP_NAME);
@@ -138,6 +149,61 @@ void afterEach() throws Throwable {
asadminOK());
}
+ /*
+ These tests run after the top-level tests and repeat them with virtual threads enabled on the HTTP1 thread pool
+ */
+ @Nested
+ @TestMethodOrder(MethodName.class)
+ class VirtualThreadTests {
+
+ private ThreadPoolMonitoringTest parent = ThreadPoolMonitoringTest.this;
+
+ @BeforeAll
+ static void setupVirtualThreads() {
+ useVirtualThreads(true);
+ }
+
+ @Test
+ void testDualListenerHugeAmountOfFastRequests() throws Exception {
+ parent.testDualListenerHugeAmountOfFastRequests();
+ }
+
+ @Test
+ void testThreadPoolMetricsBaseline() throws Exception {
+ parent.testThreadPoolMetricsBaseline();
+ }
+
+ @Test
+ void testThreadPoolMetricsReadTimeout() throws Exception {
+ parent.testThreadPoolMetricsReadTimeout();
+ }
+
+ @Test
+ void testThreadPoolMetricsWithBurstLoad() throws Exception {
+ parent.testThreadPoolMetricsWithBurstLoad();
+ }
+
+ @Test
+ void testThreadPoolMonitoringEnableDisable() throws Exception {
+ parent.testThreadPoolMonitoringEnableDisable();
+ }
+
+ @Test
+ void testThreadPoolSizeCycling() throws Exception {
+ parent.testThreadPoolSizeCycling();
+ }
+
+ @Test
+ void testThreadPoolSizeDecrease() throws Exception {
+ parent.testThreadPoolSizeDecrease();
+ }
+
+ @Test
+ void testThreadPoolSizeIncrease() throws Exception {
+ parent.testThreadPoolSizeIncrease();
+ }
+ }
+
/**
* Create load on admin port (4848) using asadmin commands
*/
@@ -176,7 +242,7 @@ void testDualListenerHugeAmountOfFastRequests() throws Exception {
final ThreadPoolMetrics metricsTestBaseline = getThreadPoolMetrics(HTTP_POOL_TEST);
assertThat("listener 1 current threads", metrics1Baseline.currentThreadCount(), greaterThanOrEqualTo(0));
- assertThat("listener Test current threads", metricsTestBaseline.currentThreadCount(), equalTo(5));
+ assertThat("listener Test current threads", metricsTestBaseline.currentThreadCount(), useVirtualThreads ? equalTo(0) : equalTo(5));
assertThat(new AppClient(HTTP_POOL_TEST_PORT, 5000).test(), stringContainsInOrder(HTTP_POOL_TEST));
@@ -251,7 +317,8 @@ void testThreadPoolMetricsReadTimeout() throws Exception {
Thread.sleep(HTTP_REQUEST_TIMEOUT + 100L);
assertAll("metrics under load - no response yet",
- () -> assertThat("current threads", duringLoad.currentThreadCount(), equalTo(http1Baseline.maxThreads())),
+ () -> assertThat("current threads", duringLoad.currentThreadCount(), lessThanOrEqualTo(http1Baseline.maxThreads())),
+ () -> assertThat("current threads", duringLoad.currentThreadCount(), greaterThanOrEqualTo(duringLoad.currentThreadsBusy())),
() -> assertThat("busy threads", duringLoad.currentThreadsBusy(), equalTo(locks.size())),
() -> assertThat("total tasks", duringLoad.totalTasks(), equalTo(http1Baseline.totalTasks()))
);
@@ -262,7 +329,8 @@ void testThreadPoolMetricsReadTimeout() throws Exception {
final ThreadPoolMetrics afterLoad = getThreadPoolMetrics(HTTP_POOL_1);
assertAll("metrics after client stopped",
- () -> assertThat("current threads", afterLoad.currentThreadCount(), equalTo(afterLoad.maxThreads())),
+ () -> assertThat("current threads", duringLoad.currentThreadCount(), lessThanOrEqualTo(http1Baseline.maxThreads())),
+ () -> assertThat("current threads", duringLoad.currentThreadCount(), greaterThanOrEqualTo(duringLoad.currentThreadsBusy())),
() -> assertThat("busy threads", afterLoad.currentThreadsBusy(), equalTo(0)),
() -> assertThat("total tasks", afterLoad.totalTasks(), greaterThan(http1Baseline.totalTasks()))
);
@@ -320,7 +388,7 @@ void testThreadPoolMonitoringEnableDisable() throws Exception {
// 4. Verify thread metrics show running requests
final ThreadPoolMetrics metrics = getThreadPoolMetrics(HTTP_POOL_1);
assertAll("Under load",
- () -> assertThat("current thread count", metrics.currentThreadCount(), equalTo(http1Baseline.currentThreadCount())),
+ () -> assertThat("current thread count", metrics.currentThreadCount(), greaterThanOrEqualTo(metrics.currentThreadsBusy())),
() -> assertThat("busy threads", metrics.currentThreadsBusy(), equalTo(locks.size()))
);
@@ -397,7 +465,7 @@ void testThreadPoolSizeDecrease() throws Exception {
final ThreadPoolMetrics afterDecrease = getThreadPoolMetrics(HTTP_POOL_1);
assertAll("afterDecrease",
() -> assertThat("max threads", afterDecrease.maxThreads(), equalTo(count2)),
- () -> assertThat("current threads", afterDecrease.currentThreadCount(), equalTo(afterDecrease.coreThreads())),
+ () -> assertThat("current threads", afterDecrease.currentThreadCount(), useVirtualThreads ? equalTo(0) : equalTo(afterDecrease.coreThreads())),
() -> assertThat("busy threads", afterDecrease.currentThreadsBusy(), equalTo(0))
);
@@ -431,7 +499,10 @@ void testThreadPoolSizeIncrease() throws Exception {
unlockGenerator.close();
lockGenerator.close();
- assertThat("current thread count under load", loaded.currentThreadCount(), equalTo(locks.size()));
+ assertAll("under load",
+ () -> assertThat("busy thread count under load", loaded.currentThreadsBusy(), equalTo(locks.size())),
+ () -> assertThat("current thread count under load", loaded.currentThreadCount(), equalTo(loaded.currentThreadsBusy()))
+ );
}
private static List generateLocks(int count) {
diff --git a/appserver/transaction/jts/src/main/java/com/sun/enterprise/transaction/jts/recovery/GMSCallBack.java b/appserver/transaction/jts/src/main/java/com/sun/enterprise/transaction/jts/recovery/GMSCallBack.java
index a2a2213f277..ff765da6078 100644
--- a/appserver/transaction/jts/src/main/java/com/sun/enterprise/transaction/jts/recovery/GMSCallBack.java
+++ b/appserver/transaction/jts/src/main/java/com/sun/enterprise/transaction/jts/recovery/GMSCallBack.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Contributors to the Eclipse Foundation
+ * Copyright (c) 2021, 2026 Contributors to the Eclipse Foundation
* Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -19,11 +19,6 @@
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.Servers;
-import com.sun.enterprise.ee.cms.core.CallBack;
-import com.sun.enterprise.ee.cms.core.DistributedStateCache;
-import com.sun.enterprise.ee.cms.core.FailureRecoverySignal;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
-import com.sun.enterprise.ee.cms.core.Signal;
import com.sun.enterprise.transaction.api.ResourceRecoveryManager;
import com.sun.enterprise.transaction.jts.api.DelegatedTransactionRecoveryFence;
import com.sun.jts.CosTransactions.Configuration;
@@ -38,6 +33,11 @@
import org.glassfish.gms.bootstrap.GMSAdapter;
import org.glassfish.gms.bootstrap.GMSAdapterService;
import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.shoal.gms.api.core.CallBack;
+import org.glassfish.shoal.gms.api.core.DistributedStateCache;
+import org.glassfish.shoal.gms.api.core.FailureRecoverySignal;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
+import org.glassfish.shoal.gms.api.core.Signal;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
diff --git a/docs/administration-guide/src/main/asciidoc/http_https.adoc b/docs/administration-guide/src/main/asciidoc/http_https.adoc
index 65ec335442c..129d4f1bca0 100644
--- a/docs/administration-guide/src/main/asciidoc/http_https.adoc
+++ b/docs/administration-guide/src/main/asciidoc/http_https.adoc
@@ -190,6 +190,13 @@ xref:reference-manual.adoc#create-threadpool[`create-threadpool`] subcommand.
To avoid using a thread pool, or to use the built-in `http-thread-pool`
thread pool, skip this step.
For additional thread pool information, see xref:threadpools.adoc#administering-thread-pools[Administering Thread Pools].
++
+To enable virtual threads, set the thread pool class name:
++
+[source]
+----
+asadmin> set server.thread-pools.thread-pool.thread-pool-name.classname=org.glassfish.grizzly.threadpool.VirtualThreadExecutorService
+----
6. Create an HTTP listener by using the
xref:reference-manual.adoc#create-network-listener[`create-network-listener`] subcommand.
Specify a protocol and transport, optionally a thread pool.
diff --git a/docs/administration-guide/src/main/asciidoc/threadpools.adoc b/docs/administration-guide/src/main/asciidoc/threadpools.adoc
index dd056763761..ad0395de4b3 100644
--- a/docs/administration-guide/src/main/asciidoc/threadpools.adoc
+++ b/docs/administration-guide/src/main/asciidoc/threadpools.adoc
@@ -18,6 +18,7 @@ The following topics are addressed here:
* <>
* <>
+* <>
Instructions for accomplishing these tasks by using the Administration
Console are contained in the Administration Console online help.
@@ -214,4 +215,50 @@ See Also
You can also view the full syntax and options of the subcommand by
typing `asadmin help delete-threadpool` at the command line.
+[[using-virtual-threads]]
+
+=== Using Virtual Threads
+
+{productName} supports virtual threads for HTTP request processing, providing improved scalability for high-concurrency applications.
+
+[[configuring-virtual-threads]]
+
+==== Configuring Virtual Threads
+
+To enable virtual threads for an HTTP thread pool, set the thread pool's class name to the virtual thread executor service:
+
+[source]
+----
+asadmin> set server.thread-pools.thread-pool.http-thread-pool.classname=org.glassfish.grizzly.threadpool.VirtualThreadExecutorService
+Command set executed successfully
+----
+
+To revert to platform threads, set the class name back to the default:
+
+[source]
+----
+asadmin> set server.thread-pools.thread-pool.http-thread-pool.classname=org.glassfish.grizzly.threadpool.GrizzlyExecutorService
+Command set executed successfully
+----
+
+[[virtual-thread-behavior]]
+
+==== Virtual Thread Behavior
+
+When virtual threads are enabled:
+
+* A new virtual thread is created for each HTTP request and destroyed when the request completes
+* Maximum parallel requests equals the sum of `max-thread-pool-size` and `max-queue-size`
+* The `min-thread-pool-size` and `idle-timeout` parameters are ignored
+* Configuration changes apply immediately without requiring a server restart
+
+For optimal performance with virtual threads, set high limits:
+
+[source]
+----
+asadmin> set server.thread-pools.thread-pool.http-thread-pool.max-thread-pool-size=10000
+asadmin> set server.thread-pools.thread-pool.http-thread-pool.max-queue-size=10000
+Command set executed successfully
+----
+
diff --git a/docs/performance-tuning-guide/src/main/asciidoc/tuning-glassfish.adoc b/docs/performance-tuning-guide/src/main/asciidoc/tuning-glassfish.adoc
index e11765c902a..fa02362bbc6 100644
--- a/docs/performance-tuning-guide/src/main/asciidoc/tuning-glassfish.adoc
+++ b/docs/performance-tuning-guide/src/main/asciidoc/tuning-glassfish.adoc
@@ -1176,6 +1176,10 @@ processing new requests until the number of active requests drops below
the maximum amount. Increasing this value will reduce HTTP response
latency times.
+When using virtual threads, consider much higher
+values (10,000 or more) as virtual threads have significantly lower
+overhead than platform threads.
+
In practice, clients frequently connect to the server and then do not
complete their requests. In these cases, the server waits a length of
time specified by the Timeout parameter.
diff --git a/docs/reference-manual/src/main/asciidoc/create-threadpool.adoc b/docs/reference-manual/src/main/asciidoc/create-threadpool.adoc
index 9da27e93a5a..59b463c1a81 100644
--- a/docs/reference-manual/src/main/asciidoc/create-threadpool.adoc
+++ b/docs/reference-manual/src/main/asciidoc/create-threadpool.adoc
@@ -22,7 +22,8 @@ asadmin [asadmin-options] create-threadpool [--help]
[--maxthreadpoolsize maxthreadpoolsize]
[--minthreadpoolsize minthreadpoolsize]
[--idletimeout idletimeout] [--maxqueuesize maxqueuesize]
-[--workqueues workqueues] threadpool-id
+[--workqueues workqueues] [--classname classname]
+[--virtual virtual] threadpool-id
----
=== Description
@@ -75,6 +76,16 @@ asadmin-options::
with earlier releases. If you specify this option, a syntax error does
not occur. Instead, the subcommand runs successfully and displays a
warning message that the option is ignored.
+`--classname`::
+ Specifies the fully qualified class name of a custom thread pool implementation.
+ If not specified, the default thread pool implementation will be used.
+`--virtual`::
+ Specifies whether to use virtual threads for the thread pool. When set to
+ `true`, the thread pool will use virtual threads. When set to `false` (default),
+ the thread pool will use platform threads. This setting applies when using the
+ default thread pool implementation (when classname is not specified or is set to
+ the default value). When a custom classname is specified, this setting is ignored.
+ Default is `false`.
=== Operands
@@ -85,9 +96,9 @@ threadpool-id::
[[sthref558]]
-==== Example 1 Creating a Thread Pool
+==== Example 1 Creating a Thread Pool
-This command creates a new thread pool called `threadpool-l`.
+This command creates a new thread pool called `threadpool-l` that uses platform threads (the default).
[source]
----
@@ -96,6 +107,32 @@ asadmin> create-threadpool --maxthreadpoolsize 100
Command create-threadpool executed successfully
----
+[[sthref559]]
+
+==== Example 2 Creating a Thread Pool with Virtual Threads Enabled
+
+This command creates a new thread pool called `threadpool-2` that uses virtual threads.
+
+[source]
+----
+asadmin> create-threadpool --maxthreadpoolsize 50
+--minthreadpoolsize 10 --virtual true threadpool-2
+Command create-threadpool executed successfully
+----
+
+[[sthref560]]
+
+==== Example 3 Creating a Thread Pool with Custom Implementation
+
+This command creates a new thread pool called `threadpool-3` with a custom thread pool implementation.
+
+[source]
+----
+asadmin> create-threadpool --maxthreadpoolsize 75
+--classname com.example.CustomThreadPool threadpool-3
+Command create-threadpool executed successfully
+----
+
=== Exit Status
0::
@@ -109,5 +146,3 @@ xref:asadmin.adoc#asadmin[`asadmin`(1M)]
xref:delete-threadpool.adoc#delete-threadpool[`delete-threadpool`(1)],
xref:list-threadpools.adoc#list-threadpools[`list-threadpools`(1)]
-
-
diff --git a/nucleus/admin/template/src/main/resources/config/logging.properties b/nucleus/admin/template/src/main/resources/config/logging.properties
index ddebea8256e..7c67a6ec8c0 100644
--- a/nucleus/admin/template/src/main/resources/config/logging.properties
+++ b/nucleus/admin/template/src/main/resources/config/logging.properties
@@ -218,6 +218,7 @@ org.glassfish.naming.level=INFO
org.glassfish.persistence.level=INFO
org.glassfish.resourcebase.level=INFO
org.glassfish.security.level=INFO
+org.glassfish.shoal.level=INFO
org.glassfish.soteria.level=INFO
org.glassfish.wasp.level=INFO
org.glassfish.wasp.compiler.level=INFO
@@ -231,7 +232,6 @@ org.jvnet.hk2.level=INFO
org.jvnet.hk2.osgiadapter.level=WARNING
org.jvnet.mimepull.level=INFO
-ShoalLogger.level=INFO
sun.level=INFO
diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/ValidateMulticastCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/ValidateMulticastCommand.java
index 0ed4426b266..eff954186fd 100644
--- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/ValidateMulticastCommand.java
+++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/ValidateMulticastCommand.java
@@ -17,7 +17,6 @@
package com.sun.enterprise.admin.cli.cluster;
import com.sun.enterprise.admin.cli.CLICommand;
-import com.sun.enterprise.gms.tools.MulticastTester;
import java.util.ArrayList;
import java.util.List;
@@ -25,6 +24,7 @@
import org.glassfish.api.Param;
import org.glassfish.api.admin.CommandException;
import org.glassfish.hk2.api.PerLookup;
+import org.glassfish.shoal.gms.tools.MulticastTester;
import org.jvnet.hk2.annotations.Service;
/**
diff --git a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/GMSAdapterImpl.java b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/GMSAdapterImpl.java
index 58367d9d23e..7e831a7000a 100644
--- a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/GMSAdapterImpl.java
+++ b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/GMSAdapterImpl.java
@@ -26,34 +26,6 @@
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerRef;
import com.sun.enterprise.config.serverbeans.Servers;
-import com.sun.enterprise.ee.cms.core.AliveAndReadySignal;
-import com.sun.enterprise.ee.cms.core.AliveAndReadyView;
-import com.sun.enterprise.ee.cms.core.CallBack;
-import com.sun.enterprise.ee.cms.core.FailureNotificationActionFactory;
-import com.sun.enterprise.ee.cms.core.FailureNotificationSignal;
-import com.sun.enterprise.ee.cms.core.FailureRecoverySignal;
-import com.sun.enterprise.ee.cms.core.FailureSuspectedActionFactory;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
-import com.sun.enterprise.ee.cms.core.GMSException;
-import com.sun.enterprise.ee.cms.core.GMSFactory;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
-import com.sun.enterprise.ee.cms.core.JoinNotificationActionFactory;
-import com.sun.enterprise.ee.cms.core.JoinedAndReadyNotificationActionFactory;
-import com.sun.enterprise.ee.cms.core.JoinedAndReadyNotificationSignal;
-import com.sun.enterprise.ee.cms.core.PlannedShutdownActionFactory;
-import com.sun.enterprise.ee.cms.core.PlannedShutdownSignal;
-import com.sun.enterprise.ee.cms.core.ServiceProviderConfigurationKeys;
-import com.sun.enterprise.ee.cms.core.Signal;
-import com.sun.enterprise.ee.cms.impl.client.FailureNotificationActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.FailureRecoveryActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.FailureSuspectedActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.GroupLeadershipNotificationActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.JoinNotificationActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.JoinedAndReadyNotificationActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.MessageActionFactoryImpl;
-import com.sun.enterprise.ee.cms.impl.client.PlannedShutdownActionFactoryImpl;
-import com.sun.enterprise.mgmt.transport.NetworkUtility;
-import com.sun.enterprise.mgmt.transport.grizzly.GrizzlyConfigConstants;
import com.sun.enterprise.util.io.ServerDirs;
import jakarta.inject.Inject;
@@ -83,6 +55,34 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.AliveAndReadySignal;
+import org.glassfish.shoal.gms.api.core.AliveAndReadyView;
+import org.glassfish.shoal.gms.api.core.CallBack;
+import org.glassfish.shoal.gms.api.core.FailureNotificationActionFactory;
+import org.glassfish.shoal.gms.api.core.FailureNotificationSignal;
+import org.glassfish.shoal.gms.api.core.FailureRecoverySignal;
+import org.glassfish.shoal.gms.api.core.FailureSuspectedActionFactory;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
+import org.glassfish.shoal.gms.api.core.GMSException;
+import org.glassfish.shoal.gms.api.core.GMSFactory;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
+import org.glassfish.shoal.gms.api.core.JoinNotificationActionFactory;
+import org.glassfish.shoal.gms.api.core.JoinedAndReadyNotificationActionFactory;
+import org.glassfish.shoal.gms.api.core.JoinedAndReadyNotificationSignal;
+import org.glassfish.shoal.gms.api.core.PlannedShutdownActionFactory;
+import org.glassfish.shoal.gms.api.core.PlannedShutdownSignal;
+import org.glassfish.shoal.gms.api.core.ServiceProviderConfigurationKeys;
+import org.glassfish.shoal.gms.api.core.Signal;
+import org.glassfish.shoal.gms.client.FailureNotificationActionFactoryImpl;
+import org.glassfish.shoal.gms.client.FailureRecoveryActionFactoryImpl;
+import org.glassfish.shoal.gms.client.FailureSuspectedActionFactoryImpl;
+import org.glassfish.shoal.gms.client.GroupLeadershipNotificationActionFactoryImpl;
+import org.glassfish.shoal.gms.client.JoinNotificationActionFactoryImpl;
+import org.glassfish.shoal.gms.client.JoinedAndReadyNotificationActionFactoryImpl;
+import org.glassfish.shoal.gms.client.MessageActionFactoryImpl;
+import org.glassfish.shoal.gms.client.PlannedShutdownActionFactoryImpl;
+import org.glassfish.shoal.gms.mgmt.transport.NetworkUtility;
+import org.glassfish.shoal.gms.mgmt.transport.grizzly.GrizzlyConfigConstants;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.Dom;
import org.jvnet.hk2.config.types.Property;
diff --git a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStartClusterCommand.java b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStartClusterCommand.java
index a064d3f5a9b..7c75ad00ec8 100644
--- a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStartClusterCommand.java
+++ b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStartClusterCommand.java
@@ -17,7 +17,6 @@
package org.glassfish.gms.admin;
import com.sun.enterprise.config.serverbeans.Domain;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
import jakarta.inject.Inject;
@@ -42,6 +41,7 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
import org.jvnet.hk2.annotations.Service;
diff --git a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStopClusterCommand.java b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStopClusterCommand.java
index 32722d4a012..f2c3e461418 100644
--- a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStopClusterCommand.java
+++ b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceAfterStopClusterCommand.java
@@ -17,7 +17,6 @@
package org.glassfish.gms.admin;
import com.sun.enterprise.config.serverbeans.Domain;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
import java.util.logging.Logger;
@@ -34,6 +33,7 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
import org.jvnet.hk2.annotations.Service;
diff --git a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStartClusterCommand.java b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStartClusterCommand.java
index 03dcb1a4e08..3e637154914 100644
--- a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStartClusterCommand.java
+++ b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStartClusterCommand.java
@@ -19,8 +19,6 @@
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Server;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
import jakarta.inject.Inject;
@@ -47,6 +45,8 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
import org.jvnet.hk2.annotations.Service;
diff --git a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStopClusterCommand.java b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStopClusterCommand.java
index 2b0bcc79011..5c932fe946b 100644
--- a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStopClusterCommand.java
+++ b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceBeforeStopClusterCommand.java
@@ -19,8 +19,6 @@
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Server;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
import jakarta.inject.Inject;
@@ -45,6 +43,8 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
import org.jvnet.hk2.annotations.Service;
diff --git a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceSupplementalInfo.java b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceSupplementalInfo.java
index 000d60150ac..1f4103d607e 100644
--- a/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceSupplementalInfo.java
+++ b/nucleus/cluster/gms-adapter/src/main/java/org/glassfish/gms/admin/GMSAnnounceSupplementalInfo.java
@@ -16,11 +16,10 @@
package org.glassfish.gms.admin;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
-
import java.util.List;
import org.glassfish.gms.bootstrap.GMSAdapter;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
class GMSAnnounceSupplementalInfo {
final public List clusterMembers;
diff --git a/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapter.java b/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapter.java
index 51ab2379588..93a8693470d 100644
--- a/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapter.java
+++ b/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapter.java
@@ -17,9 +17,8 @@
package org.glassfish.gms.bootstrap;
-import com.sun.enterprise.ee.cms.core.CallBack;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
-
+import org.glassfish.shoal.gms.api.core.CallBack;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
import org.jvnet.hk2.annotations.Contract;
/**
diff --git a/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapterService.java b/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapterService.java
index d7a8d341ad7..6bb8bfbf257 100644
--- a/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapterService.java
+++ b/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/GMSAdapterService.java
@@ -20,8 +20,6 @@
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.Clusters;
import com.sun.enterprise.config.serverbeans.Server;
-import com.sun.enterprise.ee.cms.core.GMSConstants;
-import com.sun.enterprise.ee.cms.core.GroupManagementService;
import com.sun.enterprise.module.bootstrap.StartupContext;
import com.sun.enterprise.util.i18n.StringManager;
@@ -46,6 +44,8 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.GMSConstants;
+import org.glassfish.shoal.gms.api.core.GroupManagementService;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.Changed;
import org.jvnet.hk2.config.ConfigBeanProxy;
diff --git a/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/HealthHistory.java b/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/HealthHistory.java
index 5eec2510d9f..076c1cebd12 100644
--- a/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/HealthHistory.java
+++ b/nucleus/cluster/gms-bootstrap/src/main/java/org/glassfish/gms/bootstrap/HealthHistory.java
@@ -19,12 +19,6 @@
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerRef;
-import com.sun.enterprise.ee.cms.core.FailureNotificationSignal;
-import com.sun.enterprise.ee.cms.core.JoinNotificationSignal;
-import com.sun.enterprise.ee.cms.core.JoinedAndReadyNotificationSignal;
-import com.sun.enterprise.ee.cms.core.PlannedShutdownSignal;
-import com.sun.enterprise.ee.cms.core.RejoinSubevent;
-import com.sun.enterprise.ee.cms.core.Signal;
import com.sun.enterprise.util.i18n.StringManager;
import java.beans.PropertyChangeEvent;
@@ -41,6 +35,12 @@
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
+import org.glassfish.shoal.gms.api.core.FailureNotificationSignal;
+import org.glassfish.shoal.gms.api.core.JoinNotificationSignal;
+import org.glassfish.shoal.gms.api.core.JoinedAndReadyNotificationSignal;
+import org.glassfish.shoal.gms.api.core.PlannedShutdownSignal;
+import org.glassfish.shoal.gms.api.core.RejoinSubevent;
+import org.glassfish.shoal.gms.api.core.Signal;
import org.jvnet.hk2.config.ConfigListener;
import org.jvnet.hk2.config.UnprocessedChangeEvents;
diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/commands/CreateThreadpool.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/commands/CreateThreadpool.java
index e4ab1c04f33..07f8322476f 100644
--- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/commands/CreateThreadpool.java
+++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/commands/CreateThreadpool.java
@@ -83,6 +83,12 @@ public class CreateThreadpool implements AdminCommand, AdminCommandSecurity.Prea
@Param(name = "target", optional = true, defaultValue = SystemPropertyConstants.DAS_SERVER_NAME)
String target;
+ @Param(name="classname", optional=true)
+ String poolClassName;
+
+ @Param(name="virtual", optional=true, defaultValue = "false")
+ boolean useVirtualThreads;
+
@Param(name="threadpool_id", primary=true)
String threadpool_id;
@@ -138,6 +144,11 @@ public Object run(ThreadPools param) throws PropertyVetoException, TransactionFa
newPool.setMinThreadPoolSize(minthreadpoolsize);
newPool.setMaxQueueSize(maxQueueSize);
newPool.setIdleThreadTimeoutSeconds(idletimeout);
+ if (poolClassName != null) {
+ newPool.setClassname(poolClassName);
+ } else if (useVirtualThreads) {
+ newPool.setVirtual(Boolean.TRUE.toString());
+ }
param.getThreadPool().add(newPool);
return newPool;
}
diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/services/impl/monitor/ThreadPoolMonitor.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/services/impl/monitor/ThreadPoolMonitor.java
index 3a26367be4a..b435873f694 100644
--- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/services/impl/monitor/ThreadPoolMonitor.java
+++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/services/impl/monitor/ThreadPoolMonitor.java
@@ -1,4 +1,5 @@
/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation.
* Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -20,8 +21,8 @@
import com.sun.enterprise.v3.services.impl.monitor.stats.ThreadPoolStats;
import com.sun.enterprise.v3.services.impl.monitor.stats.ThreadPoolStatsProvider;
-import org.glassfish.grizzly.threadpool.AbstractThreadPool;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
+import org.glassfish.grizzly.threadpool.ThreadPoolInfo;
import org.glassfish.grizzly.threadpool.ThreadPoolProbe;
/**
@@ -57,15 +58,15 @@ public ThreadPoolMonitor(GrizzlyMonitoring grizzlyMonitoring,
}
@Override
- public void onThreadPoolStartEvent(AbstractThreadPool threadPool) {
+ public void onThreadPoolStartEvent(ThreadPoolInfo threadPool) {
}
@Override
- public void onThreadPoolStopEvent(AbstractThreadPool threadPool) {
+ public void onThreadPoolStopEvent(ThreadPoolInfo threadPool) {
}
@Override
- public void onThreadAllocateEvent(AbstractThreadPool threadPool, Thread thread) {
+ public void onThreadAllocateEvent(ThreadPoolInfo threadPool, Thread thread) {
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getThreadPoolProbeProvider().threadAllocatedEvent(
monitoringId, threadPool.getConfig().getPoolName(),
@@ -76,7 +77,7 @@ public void onThreadAllocateEvent(AbstractThreadPool threadPool, Thread thread)
}
@Override
- public void onThreadReleaseEvent(AbstractThreadPool threadPool, Thread thread) {
+ public void onThreadReleaseEvent(ThreadPoolInfo threadPool, Thread thread) {
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getThreadPoolProbeProvider().threadReleasedEvent(
monitoringId, threadPool.getConfig().getPoolName(),
@@ -87,7 +88,7 @@ public void onThreadReleaseEvent(AbstractThreadPool threadPool, Thread thread) {
}
@Override
- public void onMaxNumberOfThreadsEvent(AbstractThreadPool threadPool, int maxNumberOfThreads) {
+ public void onMaxNumberOfThreadsEvent(ThreadPoolInfo threadPool, int maxNumberOfThreads) {
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getThreadPoolProbeProvider().maxNumberOfThreadsReachedEvent(
monitoringId, threadPool.getConfig().getPoolName(),
@@ -98,7 +99,7 @@ public void onMaxNumberOfThreadsEvent(AbstractThreadPool threadPool, int maxNumb
}
@Override
- public void onTaskDequeueEvent(AbstractThreadPool threadPool, Runnable task) {
+ public void onTaskDequeueEvent(ThreadPoolInfo threadPool, Runnable task) {
long currentBusyThreadCount = stats.currentBusyThreadCount.incrementAndGet();
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getThreadPoolProbeProvider().threadDispatchedFromPoolEvent(
@@ -113,7 +114,7 @@ public void onTaskDequeueEvent(AbstractThreadPool threadPool, Runnable task) {
}
@Override
- public void onTaskCancelEvent(AbstractThreadPool threadPool, Runnable task) {
+ public void onTaskCancelEvent(ThreadPoolInfo threadPool, Runnable task) {
long currentBusyThreadCount = stats.currentBusyThreadCount.decrementAndGet();
stats.currentThreadCount = threadPool.getSize();
// when dequeued task is cancelled - we have to "return" the thread, that
@@ -128,7 +129,7 @@ public void onTaskCancelEvent(AbstractThreadPool threadPool, Runnable task) {
}
@Override
- public void onTaskCompleteEvent(AbstractThreadPool threadPool, Runnable task) {
+ public void onTaskCompleteEvent(ThreadPoolInfo threadPool, Runnable task) {
long currentBusyThreadCount = stats.currentBusyThreadCount.decrementAndGet();
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getThreadPoolProbeProvider().threadReturnedToPoolEvent(
@@ -141,7 +142,7 @@ public void onTaskCompleteEvent(AbstractThreadPool threadPool, Runnable task) {
}
@Override
- public void onTaskQueueEvent(AbstractThreadPool threadPool, Runnable task) {
+ public void onTaskQueueEvent(ThreadPoolInfo threadPool, Runnable task) {
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getConnectionQueueProbeProvider().onTaskQueuedEvent(
monitoringId, task.getClass().getName());
@@ -151,7 +152,7 @@ public void onTaskQueueEvent(AbstractThreadPool threadPool, Runnable task) {
}
@Override
- public void onTaskQueueOverflowEvent(AbstractThreadPool threadPool) {
+ public void onTaskQueueOverflowEvent(ThreadPoolInfo threadPool) {
stats.currentThreadCount = threadPool.getSize();
grizzlyMonitoring.getConnectionQueueProbeProvider().onTaskQueueOverflowEvent(
monitoringId);
diff --git a/nucleus/core/kernel/src/main/manpages/com/sun/enterprise/v3/admin/commands/create-threadpool.1 b/nucleus/core/kernel/src/main/manpages/com/sun/enterprise/v3/admin/commands/create-threadpool.1
index a0edd569246..431f6113840 100644
--- a/nucleus/core/kernel/src/main/manpages/com/sun/enterprise/v3/admin/commands/create-threadpool.1
+++ b/nucleus/core/kernel/src/main/manpages/com/sun/enterprise/v3/admin/commands/create-threadpool.1
@@ -8,7 +8,8 @@ SYNOPSIS
[--maxthreadpoolsize maxthreadpoolsize]
[--minthreadpoolsize minthreadpoolsize]
[--idletimeout idletimeout] [--maxqueuesize maxqueuesize]
- [--workqueues workqueues] threadpool-id
+ [--workqueues workqueues] [--classname classname]
+ [--virtual virtual] threadpool-id
DESCRIPTION
The create-threadpool subcommand creates a thread pool with the
@@ -67,18 +68,51 @@ OPTIONS
successfully and displays a warning message that the option is
ignored.
+ --classname
+ Specifies the fully qualified class name of a custom thread pool
+ implementation. If not specified and virtual threads are enabled,
+ the default virtual thread pool implementation will be used. If not
+ specified and virtual threads are disabled, the default platform
+ thread pool implementation will be used.
+
+ --virtual
+ Specifies whether to use virtual threads for the thread pool. When
+ set to true, the thread pool will use virtual threads. When set to
+ false (default), the thread pool will use platform threads. This
+ setting applies when using the default thread pool implementation
+ (when classname is not specified or is set to the default value).
+ When a custom classname is specified, this setting is ignored.
+ Default is false.
+
OPERANDS
threadpool-id
An ID for the work queue, for example, threadpool-1.
EXAMPLES
Example 1, Creating a Thread Pool
- This command creates a new thread pool called threadpool-l.
+ This command creates a new thread pool called threadpool-l that
+ uses platform threads (the default).
asadmin> create-threadpool --maxthreadpoolsize 100
--minthreadpoolsize 20 --idletimeout 2 threadpool-1
Command create-threadpool executed successfully
+ Example 2, Creating a Thread Pool with Virtual Threads Enabled
+ This command creates a new thread pool called threadpool-2 that
+ uses virtual threads.
+
+ asadmin> create-threadpool --maxthreadpoolsize 50
+ --minthreadpoolsize 10 --virtual true threadpool-2
+ Command create-threadpool executed successfully
+
+ Example 3, Creating a Thread Pool with Custom Implementation
+ This command creates a new thread pool called threadpool-3 with a
+ custom thread pool implementation.
+
+ asadmin> create-threadpool --maxthreadpoolsize 75
+ --classname com.example.CustomThreadPool threadpool-3
+ Command create-threadpool executed successfully
+
EXIT STATUS
0
subcommand executed successfully
@@ -91,4 +125,4 @@ SEE ALSO
asadmin(1M)
-Jakarta EE 10 29 Nov 2010 create-threadpool(1)
+Jakarta EE 11 01 Jan 2026 create-threadpool(1)
diff --git a/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/GenericGrizzlyListener.java b/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/GenericGrizzlyListener.java
index d4d099abd2d..1ab95dd2d13 100644
--- a/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/GenericGrizzlyListener.java
+++ b/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/GenericGrizzlyListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2024 Contributors to the Eclipse Foundation.
+ * Copyright (c) 2021, 2025 Contributors to the Eclipse Foundation.
* Copyright (c) 2007, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -91,6 +91,7 @@
import org.glassfish.grizzly.threadpool.DefaultWorkerThread;
import org.glassfish.grizzly.threadpool.GrizzlyExecutorService;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
+import org.glassfish.grizzly.threadpool.VirtualThreadExecutorService;
import org.glassfish.grizzly.utils.DelayedExecutor;
import org.glassfish.grizzly.utils.IdleTimeoutFilter;
import org.glassfish.hk2.api.ServiceLocator;
@@ -565,48 +566,75 @@ protected void configureThreadPool(final ServiceLocator locator,
final ThreadPool threadPool) {
final String classname = threadPool.getClassname();
+ ExecutorService result = null;
+ final Boolean virtualThreads = Boolean.valueOf(threadPool.getVirtual());
+
if (classname != null &&
!ThreadPool.DEFAULT_THREAD_POOL_CLASS_NAME.equals(classname)) {
- // Use custom thread pool
- try {
- final ExecutorService customThreadPool =
- Utils.newInstance(locator,
- ExecutorService.class, classname, classname);
-
- if (customThreadPool != null) {
- if (!configureElement(locator, networkListener,
- threadPool, customThreadPool)) {
- LOGGER.log(Level.INFO,
- "The ThreadPool configuration bean can not be "
- + "passed to the custom thread-pool: {0}" +
- " instance, because it's not {1}.",
- new Object[] {
- classname, ConfigAwareElement.class.getName()});
- }
-
- workerExecutorService = customThreadPool;
- transport.setWorkerThreadPool(customThreadPool);
- return;
- }
+ result = createCustomThreadPool(locator, classname, networkListener, threadPool);
+ }
- LOGGER.log(Level.WARNING,
- "Can not initalize custom thread pool: {0}", classname);
+ if (result == null && virtualThreads) {
+ try {
+ // Use standard virtual threads Grizzly thread pool
+ result = VirtualThreadExecutorService.createInstance(
+ configureThreadPoolConfig(networkListener, threadPool));
+ } catch (NumberFormatException ex) {
+ LOGGER.log(Level.WARNING, "Invalid thread-pool attribute", ex);
+ } catch (Throwable ex) {
+ LOGGER.log(Level.WARNING, "Cannot use virtual threads, going to use platform threads", ex);
+ }
+ }
- } catch (Throwable t) {
- LOGGER.log(Level.WARNING,
- "Can not initalize custom thread pool: " + classname, t);
+ if (result == null) {
+ try {
+ // Use standard Grizzly thread pool
+ result = GrizzlyExecutorService.createInstance(
+ configureThreadPoolConfig(networkListener, threadPool));
+ } catch (NumberFormatException ex) {
+ LOGGER.log(Level.WARNING, "Invalid thread-pool attribute", ex);
}
}
+ if (result != null) {
+ workerExecutorService = result;
+ transport.setWorkerThreadPool(result);
+ } else {
+ LOGGER.log(Level.SEVERE, () -> "Could not configure a thread pool for HTTP listener " + networkListener.getName());
+ }
+ }
+
+ private ExecutorService createCustomThreadPool(final ServiceLocator locator, final String classname,
+ final NetworkListener networkListener, final ThreadPool threadPool) {
try {
- // Use standard Grizzly thread pool
- workerExecutorService = GrizzlyExecutorService.createInstance(
- configureThreadPoolConfig(networkListener, threadPool));
- transport.setWorkerThreadPool(workerExecutorService);
- } catch (NumberFormatException ex) {
- LOGGER.log(Level.WARNING, "Invalid thread-pool attribute", ex);
+ final ExecutorService customThreadPool =
+ Utils.newInstance(locator,
+ ExecutorService.class, classname, classname);
+
+ if (customThreadPool != null) {
+ if (!configureElement(locator, networkListener,
+ threadPool, customThreadPool)) {
+ LOGGER.log(Level.INFO,
+ "The ThreadPool configuration bean can not be "
+ + "passed to the custom thread-pool: {0}" +
+ " instance, because it's not {1}.",
+ new Object[] {
+ classname, ConfigAwareElement.class.getName()});
+ }
+ return customThreadPool;
+ }
+ LOGGER.log(Level.WARNING,
+ () -> couldNotInintializeCustomThreadPoolMessage(classname));
+ }catch (Throwable exception) {
+ LOGGER.log(Level.WARNING, exception,
+ () -> couldNotInintializeCustomThreadPoolMessage(classname));
}
+ return null;
+ }
+
+ private static String couldNotInintializeCustomThreadPoolMessage(String classname) {
+ return "Can not initalize custom thread pool: " + classname + ". Will use the default thread pool";
}
protected ThreadPoolConfig configureThreadPoolConfig(final NetworkListener networkListener,
diff --git a/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/dom/ThreadPool.java b/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/dom/ThreadPool.java
index 253d55011f8..7ca3863b262 100644
--- a/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/dom/ThreadPool.java
+++ b/nucleus/grizzly/config/src/main/java/org/glassfish/grizzly/config/dom/ThreadPool.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Contributors to the Eclipse Foundation
+ * Copyright (c) 2023, 2025 Contributors to the Eclipse Foundation
* Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
@@ -31,6 +31,7 @@
@Configured
public interface ThreadPool extends ConfigBeanProxy, PropertyBag {
+ // Used in annotations, must be constant expressions, not X.class.getName()
String DEFAULT_THREAD_POOL_CLASS_NAME = "org.glassfish.grizzly.threadpool.GrizzlyExecutorService";
int IDLE_THREAD_TIMEOUT = 900;
@@ -53,6 +54,14 @@ public interface ThreadPool extends ConfigBeanProxy, PropertyBag {
void setClassname(String classname);
+ /**
+ * Whether to use virtual threads for this thread pool.
+ */
+ @Attribute(defaultValue = "false", dataType = Boolean.class)
+ String getVirtual();
+
+ void setVirtual(String virtual);
+
/**
* Idle threads are removed from pool, after this time (in seconds).
*/
diff --git a/nucleus/grizzly/nucleus-grizzly-all/pom.xml b/nucleus/grizzly/nucleus-grizzly-all/pom.xml
index 058f9b3a25b..06814c7dd45 100644
--- a/nucleus/grizzly/nucleus-grizzly-all/pom.xml
+++ b/nucleus/grizzly/nucleus-grizzly-all/pom.xml
@@ -27,7 +27,6 @@
nucleus-grizzly-all
- jar
Nucleus Grizzly jars Combining
combining of all nucleus grizzly jars
diff --git a/nucleus/parent/pom.xml b/nucleus/parent/pom.xml
index 808b7a41fff..37606ab63fd 100644
--- a/nucleus/parent/pom.xml
+++ b/nucleus/parent/pom.xml
@@ -94,6 +94,27 @@
+
+
+ central
+ https://repo1.maven.org/maven2
+
+ fail
+
+
+
+ central-portal-snapshots
+ https://central.sonatype.com/repository/maven-snapshots
+
+ false
+
+
+ true
+ fail
+
+
+
+
6.0.1
@@ -110,7 +131,7 @@
4.0.2
- 4.0.4
+ 4.0.5
2.0.1.MR
@@ -126,7 +147,7 @@
4.0.0
- 4.0.0
+ 4.0.2
3.2.0
@@ -143,7 +164,7 @@
3.0.0
- 4.1.0-M1
+ 5.0.0
2.0.0
3.3.0
@@ -152,7 +173,7 @@
5.0.0
4.1.0
- 3.1.0
+ 4.0.0
3.1.13
1.10
true
@@ -385,7 +406,6 @@
-
@@ -396,7 +416,7 @@
org.osgi
- org.osgi.core
+ osgi.core
@@ -2112,7 +2132,7 @@
org.sonatype.central
central-publishing-maven-plugin
- 0.9.0
+ 0.10.0
true
${release.autopublish}
diff --git a/nucleus/pom.xml b/nucleus/pom.xml
index 3487c489e6f..a587a799815 100644
--- a/nucleus/pom.xml
+++ b/nucleus/pom.xml
@@ -111,27 +111,6 @@
-
-
- central
- https://repo1.maven.org/maven2
-
- fail
-
-
-
- sonatype-oss-snapshots
- https://central.sonatype.com/repository/maven-snapshots
-
- false
-
-
- true
- fail
-
-
-
-