This is an automated email from the ASF dual-hosted git repository.

OpenPj pushed a commit to branch CONNECTORS-1784
in repository https://gitbox.apache.org/repos/asf/manifoldcf.git


The following commit(s) were added to refs/heads/CONNECTORS-1784 by this push:
     new 9cd56535c Introduced Virtual Threads again CONNECTORS-1784
9cd56535c is described below

commit 9cd56535c301e8622464e8db85c906934c184df4
Author: Piergiorgio Lucidi <[email protected]>
AuthorDate: Fri May 22 18:09:20 2026 +0200

    Introduced Virtual Threads again CONNECTORS-1784
---
 .github/workflows/create-release-candidate.yml     |  2 +-
 .github/workflows/license-check.yml                |  2 +-
 .github/workflows/publish-maven-release.yml        |  2 +-
 .github/workflows/publish-maven-snapshot.yml       |  2 +-
 .../output/cmisoutput/CmisOutputConnector.java     | 20 ++++----
 .../connectors/cmis/CmisRepositoryConnector.java   | 20 ++++----
 .../output/solr/ModifiedCloudSolrClient.java       | 10 ++--
 .../connectors/webcrawler/ThrottledFetcher.java    |  3 +-
 .../manifoldcf/agents/system/AgentsDaemon.java     |  4 +-
 .../authorityservlet/UserACLServlet.java           |  3 +-
 framework/build.xml                                | 42 ++++++++---------
 framework/buildfiles/connector-build.xml           | 22 ++++-----
 .../connectorcommon/common/CommonsHTTPSender.java  |  3 +-
 .../common/InterruptibleSocketFactory.java         | 55 ++++++++++------------
 .../jettyrunner/ManifoldCFCombinedJettyRunner.java | 10 +++-
 .../jettyrunner/ManifoldCFJettyRunner.java         | 10 +++-
 .../manifoldcf/crawler/system/CrawlerAgent.java    | 40 ++++++++--------
 .../crawler/tests/ManifoldCFInstance.java          | 11 ++++-
 pom.xml                                            | 10 ++--
 19 files changed, 145 insertions(+), 126 deletions(-)

diff --git a/.github/workflows/create-release-candidate.yml 
b/.github/workflows/create-release-candidate.yml
index baa25995f..8fe27fd3c 100644
--- a/.github/workflows/create-release-candidate.yml
+++ b/.github/workflows/create-release-candidate.yml
@@ -41,7 +41,7 @@ jobs:
       - name: Set up OpenJDK 21 Temurin x64
         uses: actions/[email protected]
         with:
-          java-version: '21'
+          java-version: '25'
           distribution: 'temurin'
           architecture: x64
           cache: maven
diff --git a/.github/workflows/license-check.yml 
b/.github/workflows/license-check.yml
index 7e74e4a49..adc08cfb3 100644
--- a/.github/workflows/license-check.yml
+++ b/.github/workflows/license-check.yml
@@ -31,7 +31,7 @@ jobs:
       - name: Set up OpenJDK 21 Temurin x64
         uses: actions/[email protected]
         with:
-          java-version: '21'
+          java-version: '25'
           distribution: 'temurin'
           architecture: x64
           cache: maven
diff --git a/.github/workflows/publish-maven-release.yml 
b/.github/workflows/publish-maven-release.yml
index 05fd1f012..c948c444e 100644
--- a/.github/workflows/publish-maven-release.yml
+++ b/.github/workflows/publish-maven-release.yml
@@ -75,7 +75,7 @@ jobs:
       - name: Set up Java
         uses: actions/[email protected]
         with:
-          java-version: '21'
+          java-version: '25'
           distribution: 'temurin'
           architecture: x64
           cache: maven
diff --git a/.github/workflows/publish-maven-snapshot.yml 
b/.github/workflows/publish-maven-snapshot.yml
index 42ac29499..d382d6bec 100644
--- a/.github/workflows/publish-maven-snapshot.yml
+++ b/.github/workflows/publish-maven-snapshot.yml
@@ -38,7 +38,7 @@ jobs:
       - name: Set up Java
         uses: actions/[email protected]
         with:
-          java-version: '21'
+          java-version: '25'
           distribution: 'temurin'
           architecture: x64
           cache: maven
diff --git 
a/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java
 
