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 - - - -