b/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java
index 5249b6b9b..de3c09aeb 100644
--- 
a/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java
+++ 
b/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java
@@ -305,12 +305,12 @@ public class CmisOutputConnector extends 
BaseOutputConnector {
   public void disconnect() throws ManifoldCFException {
     if (session != null) {
       DestroySessionThread t = new DestroySessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -446,12 +446,12 @@ public class CmisOutputConnector extends 
BaseOutputConnector {
 
       long currentTime;
       GetSessionThread t = new GetSessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -521,12 +521,12 @@ public class CmisOutputConnector extends 
BaseOutputConnector {
     long currentTime = System.currentTimeMillis();
     if (currentTime >= lastSessionFetch + timeToRelease) {
       DestroySessionThread t = new DestroySessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -567,12 +567,12 @@ public class CmisOutputConnector extends 
BaseOutputConnector {
       getSession();
       long currentTime;
       CheckConnectionThread t = new CheckConnectionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -625,12 +625,12 @@ public class CmisOutputConnector extends 
BaseOutputConnector {
     long currentTime = System.currentTimeMillis();
     if (currentTime >= lastSessionFetch + timeToRelease) {
       DestroySessionThread t = new DestroySessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
diff --git 
a/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java
 
b/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java
index 6fecec6df..3e2c21736 100644
--- 
a/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java
+++ 
b/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/cmis/CmisRepositoryConnector.java
@@ -294,12 +294,12 @@ public class CmisRepositoryConnector extends 
BaseRepositoryConnector {
   public void disconnect() throws ManifoldCFException {
     if (session != null) {
       DestroySessionThread t = new DestroySessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -428,12 +428,12 @@ public class CmisRepositoryConnector extends 
BaseRepositoryConnector {
 
       long currentTime;
       GetSessionThread t = new GetSessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -507,12 +507,12 @@ public class CmisRepositoryConnector extends 
BaseRepositoryConnector {
     long currentTime = System.currentTimeMillis();
     if (currentTime >= lastSessionFetch + timeToRelease) {
       DestroySessionThread t = new DestroySessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -559,12 +559,12 @@ public class CmisRepositoryConnector extends 
BaseRepositoryConnector {
       getSession();
       long currentTime;
       CheckConnectionThread t = new CheckConnectionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
@@ -621,12 +621,12 @@ public class CmisRepositoryConnector extends 
BaseRepositoryConnector {
     long currentTime = System.currentTimeMillis();
     if (currentTime >= lastSessionFetch + timeToRelease) {
       DestroySessionThread t = new DestroySessionThread();
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         StructuredTaskScope.Subtask<Void> subtask = scope.fork(() -> {
           t.run();
           return null;
         });
-        scope.join();
+        try { scope.join(); } 
catch(java.util.concurrent.StructuredTaskScope.FailedException e) {}
         if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED) {
           Throwable thr = subtask.exception();
           if (thr != null) {
diff --git 
a/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/ModifiedCloudSolrClient.java
 
b/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/ModifiedCloudSolrClient.java
index 717b35d33..0993f08b7 100644
--- 
a/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/ModifiedCloudSolrClient.java
+++ 
b/connectors/solr/connector/src/main/java/org/apache/manifoldcf/agents/output/solr/ModifiedCloudSolrClient.java
@@ -441,7 +441,7 @@ public abstract class ModifiedCloudSolrClient extends 
SolrClient {
     final long start = System.nanoTime();
 
     if (parallelUpdates) {
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
+      try (var scope = StructuredTaskScope.open()) {
         final Map<String, StructuredTaskScope.Subtask<NamedList<?>>> subtasks 
= new HashMap<>(routes.size());
         for (final Map.Entry<String, ? extends ModifiedLBSolrClient.Req> entry 
: routes.entrySet()) {
           final String url = entry.getKey();
@@ -456,14 +456,18 @@ public abstract class ModifiedCloudSolrClient extends 
SolrClient {
           }));
         }
 
-        scope.join();
+        try {
+          scope.join();
+        } catch (java.util.concurrent.StructuredTaskScope.FailedException e) {
+          // Exception caught, but we will iterate over subtasks to collect 
exceptions
+        }
         
         for (final Map.Entry<String, 
StructuredTaskScope.Subtask<NamedList<?>>> entry : subtasks.entrySet()) {
           final String url = entry.getKey();
           final StructuredTaskScope.Subtask<NamedList<?>> subtask = 
entry.getValue();
           if (subtask.state() == StructuredTaskScope.Subtask.State.SUCCESS) {
             shardResponses.add(url, subtask.get());
-          } else {
+          } else if (subtask.state() == 
StructuredTaskScope.Subtask.State.FAILED) {
             exceptions.add(url, subtask.exception());
           }
         }
diff --git 
a/connectors/webcrawler/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/webcrawler/ThrottledFetcher.java
 
b/connectors/webcrawler/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/webcrawler/ThrottledFetcher.java
index cd28dc0c9..30e07298f 100644
--- 
a/connectors/webcrawler/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/webcrawler/ThrottledFetcher.java
+++ 
b/connectors/webcrawler/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/webcrawler/ThrottledFetcher.java
@@ -700,8 +700,7 @@ public class ThrottledFetcher
       methodThread = new ExecuteMethodThread(this, fetchThrottler, httpClient, 
hostHost, fetchMethod, cookieStore);
       try
       {
-        methodThreadRef = new Thread(methodThread, "ExecuteMethod thread");
-        methodThreadRef.start();
+        methodThreadRef = Thread.ofVirtual().name("ExecuteMethod 
thread").start(methodThread);
         threadStarted = true;
         try
         {
diff --git 
a/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/AgentsDaemon.java
 
b/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/AgentsDaemon.java
index 199583874..f63ee6016 100644
--- 
a/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/AgentsDaemon.java
+++ 
b/framework/agents/src/main/java/org/apache/manifoldcf/agents/system/AgentsDaemon.java
@@ -143,8 +143,8 @@ public class AgentsDaemon
     throws ManifoldCFException
   {
     // Create idle cleanup thread.
-    idleCleanupThread = new IdleCleanupThread(processID);
-    agentsThread = new AgentsThread();
+    idleCleanupThread = Thread.ofVirtual().name("Idle cleanup 
thread").unstarted(new IdleCleanupThread(processID));
+    agentsThread = Thread.ofVirtual().name("Agents thread").unstarted(new 
AgentsThread());
     // Create and start agents thread.
     idleCleanupThread.start();
     agentsThread.start();
diff --git 
a/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
 
b/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
index be7b40f79..669a123e4 100644
--- 
a/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
+++ 
b/framework/authority-servlet/src/main/java/org/apache/manifoldcf/authorityservlet/UserACLServlet.java
@@ -295,7 +295,7 @@ public class UserACLServlet extends HttpServlet
       }
       
       // Use Structured Concurrency to run the tasks and ensure cleanup
-      try (var scope = new StructuredTaskScope.ShutdownOnFailure())
+      try (var scope = StructuredTaskScope.open())
       {
         for (MappingOrderThread mot : mappingThreads)
         {
@@ -312,7 +312,6 @@ public class UserACLServlet extends HttpServlet
           });
         }
         scope.join();
-        scope.throwIfFailed();
       }
       catch (Exception e)
       {
diff --git a/framework/build.xml b/framework/build.xml
index aaf5e4927..7ba803037 100644
--- a/framework/build.xml
+++ b/framework/build.xml
@@ -254,7 +254,7 @@
     
     <target name="doc">
         <mkdir dir="dist/doc"/>
-        <javadoc destdir="dist/doc" maxmemory="256M" source="21" 
useexternalfile="true" use="true" locale="en_US">
+        <javadoc destdir="dist/doc" maxmemory="256M" source="25" 
useexternalfile="true" use="true" locale="en_US">
             <link href="http://docs.oracle.com/javase/8/docs/api/"/>
             <link 
href="http://manifoldcf.apache.org/release/trunk/api/framework/"/>
             <classpath>
@@ -273,7 +273,7 @@
 
     <target name="compile-less-compiler">
         <mkdir dir="build/less-compiler/classes"/>
-        <javac srcdir="less-compiler/src/main/java" 
destdir="build/less-compiler/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="less-compiler/src/main/java" 
destdir="build/less-compiler/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="less-classpath"/>
             </classpath>
@@ -282,7 +282,7 @@
 
     <target name="compile-core">
         <mkdir dir="build/core/classes"/><native2ascii encoding="UTF-8" 
src="ui-core/src/main/native2ascii" dest="build/ui-core/classes" 
includes="**/*.properties" />
-        <javac srcdir="core/src/main/java" destdir="build/core/classes" 
deprecation="true" target="21" source="21" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
+        <javac srcdir="core/src/main/java" destdir="build/core/classes" 
deprecation="true" target="25" source="25" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
             </classpath>
@@ -292,7 +292,7 @@
 
     <target name="compile-ui-core" depends="compile-core">
         <mkdir dir="build/ui-core/classes"/>
-        <javac srcdir="ui-core/src/main/java" destdir="build/ui-core/classes" 
deprecation="true" target="21" source="21" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
+        <javac srcdir="ui-core/src/main/java" destdir="build/ui-core/classes" 
deprecation="true" target="25" source="25" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -303,7 +303,7 @@
 
     <target name="compile-agents" depends="compile-core">
         <mkdir dir="build/agents/classes"/>
-        <javac srcdir="agents/src/main/java" destdir="build/agents/classes" 
deprecation="true" target="21" source="21" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
+        <javac srcdir="agents/src/main/java" destdir="build/agents/classes" 
deprecation="true" target="25" source="25" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -316,7 +316,7 @@
         <copy todir="build/connector-common/classes">
             <fileset dir="connector-common/src/main/resources"/>
         </copy>
-        <javac srcdir="connector-common/src/main/java" 
destdir="build/connector-common/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="connector-common/src/main/java" 
destdir="build/connector-common/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <path refid="connector-common-classpath"/>
@@ -329,7 +329,7 @@
 
     <target name="compile-pull-agent" depends="compile-core,compile-agents">
         <mkdir dir="build/pull-agent/classes"/>
-        <javac srcdir="pull-agent/src/main/java" 
destdir="build/pull-agent/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="pull-agent/src/main/java" 
destdir="build/pull-agent/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -340,7 +340,7 @@
 
     <target name="compile-jetty-runner" depends="compile-core,compile-agents">
         <mkdir dir="build/jetty-runner/classes"/>
-        <javac srcdir="jetty-runner/src/main/java" 
destdir="build/jetty-runner/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="jetty-runner/src/main/java" 
destdir="build/jetty-runner/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -352,7 +352,7 @@
 
     <target name="compile-script-engine" depends="compile-core">
         <mkdir dir="build/script-engine/classes"/>
-        <javac srcdir="script-engine/src/main/java" 
destdir="build/script-engine/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="script-engine/src/main/java" 
destdir="build/script-engine/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -362,7 +362,7 @@
 
     <target name="compile-authority-servlet" 
depends="compile-core,compile-agents,compile-pull-agent">
         <mkdir dir="build/authority-servlet/classes"/>
-        <javac srcdir="authority-servlet/src/main/java" 
destdir="build/authority-servlet/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="authority-servlet/src/main/java" 
destdir="build/authority-servlet/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -374,7 +374,7 @@
 
     <target name="compile-authority-service" 
depends="compile-core,compile-agents,compile-pull-agent,compile-authority-servlet">
         <mkdir dir="build/authority-service/classes"/>
-        <javac srcdir="authority-service/src/main/java" 
destdir="build/authority-service/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="authority-service/src/main/java" 
destdir="build/authority-service/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -387,7 +387,7 @@
 
     <target name="compile-api-servlet" 
depends="compile-core,compile-ui-core,compile-agents,compile-pull-agent">
         <mkdir dir="build/api-servlet/classes"/>
-        <javac srcdir="api-servlet/src/main/java" 
destdir="build/api-servlet/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="api-servlet/src/main/java" 
destdir="build/api-servlet/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -400,7 +400,7 @@
 
     <target name="compile-api-service" 
depends="compile-core,compile-ui-core,compile-agents,compile-pull-agent,compile-api-servlet">
         <mkdir dir="build/api-service/classes"/>
-        <javac srcdir="api-service/src/main/java" 
destdir="build/api-service/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="api-service/src/main/java" 
destdir="build/api-service/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -414,7 +414,7 @@
 
     <target name="compile-combined-service" 
depends="compile-core,compile-ui-core,compile-agents,compile-pull-agent,compile-api-servlet,compile-authority-servlet">
         <mkdir dir="build/combined-service/classes"/>
-        <javac srcdir="combined-service/src/main/java" 
destdir="build/combined-service/classes" deprecation="true" target="21" 
source="21" encoding="utf-8" debug="true" debuglevel="lines,vars,source">
+        <javac srcdir="combined-service/src/main/java" 
destdir="build/combined-service/classes" deprecation="true" target="25" 
source="25" encoding="utf-8" debug="true" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -443,7 +443,7 @@
 
     <target name="compile-crawler-ui" 
depends="less-compiler-invocation,compile-core,compile-ui-core,compile-agents,compile-pull-agent">
         <mkdir dir="build/crawler-ui/classes"/>
-        <javac srcdir="crawler-ui/src/main/java" 
destdir="build/crawler-ui/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="crawler-ui/src/main/java" 
destdir="build/crawler-ui/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -474,7 +474,7 @@
         <jasper2 validateXml="false" uriroot="crawler-ui/src/main/webapp" 
webFragmentXml="build/crawler-ui/web-generated.xml" 
outputDir="build/crawler-ui/java" /> 
         <!-- Compile java classes -->
         <mkdir dir="build/crawler-ui/classes"/>
-        <javac srcdir="build/crawler-ui/java" 
destdir="build/crawler-ui/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="build/crawler-ui/java" 
destdir="build/crawler-ui/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath id="classpath">
                 <pathelement location="${java.home}/../lib/tools.jar"/>
                 <path refid="framework-classpath"/>
@@ -2106,7 +2106,7 @@
 
     <target name="compile-core-tests" depends="compile-core">
         <mkdir dir="build/core-tests/classes"/>
-        <javac srcdir="core/src/test/java" destdir="build/core-tests/classes" 
deprecation="true" target="21" source="21" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
+        <javac srcdir="core/src/test/java" destdir="build/core-tests/classes" 
deprecation="true" target="25" source="25" debug="true" encoding="utf-8" 
debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -2116,7 +2116,7 @@
 
     <target name="compile-connector-common-tests" 
depends="compile-connector-common">
         <mkdir dir="build/connector-common-tests/classes"/>
-        <javac srcdir="connector-common/src/test/java" 
destdir="build/connector-common-tests/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="connector-common/src/test/java" 
destdir="build/connector-common-tests/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -2128,7 +2128,7 @@
 
     <target name="compile-agents-tests" 
depends="compile-core-tests,compile-agents">
         <mkdir dir="build/agents-tests/classes"/>
-        <javac srcdir="agents/src/test/java" 
destdir="build/agents-tests/classes" deprecation="true" target="21" source="21" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="agents/src/test/java" 
destdir="build/agents-tests/classes" deprecation="true" target="25" source="25" 
debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -2140,7 +2140,7 @@
 
     <target name="compile-pull-agent-tests" 
depends="compile-agents-tests,compile-pull-agent">
         <mkdir dir="build/pull-agent-tests/classes"/>
-        <javac srcdir="pull-agent/src/test/java" 
destdir="build/pull-agent-tests/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="pull-agent/src/test/java" 
destdir="build/pull-agent-tests/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
@@ -2154,7 +2154,7 @@
 
     <target name="compile-script-engine-tests" 
depends="compile-core,compile-script-engine">
         <mkdir dir="build/script-engine-tests/classes"/>
-        <javac srcdir="script-engine/src/test/java" 
destdir="build/script-engine-tests/classes" deprecation="true" target="21" 
source="21" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
+        <javac srcdir="script-engine/src/test/java" 
destdir="build/script-engine-tests/classes" deprecation="true" target="25" 
source="25" debug="true" encoding="utf-8" debuglevel="lines,vars,source">
             <classpath>
                 <path refid="framework-classpath"/>
                 <pathelement location="build/core/classes"/>
diff --git a/framework/buildfiles/connector-build.xml 
b/framework/buildfiles/connector-build.xml
index b0b66d0e5..17674ad67 100644
--- a/framework/buildfiles/connector-build.xml
+++ b/framework/buildfiles/connector-build.xml
@@ -395,7 +395,7 @@
 
     <target name="compile-stubs" depends="build-stubs-check" if="buildStubs">
         <mkdir dir="build/stubclasses"/>
-        <javac srcdir="build-stub/src/main/java" destdir="build/stubclasses" 
deprecation="true" target="21" source="21" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="build-stub/src/main/java" destdir="build/stubclasses" 
deprecation="true" target="25" source="25" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
             </classpath>
         </javac>
@@ -569,7 +569,7 @@
 
     <target name="compile-wsdls" depends="has-wsdls-check" if="hasWSDLs">
         <mkdir dir="build/wsdlclasses"/>
-        <javac srcdir="build/wsdljava" destdir="build/wsdlclasses" 
deprecation="true" target="21" source="21" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="build/wsdljava" destdir="build/wsdlclasses" 
deprecation="true" target="25" source="25" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <!-- JDK 11 requirements -->
                 <fileset dir="${mcf-dist}/connector-common-lib">
@@ -601,7 +601,7 @@
 
     <target name="compile-xsds" depends="has-xsds-check" if="hasXSDs">
         <mkdir dir="build/xsdclasses"/>
-        <javac srcdir="build/xsdjava" destdir="build/xsdclasses" 
deprecation="true" target="21" source="21" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="build/xsdjava" destdir="build/xsdclasses" 
deprecation="true" target="25" source="25" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <fileset dir="${mcf-dist}/connector-common-lib">
                     <include name="castor*.jar"/>
@@ -630,7 +630,7 @@
 
     <target name="doc-rmi" depends="compile-wsdls,compile-xsds,has-RMI-check" 
if="hasRMI">
         <mkdir dir="dist/doc"/>
-        <javadoc destdir="dist/doc" source="21" use="true" locale="en_US">
+        <javadoc destdir="dist/doc" source="25" use="true" locale="en_US">
             <link href="http://docs.oracle.com/javase/8/docs/api/"/>
             <link 
href="http://manifoldcf.apache.org/release/trunk/api/framework/"/>
             <classpath>
@@ -643,7 +643,7 @@
 
     <target name="doc" 
depends="compile-stubs,doc-rmi,compile-wsdls,compile-xsds,has-RMI-check,precompile-check"
 if="canBuild" unless="hasRMI">
         <mkdir dir="dist/doc"/>
-        <javadoc destdir="dist/doc" source="21" use="true" locale="en_US">
+        <javadoc destdir="dist/doc" source="25" use="true" locale="en_US">
             <link href="http://docs.oracle.com/javase/8/docs/api/"/>
             <link 
href="http://manifoldcf.apache.org/release/trunk/api/framework/"/>
             <classpath>
@@ -682,7 +682,7 @@
     
     <target name="compile-server" 
depends="compile-interface,compile-implementation,compile-rmic,has-RMI-check" 
if="hasRMI">
         <mkdir dir="build/server/classes"/>
-        <javac srcdir="server/src/main/java" destdir="build/server/classes" 
deprecation="true" target="21" source="21" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="server/src/main/java" destdir="build/server/classes" 
deprecation="true" target="25" source="25" debug="true" 
debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <pathelement location="build/interface/classes"/>
                 <pathelement location="build/implementation/classes"/>
@@ -694,7 +694,7 @@
 
     <target name="compile-registry" depends="compile-interface,has-RMI-check" 
if="hasRMI">
         <mkdir dir="build/registry/classes"/>
-        <javac srcdir="registry/src/main/java" 
destdir="build/registry/classes" deprecation="true" target="21" source="21" 
debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="registry/src/main/java" 
destdir="build/registry/classes" deprecation="true" target="25" source="25" 
debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <pathelement location="build/interface/classes"/>
             </classpath>
@@ -703,7 +703,7 @@
 
     <target name="compile-connector" 
depends="compile-stubs,compile-connector-native2ascii,compile-connector-resources,compile-wsdls,compile-xsds,compile-interface,compile-rmic,precompile-check"
 if="canBuild">
         <mkdir dir="build/connector/classes"/>
-        <javac srcdir="connector/src/main/java" 
destdir="build/connector/classes" deprecation="true" target="21" source="21" 
debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="connector/src/main/java" 
destdir="build/connector/classes" deprecation="true" target="25" source="25" 
debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <path refid="connector-classpath"/>
             </classpath>
@@ -712,7 +712,7 @@
 
     <target name="compile-implementation" 
depends="compile-stubs,compile-interface,has-RMI-check" if="hasRMI">
         <mkdir dir="build/implementation/classes"/>
-        <javac srcdir="implementation/src/main/java" 
destdir="build/implementation/classes" deprecation="true" target="21" 
source="21" debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="implementation/src/main/java" 
destdir="build/implementation/classes" deprecation="true" target="25" 
source="25" debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <path refid="implementation-classpath"/>
             </classpath>
@@ -721,7 +721,7 @@
 
     <target name="compile-interface" depends="has-RMI-check" if="hasRMI">
         <mkdir dir="build/interface/classes"/>
-        <javac srcdir="interface/src/main/java" 
destdir="build/interface/classes" deprecation="true" target="21" source="21" 
debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="interface/src/main/java" 
destdir="build/interface/classes" deprecation="true" target="25" source="25" 
debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <path refid="interface-classpath"/>
             </classpath>
@@ -737,7 +737,7 @@
 
     <target name="compile-tests" 
depends="compile-connector,compile-test-resources,has-tests-check" 
if="hasTests">
         <mkdir dir="build/connector-tests/classes"/>
-        <javac srcdir="connector/src/test/java" 
destdir="build/connector-tests/classes" deprecation="true" target="21" 
source="21" debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
+        <javac srcdir="connector/src/test/java" 
destdir="build/connector-tests/classes" deprecation="true" target="25" 
source="25" debug="true" debuglevel="lines,vars,source" encoding="UTF-8">
             <classpath>
                 <path refid="connector-test-classpath"/>
             </classpath>
diff --git 
a/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/CommonsHTTPSender.java
 
b/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/CommonsHTTPSender.java
index e6aedbedb..0f61ba7e5 100644
--- 
a/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/CommonsHTTPSender.java
+++ 
b/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/CommonsHTTPSender.java
@@ -174,8 +174,7 @@ public class CommonsHTTPSender extends BasicHandler {
       //  HttpProtocolParams.setVersion(method.getParams(),new 
ProtocolVersion("HTTP",1,0));
 
       BackgroundHTTPThread methodThread = new 
BackgroundHTTPThread(httpClient,method);
-      Thread vThread = new Thread(methodThread, "HTTP request");
-      vThread.start();
+      Thread vThread = Thread.ofVirtual().name("HTTP 
request").start(methodThread);
       try
       {
         int returnCode = methodThread.getResponseCode();
diff --git 
a/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/InterruptibleSocketFactory.java
 
b/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/InterruptibleSocketFactory.java
index 9daf1fd2b..1ea067802 100644
--- 
a/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/InterruptibleSocketFactory.java
+++ 
b/framework/connector-common/src/main/java/org/apache/manifoldcf/connectorcommon/common/InterruptibleSocketFactory.java
@@ -99,7 +99,9 @@ public class InterruptibleSocketFactory extends 
javax.net.ssl.SSLSocketFactory
   protected Socket fireOffThread(InetAddress address, int port, InetAddress 
localHost, int localPort)
     throws IOException
   {
-    try (var scope = new StructuredTaskScope.ShutdownOnFailure())
+    try (var scope = StructuredTaskScope.open(
+            StructuredTaskScope.Joiner.<Socket>awaitAllSuccessfulOrThrow(),
+            config -> 
config.withTimeout(java.time.Duration.ofMillis(connectTimeoutMilliseconds))))
     {
       StructuredTaskScope.Subtask<Socket> subtask = scope.fork(() -> {
         if (localHost == null)
@@ -110,38 +112,29 @@ public class InterruptibleSocketFactory extends 
javax.net.ssl.SSLSocketFactory
 
       try
       {
-        scope.joinUntil(Instant.now().plusMillis(connectTimeoutMilliseconds));
-        
-        if (subtask.state() == StructuredTaskScope.Subtask.State.SUCCESS)
-        {
-          return subtask.get();
-        }
-        else if (subtask.state() == StructuredTaskScope.Subtask.State.FAILED)
-        {
-          Throwable t = subtask.exception();
-          if (t instanceof java.net.SocketTimeoutException)
-            throw (java.net.SocketTimeoutException)t;
-          else if (t instanceof ConnectTimeoutException)
-            throw (ConnectTimeoutException)t;
-          else if (t instanceof InterruptedIOException)
-            throw (InterruptedIOException)t;
-          else if (t instanceof IOException)
-            throw (IOException)t;
-          else if (t instanceof Error)
-            throw (Error)t;
-          else if (t instanceof RuntimeException)
-            throw (RuntimeException)t;
-          throw new Error("Received an unexpected exception: 
"+t.getMessage(),t);
-        }
-        else
-        {
-           // Should not happen after join
-           throw new IOException("Socket creation failed with unexpected 
state: " + subtask.state());
-        }
+        scope.join();
+        return subtask.get();
+      }
+      catch (java.util.concurrent.StructuredTaskScope.TimeoutException e)
+      {
+        throw new ConnectTimeoutException("Secure connection timed out: " + 
e.getMessage());
       }
-      catch (TimeoutException e)
+      catch (java.util.concurrent.StructuredTaskScope.FailedException e)
       {
-        throw new ConnectTimeoutException("Secure connection timed out");
+        Throwable t = e.getCause();
+        if (t instanceof java.net.SocketTimeoutException)
+          throw (java.net.SocketTimeoutException)t;
+        else if (t instanceof ConnectTimeoutException)
+          throw (ConnectTimeoutException)t;
+        else if (t instanceof InterruptedIOException)
+          throw (InterruptedIOException)t;
+        else if (t instanceof IOException)
+          throw (IOException)t;
+        else if (t instanceof Error)
+          throw (Error)t;
+        else if (t instanceof RuntimeException)
+          throw (RuntimeException)t;
+        throw new Error("Received an unexpected exception: "+t.getMessage(),t);
       }
       catch (InterruptedException e)
       {
diff --git 
a/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFCombinedJettyRunner.java
 
b/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFCombinedJettyRunner.java
index b6453a270..560e374c5 100644
--- 
a/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFCombinedJettyRunner.java
+++ 
b/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFCombinedJettyRunner.java
@@ -41,6 +41,9 @@ import org.eclipse.jetty.ee10.webapp.WebAppContext;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.handler.ShutdownHandler;
 import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+import java.util.concurrent.Executors;
 
  /* Run ManifoldCF with jetty.
  * 
@@ -67,7 +70,12 @@ public class ManifoldCFCombinedJettyRunner
 
   public ManifoldCFCombinedJettyRunner( int port, String combinedWarPath )
   {
-    server = new Server( port );
+    QueuedThreadPool threadPool = new QueuedThreadPool();
+    
threadPool.setVirtualThreadsExecutor(Executors.newVirtualThreadPerTaskExecutor());
+    server = new Server( threadPool );
+    ServerConnector connector = new ServerConnector(server);
+    connector.setPort(port);
+    server.addConnector(connector);
     initializeServer( combinedWarPath );
   }
 
diff --git 
a/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFJettyRunner.java
 
b/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFJettyRunner.java
index 9ed13d869..2355442d8 100644
--- 
a/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFJettyRunner.java
+++ 
b/framework/jetty-runner/src/main/java/org/apache/manifoldcf/jettyrunner/ManifoldCFJettyRunner.java
@@ -42,6 +42,9 @@ import org.eclipse.jetty.ee10.webapp.WebAppContext;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.handler.ShutdownHandler;
 import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+import java.util.concurrent.Executors;
 
 import org.eclipse.jetty.ee10.apache.jsp.JettyJasperInitializer;
 import org.eclipse.jetty.ee10.jsp.JettyJspServlet;
@@ -80,7 +83,12 @@ public class ManifoldCFJettyRunner
   
   public ManifoldCFJettyRunner( int port, String crawlerWarPath, String 
authorityServiceWarPath, String apiWarPath, boolean useParentLoader )
   {
-    server = new Server( port );
+    QueuedThreadPool threadPool = new QueuedThreadPool();
+    
threadPool.setVirtualThreadsExecutor(Executors.newVirtualThreadPerTaskExecutor());
+    server = new Server( threadPool );
+    ServerConnector connector = new ServerConnector(server);
+    connector.setPort(port);
+    server.addConnector(connector);
     initializeServer(crawlerWarPath, authorityServiceWarPath, apiWarPath, 
useParentLoader);
   }
   
diff --git 
a/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/CrawlerAgent.java
 
b/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/CrawlerAgent.java
index 8d796e8d8..4fb266c51 100644
--- 
a/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/CrawlerAgent.java
+++ 
b/framework/pull-agent/src/main/java/org/apache/manifoldcf/crawler/system/CrawlerAgent.java
@@ -389,22 +389,22 @@ public class CrawlerAgent implements IAgent
     docDeleteResetManager = new 
DocDeleteResetManager(documentDeleteQueue,processID);
     docCleanupResetManager = new 
DocCleanupResetManager(documentCleanupQueue,processID);
 
-    jobStartThread = new JobStartThread(processID);
-    startupThread = new StartupThread(new 
StartupResetManager(processID),processID);
-    startDeleteThread = new StartDeleteThread(new 
DeleteStartupResetManager(processID),processID);
-    finisherThread = new FinisherThread(processID);
-    notificationThread = new JobNotificationThread(new 
NotificationResetManager(processID),processID);
-    jobDeleteThread = new JobDeleteThread(processID);
-    stufferThread = new 
StufferThread(documentQueue,numWorkerThreads,workerResetManager,queueTracker,blockingDocuments,lowWaterFactor,stuffAmtFactor,processID);
-    expireStufferThread = new 
ExpireStufferThread(expireQueue,numExpireThreads,workerResetManager,processID);
-    setPriorityThread = new 
SetPriorityThread(numWorkerThreads,blockingDocuments,processID);
-    historyCleanupThread = new HistoryCleanupThread(processID);
+    jobStartThread = Thread.ofVirtual().name("Job start thread").unstarted(new 
JobStartThread(processID));
+    startupThread = Thread.ofVirtual().name("Startup thread").unstarted(new 
StartupThread(new StartupResetManager(processID),processID));
+    startDeleteThread = Thread.ofVirtual().name("Start delete 
thread").unstarted(new StartDeleteThread(new 
DeleteStartupResetManager(processID),processID));
+    finisherThread = Thread.ofVirtual().name("Finisher thread").unstarted(new 
FinisherThread(processID));
+    notificationThread = Thread.ofVirtual().name("Notification 
thread").unstarted(new JobNotificationThread(new 
NotificationResetManager(processID),processID));
+    jobDeleteThread = Thread.ofVirtual().name("Job delete 
thread").unstarted(new JobDeleteThread(processID));
+    stufferThread = Thread.ofVirtual().name("Stuffer thread").unstarted(new 
StufferThread(documentQueue,numWorkerThreads,workerResetManager,queueTracker,blockingDocuments,lowWaterFactor,stuffAmtFactor,processID));
+    expireStufferThread = Thread.ofVirtual().name("Expire stuffer 
thread").unstarted(new 
ExpireStufferThread(expireQueue,numExpireThreads,workerResetManager,processID));
+    setPriorityThread = Thread.ofVirtual().name("Set priority 
thread").unstarted(new 
SetPriorityThread(numWorkerThreads,blockingDocuments,processID));
+    historyCleanupThread = Thread.ofVirtual().name("History cleanup 
thread").unstarted(new HistoryCleanupThread(processID));
 
     workerThreads = new Thread[numWorkerThreads];
     int i = 0;
     while (i < numWorkerThreads)
     {
-      workerThreads[i] = new 
WorkerThread(Integer.toString(i),documentQueue,workerResetManager,queueTracker,processID);
+      workerThreads[i] = Thread.ofVirtual().name("Worker thread 
'"+i+"'").unstarted(new 
WorkerThread(Integer.toString(i),documentQueue,workerResetManager,queueTracker,processID));
       i++;
     }
 
@@ -412,32 +412,32 @@ public class CrawlerAgent implements IAgent
     i = 0;
     while (i < numExpireThreads)
     {
-      expireThreads[i] = new 
ExpireThread(Integer.toString(i),expireQueue,workerResetManager,processID);
+      expireThreads[i] = Thread.ofVirtual().name("Expire thread 
'"+i+"'").unstarted(new 
ExpireThread(Integer.toString(i),expireQueue,workerResetManager,processID));
       i++;
     }
 
-    deleteStufferThread = new 
DocumentDeleteStufferThread(documentDeleteQueue,numDeleteThreads,docDeleteResetManager,processID);
+    deleteStufferThread = Thread.ofVirtual().name("Delete stuffer 
thread").unstarted(new 
DocumentDeleteStufferThread(documentDeleteQueue,numDeleteThreads,docDeleteResetManager,processID));
     deleteThreads = new Thread[numDeleteThreads];
     i = 0;
     while (i < numDeleteThreads)
     {
-      deleteThreads[i] = new 
DocumentDeleteThread(Integer.toString(i),documentDeleteQueue,docDeleteResetManager,processID);
+      deleteThreads[i] = Thread.ofVirtual().name("Delete thread 
'"+i+"'").unstarted(new 
DocumentDeleteThread(Integer.toString(i),documentDeleteQueue,docDeleteResetManager,processID));
       i++;
     }
       
-    cleanupStufferThread = new 
DocumentCleanupStufferThread(documentCleanupQueue,numCleanupThreads,docCleanupResetManager,processID);
+    cleanupStufferThread = Thread.ofVirtual().name("Cleanup stuffer 
thread").unstarted(new 
DocumentCleanupStufferThread(documentCleanupQueue,numCleanupThreads,docCleanupResetManager,processID));
     cleanupThreads = new Thread[numCleanupThreads];
     i = 0;
     while (i < numCleanupThreads)
     {
-      cleanupThreads[i] = new 
DocumentCleanupThread(Integer.toString(i),documentCleanupQueue,docCleanupResetManager,processID);
+      cleanupThreads[i] = Thread.ofVirtual().name("Cleanup thread 
'"+i+"'").unstarted(new 
DocumentCleanupThread(Integer.toString(i),documentCleanupQueue,docCleanupResetManager,processID));
       i++;
     }
 
-    jobResetThread = new JobResetThread(processID);
-    seedingThread = new SeedingThread(new 
SeedingResetManager(processID),processID);
-    idleCleanupThread = new IdleCleanupThread(processID);
-    assessmentThread = new AssessmentThread(processID);
+    jobResetThread = Thread.ofVirtual().name("Job reset thread").unstarted(new 
JobResetThread(processID));
+    seedingThread = Thread.ofVirtual().name("Seeding thread").unstarted(new 
SeedingThread(new SeedingResetManager(processID),processID));
+    idleCleanupThread = Thread.ofVirtual().name("Idle cleanup 
thread").unstarted(new IdleCleanupThread(processID));
+    assessmentThread = Thread.ofVirtual().name("Assessment 
thread").unstarted(new AssessmentThread(processID));
 
     // Start all the threads
     jobStartThread.start();
diff --git 
a/framework/pull-agent/src/test/java/org/apache/manifoldcf/crawler/tests/ManifoldCFInstance.java
 
b/framework/pull-agent/src/test/java/org/apache/manifoldcf/crawler/tests/ManifoldCFInstance.java
index bbf419e2d..b48988945 100644
--- 
a/framework/pull-agent/src/test/java/org/apache/manifoldcf/crawler/tests/ManifoldCFInstance.java
+++ 
b/framework/pull-agent/src/test/java/org/apache/manifoldcf/crawler/tests/ManifoldCFInstance.java
@@ -33,8 +33,12 @@ import org.junit.*;
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.ee10.webapp.WebAppContext;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+import java.util.concurrent.Executors;
 
 import org.apache.http.conn.HttpClientConnectionManager;
 import org.apache.http.client.HttpClient;
@@ -567,7 +571,12 @@ public class ManifoldCFInstance
     if (webapps)
     {
       // Start jetty
-      server = new Server( testPort );    
+      QueuedThreadPool threadPool = new QueuedThreadPool();
+      
threadPool.setVirtualThreadsExecutor(Executors.newVirtualThreadPerTaskExecutor());
+      server = new Server( threadPool );
+      ServerConnector connector = new ServerConnector(server);
+      connector.setPort(testPort);
+      server.addConnector(connector);
       server.setStopAtShutdown( true );
       // Initialize the servlets
       server.setHandler(contexts);
diff --git a/pom.xml b/pom.xml
index 1e4f507ef..5b1a58b8b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,11 +109,11 @@
     <maven-assembly-plugin.version>3.8.0</maven-assembly-plugin.version>
     
<maven-apache-source-release-assembly-descriptor.version>1.5</maven-apache-source-release-assembly-descriptor.version>
     <maven-compiler-plugin.version>3.15.0</maven-compiler-plugin.version>
-    <maven.compiler.source>21</maven.compiler.source>
-    <maven.compiler.target>21</maven.compiler.target>
+    <maven.compiler.source>25</maven.compiler.source>
+    <maven.compiler.target>25</maven.compiler.target>
     <maven-antrun-plugin.version>3.2.0</maven-antrun-plugin.version>
-    <javaVersion>21</javaVersion>
-    <spring-boot.version>3.3.0</spring-boot.version>
+    <javaVersion>25</javaVersion>
+    <spring-boot.version>4.0.6</spring-boot.version>
     <maven-surefire-plugin.version>3.5.2</maven-surefire-plugin.version>
     <maven-failsafe-plugin.version>3.5.2</maven-failsafe-plugin.version>
     <skipTests>false</skipTests>
@@ -418,7 +418,7 @@
           <maxmem>512m</maxmem>
           <compilerArgs>
             <arg>-Xpkginfo:always</arg>
-            <arg>-Xlint:options</arg>
+            <arg>-Xlint:options</arg><arg>--enable-preview</arg>
             <arg>--enable-preview</arg>
           </compilerArgs>
         </configuration>

Reply via email to