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

acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new ee62f2bbfaee CAMEL-23112 - Drop Support for JDK 17 (#21696)
ee62f2bbfaee is described below

commit ee62f2bbfaeeff1a367ba24591a5c1830f6f539c
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Mar 4 10:46:27 2026 +0100

    CAMEL-23112 - Drop Support for JDK 17 (#21696)
    
    * CAMEL-23112 - Drop Support for JDK 17
    
    - Jenkinsfile: remove jdk_17_latest from matrix axis and JDK_FILTER
      choices, remove JDK 21 excludes on ppc64le/s390x so the new baseline
      runs on all platforms, move coverage profile to the JDK 21 build,
      and run Sonar analysis on JDK 21 instead of JDK 17
    - Jenkinsfile.deploy: default JDK changed to jdk_21_latest
    - Jenkinsfile.jbangtest: default JDK changed to jdk_21_latest
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * CAMEL-23112: Remove multi-release JAR workarounds for JDK 21
    
    With JDK 21 as the minimum baseline, the multi-release JAR pattern
    used in camel-util and camel-support for virtual thread support is
    no longer needed.
    
    Merge the JDK 21 source variants (src/main/java21/) into the main
    source tree:
    - ThreadType: now checks camel.threads.virtual.enabled system property
      directly instead of always returning PLATFORM
    - CamelThreadFactory: now implements ThreadFactoryTypeAware with
      Thread.ofPlatform()/Thread.ofVirtual() builder support
    - DefaultThreadPoolFactory: now includes ThreadPoolFactoryType enum
      with VIRTUAL variant using Executors.newThreadPerTaskExecutor()
    
    Remove java-21-sources profile and Multi-Release JAR manifest entries
    from both camel-util and camel-support pom.xml files.
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * CAMEL-23112: Remove JDK 17 option from camel-jbang --java-version
    
    With JDK 21 as the minimum baseline, JDK 17 is no longer a valid
    choice for the camel-jbang export --java-version flag.
    
    - Remove 17 from @Metadata enums in CamelJBangConstants
    - Update JBang script headers from JAVA 17+ to JAVA 21+
    - Update ExportMainJibTest to test explicit Java 21 instead of 17
    - Update MigrationTools to require Java 21+ for Camel 4.19+
    - Regenerate metadata JSON and docs
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    * Regen
    
    Signed-off-by: Andrea Cosentino <[email protected]>
    
    ---------
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .github/workflows/alternative-os-build-main.yml    |   2 +-
 .github/workflows/generate-sbom-main.yml           |   2 +-
 .github/workflows/pr-build-main.yml                |   5 +-
 .github/workflows/pr-manual-component-test.yml     |   2 +-
 .github/workflows/security-scan.yml                |   4 +-
 AGENTS.md                                          |   2 +-
 Jenkinsfile                                        |  33 +---
 Jenkinsfile.deploy                                 |   2 +-
 Jenkinsfile.jbangtest                              |   2 +-
 .../jbang/camel-jbang-configuration-metadata.json  |   2 +-
 core/camel-support/pom.xml                         |  49 -----
 .../camel/support/DefaultThreadPoolFactory.java    | 154 ++++++++++-----
 .../camel/support/DefaultThreadPoolFactory.java    | 208 ---------------------
 core/camel-util/pom.xml                            |  47 -----
 .../camel/util/concurrent/CamelThreadFactory.java  |  43 ++++-
 .../apache/camel/util/concurrent/ThreadType.java   |  20 +-
 .../camel/util/concurrent/CamelThreadFactory.java  |  91 ---------
 .../apache/camel/util/concurrent/ThreadType.java   |  42 -----
 docs/main/modules/contributing/pages/building.adoc |   4 +-
 docs/main/modules/contributing/pages/index.adoc    |   2 +-
 .../modules/ROOT/pages/camel-jbang.adoc            |   2 +-
 .../camel-jbang-configuration-metadata.json        |   2 +-
 .../camel/dsl/jbang/core/commands/Export.java      |   4 +-
 .../dsl/jbang/core/common/CamelJBangConstants.java |   4 +-
 .../src/main/resources/templates/Dockerfile17.tmpl |  97 ----------
 .../dsl/jbang/core/commands/ExportMainJibTest.java |   8 +-
 .../camel-jbang-main/dist/CamelJBang.java          |   2 +-
 .../src/main/jbang/main/CamelJBang.java            |   2 +-
 .../jbang/core/commands/mcp/MigrationTools.java    |  47 +++--
 pom.xml                                            |   2 +-
 .../src/it/customized-v3/pom.xml                   |   6 +-
 .../src/it/expanded-v3-yaml/pom.xml                |   6 +-
 .../src/it/simple-dto-v3/pom.xml                   |   6 +-
 .../src/it/simple-v3-yaml/pom.xml                  |   6 +-
 .../src/it/simple-v3/pom.xml                       |   6 +-
 .../src/it/simple-xml-dto-v3/pom.xml               |   6 +-
 .../src/it/simple-xml-v3/pom.xml                   |   6 +-
 .../src/it/simple-yaml-dto-v3/pom.xml              |   6 +-
 .../src/it/simple-yaml-kamelet-v3/pom.xml          |   6 +-
 .../src/it/simple-yaml-v3/pom.xml                  |   6 +-
 40 files changed, 262 insertions(+), 684 deletions(-)

diff --git a/.github/workflows/alternative-os-build-main.yml 
b/.github/workflows/alternative-os-build-main.yml
index 170688ce4520..fc81eab36209 100644
--- a/.github/workflows/alternative-os-build-main.yml
+++ b/.github/workflows/alternative-os-build-main.yml
@@ -41,7 +41,7 @@ jobs:
         uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 
v5.2.0
         with:
           distribution: 'temurin'
-          java-version: 17
+          java-version: 21
           cache: 'maven'
       - name: mvn build ${{ matrix.os }}
         run: ./mvnw -B -V -D'http.keepAlive=false' -l build.log 
-D'maven.wagon.http.pool=false' 
-D'maven.wagon.httpconnectionManager.ttlSeconds=120' --no-transfer-progress 
-Dquickly install
diff --git a/.github/workflows/generate-sbom-main.yml 
b/.github/workflows/generate-sbom-main.yml
index 113d6096abab..6b0460766395 100644
--- a/.github/workflows/generate-sbom-main.yml
+++ b/.github/workflows/generate-sbom-main.yml
@@ -34,7 +34,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        java: [ '17' ]
+        java: [ '21' ]
     steps:
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 
v6.0.2
         with:
diff --git a/.github/workflows/pr-build-main.yml 
b/.github/workflows/pr-build-main.yml
index 569680d03531..9467f7fe951e 100644
--- a/.github/workflows/pr-build-main.yml
+++ b/.github/workflows/pr-build-main.yml
@@ -41,11 +41,8 @@ jobs:
     continue-on-error: ${{ matrix.experimental }}
     strategy:
       matrix:
-        java: ['17']
+        java: ['21']
         experimental: [ false ]
-        include:
-          - java: '21'
-            experimental: true
 
     steps:
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 
v6.0.2
diff --git a/.github/workflows/pr-manual-component-test.yml 
b/.github/workflows/pr-manual-component-test.yml
index 1e186e1e199f..ef88b148f140 100644
--- a/.github/workflows/pr-manual-component-test.yml
+++ b/.github/workflows/pr-manual-component-test.yml
@@ -33,7 +33,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        java: [ '17' ]
+        java: [ '21' ]
     steps:
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 
v6.0.2
         with:
diff --git a/.github/workflows/security-scan.yml 
b/.github/workflows/security-scan.yml
index 2d7bfdc3ef49..c5fa606e3643 100644
--- a/.github/workflows/security-scan.yml
+++ b/.github/workflows/security-scan.yml
@@ -35,11 +35,11 @@ jobs:
         uses: actions/checkout@v6
         with:
           persist-credentials: false
-      - name: Set up JDK 17
+      - name: Set up JDK 21
         uses: actions/setup-java@v5
         with:
           distribution: 'temurin'
-          java-version: '17'
+          java-version: '21'
           cache: 'maven'
       - name: OWASP Dependency Check
         run: ./mvnw -B -Pdependencycheck validate -DskipTests -DnvdApiKey=${{ 
secrets.NVD_API_KEY }} -DnvdApiDelay=5000 -l owasp-check.log
diff --git a/AGENTS.md b/AGENTS.md
index f2f3385bef39..632f852c8382 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -7,7 +7,7 @@ Guidelines for AI agents working on this codebase.
 Apache Camel is an integration framework supporting routing rules in Java, XML 
and YAML DSLs.
 
 - Version: 4.19.0-SNAPSHOT
-- Java: 17+ (21 for Virtual Threads)
+- Java: 21+
 - Build: Maven 3.9.12+
 
 ## Structure
diff --git a/Jenkinsfile b/Jenkinsfile
index b49f2bab0cc3..bbabca5708eb 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -49,7 +49,7 @@ pipeline {
     parameters {
         booleanParam(name: 'VIRTUAL_THREAD', defaultValue: false, description: 
'Perform the build using virtual threads')
         choice(name: 'PLATFORM_FILTER', choices: ['all', 'ppc64le', 's390x', 
'ubuntu-avx'], description: 'Run on specific platform')
-        choice(name: 'JDK_FILTER', choices: ['all', 'jdk_17_latest', 
'jdk_21_latest', 'jdk_25_latest'], description: 'Run on specific jdk')
+        choice(name: 'JDK_FILTER', choices: ['all', 'jdk_21_latest', 
'jdk_25_latest'], description: 'Run on specific jdk')
     }
     agent none
     stages {
@@ -70,7 +70,7 @@ pipeline {
                 axes {
                     axis {
                         name 'JDK_NAME'
-                        values 'jdk_17_latest', 'jdk_21_latest', 
'jdk_25_latest'
+                        values 'jdk_21_latest', 'jdk_25_latest'
                     }
                     axis {
                         name 'PLATFORM'
@@ -78,26 +78,6 @@ pipeline {
                     }
                 }
                 excludes {
-                    exclude {
-                        axis {
-                            name 'JDK_NAME'
-                            values 'jdk_21_latest'
-                        }
-                        axis {
-                            name 'PLATFORM'
-                            values 'ppc64le'
-                        }
-                    }
-                    exclude {
-                        axis {
-                            name 'JDK_NAME'
-                            values 'jdk_21_latest'
-                        }
-                        axis {
-                            name 'PLATFORM'
-                            values 's390x'
-                        }
-                    }
                     exclude {
                         axis {
                             name 'JDK_NAME'
@@ -139,11 +119,8 @@ pipeline {
                                 script {
                                     if ("${PLATFORM}" == "ubuntu-avx") {
                                         if ("${JDK_NAME}" == "jdk_21_latest") {
-                                            // Enable virtual threads
-                                            sh "./mvnw $MAVEN_PARAMS 
$MAVEN_TEST_PARAMS_UBUNTU -Darchetype.test.skip 
-Dmaven.test.failure.ignore=true -Dcheckstyle.skip=true install 
-Dcamel.threads.virtual.enabled=${params.VIRTUAL_THREAD}"
-                                        } else if ("${JDK_NAME}" == 
"jdk_17_latest") {
-                                            // Enable coverage required later 
by Sonar check
-                                            sh "./mvnw $MAVEN_PARAMS 
$MAVEN_TEST_PARAMS -Darchetype.test.skip -Dmaven.test.failure.ignore=true 
-Dcheckstyle.skip=true install -Pcoverage"
+                                            // Enable virtual threads and 
coverage required later by Sonar check
+                                            sh "./mvnw $MAVEN_PARAMS 
$MAVEN_TEST_PARAMS_UBUNTU -Darchetype.test.skip 
-Dmaven.test.failure.ignore=true -Dcheckstyle.skip=true install 
-Dcamel.threads.virtual.enabled=${params.VIRTUAL_THREAD} -Pcoverage"
                                         } else {
                                             sh "./mvnw $MAVEN_PARAMS 
$MAVEN_TEST_PARAMS -Darchetype.test.skip -Dmaven.test.failure.ignore=true 
-Dcheckstyle.skip=true install"
                                         }
@@ -168,7 +145,7 @@ pipeline {
                             script {
                                 echo "Do Static code analysis for 
${PLATFORM}-${JDK_NAME}"
                                 // We only execute this on the main 
PLATFORM/JDK target
-                                if ("${PLATFORM}" == "ubuntu-avx" && 
"${JDK_NAME}" == "jdk_17_latest") {
+                                if ("${PLATFORM}" == "ubuntu-avx" && 
"${JDK_NAME}" == "jdk_21_latest") {
                                     withCredentials([string(credentialsId: 
'apache-camel-core', variable: 'SONAR_TOKEN')]) {
                                         echo "Code quality review ENABLED for 
${PLATFORM} with ${JDK_NAME}"
                                         sh "./mvnw $MAVEN_PARAMS 
-Dsonar.host.url=https://sonarcloud.io 
-Dsonar.java.experimental.batchModeSizeInKB=2048 -Dsonar.organization=apache 
-Dsonar.projectKey=apache_camel -Dsonar.branch.name=$BRANCH_NAME 
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar"
diff --git a/Jenkinsfile.deploy b/Jenkinsfile.deploy
index 405b786d93af..5c1db358ac00 100644
--- a/Jenkinsfile.deploy
+++ b/Jenkinsfile.deploy
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 def AGENT_LABEL = env.AGENT_LABEL ?: 'ubuntu'
-def JDK_NAME = env.JDK_NAME ?: 'jdk_17_latest'
+def JDK_NAME = env.JDK_NAME ?: 'jdk_21_latest'
 
 def MAVEN_PARAMS = "-U -B -e -fae -V -Dnoassembly -Dmaven.compiler.fork=true "
 
diff --git a/Jenkinsfile.jbangtest b/Jenkinsfile.jbangtest
index 63729151045c..7b0b4807f024 100644
--- a/Jenkinsfile.jbangtest
+++ b/Jenkinsfile.jbangtest
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 def AGENT_LABEL = env.AGENT_LABEL ?: 'ubuntu'
-def JDK_NAME = env.JDK_NAME ?: 'jdk_17_latest'
+def JDK_NAME = env.JDK_NAME ?: 'jdk_21_latest'
 
 def MAVEN_PARAMS = "-U -B -e -fae -V -Dnoassembly -Dmaven.compiler.fork=true "
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
index 01c0f4bbcdec..7249ffadeb29 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/jbang/camel-jbang-configuration-metadata.json
@@ -19,7 +19,7 @@
     { "name": "camel.jbang.groovyFiles", "required": false, "description": 
"Additional groovy source files to export to src\/main\/resources\/camel-groovy 
directory (Use commas to separate multiple files)", "type": "string", 
"javaType": "String", "secret": false },
     { "name": "camel.jbang.health", "required": false, "description": "Health 
check at \/observe\/health on local HTTP server (port 8080 by default)", 
"type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": 
false, "deprecated": true },
     { "name": "camel.jbang.ignoreLoadingError", "required": false, 
"description": "Whether to ignore route loading and compilation errors (use 
this with care!)", "label": "advanced", "type": "boolean", "javaType": 
"boolean", "defaultValue": false, "secret": false },
-    { "name": "camel.jbang.javaVersion", "required": false, "description": 
"Java version (17 or 21)", "type": "enum", "javaType": "String", 
"defaultValue": "21", "secret": false, "enum": [ "17", "21" ] },
+    { "name": "camel.jbang.javaVersion", "required": false, "description": 
"Java version", "type": "enum", "javaType": "String", "defaultValue": "21", 
"secret": false, "enum": [ "21" ] },
     { "name": "camel.jbang.jfr", "required": false, "description": "Enables 
Java Flight Recorder saving recording to disk on exit", "type": "boolean", 
"javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.jbang.jfr-profile", "required": false, "description": 
"Java Flight Recorder profile to use (such as default or profile)", "type": 
"string", "javaType": "String", "defaultValue": "default", "secret": false },
     { "name": "camel.jbang.jib-maven-plugin-version", "required": false, 
"description": "Version to use for jib-maven-plugin if exporting to camel-main 
and have Kubernetes enabled (jkube.xxx options)", "label": "kubernetes", 
"type": "string", "javaType": "String", "defaultValue": "3.4.5", "secret": 
false },
diff --git a/core/camel-support/pom.xml b/core/camel-support/pom.xml
index cc010e72eb6d..9480c6c1b48b 100644
--- a/core/camel-support/pom.xml
+++ b/core/camel-support/pom.xml
@@ -85,53 +85,4 @@
         </dependency>
     </dependencies>
 
-    <profiles>
-        <profile>
-            <id>java-21-sources</id>
-            <activation>
-                <jdk>[21,)</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <version>${maven-compiler-plugin-version}</version>
-                        <executions>
-                            <execution>
-                                <id>default-compile</id>
-                                <phase>compile</phase>
-                                <goals>
-                                    <goal>compile</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>compile-java-21</id>
-                                <phase>compile</phase>
-                                <goals>
-                                    <goal>compile</goal>
-                                </goals>
-                                <configuration>
-                                    <release>21</release>
-                                    
<compileSourceRoots>${project.basedir}/src/main/java21</compileSourceRoots>
-                                    
<multiReleaseOutput>true</multiReleaseOutput>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <configuration>
-                            <archive>
-                                <manifestEntries>
-                                    <Multi-Release>true</Multi-Release>
-                                </manifestEntries>
-                            </archive>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
-    </profiles>
 </project>
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultThreadPoolFactory.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultThreadPoolFactory.java
index aa9c68845dab..c69d555511b1 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultThreadPoolFactory.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultThreadPoolFactory.java
@@ -37,6 +37,8 @@ import org.apache.camel.support.service.ServiceSupport;
 import org.apache.camel.util.concurrent.RejectableScheduledThreadPoolExecutor;
 import org.apache.camel.util.concurrent.RejectableThreadPoolExecutor;
 import org.apache.camel.util.concurrent.SizedScheduledExecutorService;
+import org.apache.camel.util.concurrent.ThreadFactoryTypeAware;
+import org.apache.camel.util.concurrent.ThreadType;
 
 /**
  * Factory for thread pools that uses the JDK {@link Executors} for creating 
the thread pools.
@@ -57,7 +59,7 @@ public class DefaultThreadPoolFactory extends ServiceSupport 
implements CamelCon
 
     @Override
     public ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
-        return Executors.newCachedThreadPool(threadFactory);
+        return ThreadPoolFactoryType.from(threadFactory, 
Integer.MAX_VALUE).newCachedThreadPool(threadFactory);
     }
 
     @Override
@@ -79,7 +81,6 @@ public class DefaultThreadPoolFactory extends ServiceSupport 
implements CamelCon
             boolean allowCoreThreadTimeOut,
             RejectedExecutionHandler rejectedExecutionHandler, ThreadFactory 
threadFactory)
             throws IllegalArgumentException {
-
         // the core pool size must be 0 or higher
         if (corePoolSize < 0) {
             throw new IllegalArgumentException("CorePoolSize must be >= 0, was 
" + corePoolSize);
@@ -90,52 +91,121 @@ public class DefaultThreadPoolFactory extends 
ServiceSupport implements CamelCon
             throw new IllegalArgumentException(
                     "MaxPoolSize must be >= corePoolSize, was " + maxPoolSize 
+ " >= " + corePoolSize);
         }
-
-        BlockingQueue<Runnable> workQueue;
-        if (corePoolSize == 0 && maxQueueSize <= 0) {
-            // use a synchronous queue for direct-handover (no tasks stored on 
the queue)
-            workQueue = new SynchronousQueue<>();
-            // and force 1 as pool size to be able to create the thread pool 
by the JDK
-            corePoolSize = 1;
-            maxPoolSize = 1;
-        } else if (maxQueueSize <= 0) {
-            // use a synchronous queue for direct-handover (no tasks stored on 
the queue)
-            workQueue = new SynchronousQueue<>();
-        } else {
-            // bounded task queue to store tasks on the queue
-            workQueue = new LinkedBlockingQueue<>(maxQueueSize);
-        }
-
-        ThreadPoolExecutor answer
-                = new RejectableThreadPoolExecutor(corePoolSize, maxPoolSize, 
keepAliveTime, timeUnit, workQueue);
-        answer.setThreadFactory(threadFactory);
-        answer.allowCoreThreadTimeOut(allowCoreThreadTimeOut);
-        if (rejectedExecutionHandler == null) {
-            rejectedExecutionHandler = new 
ThreadPoolExecutor.CallerRunsPolicy();
-        }
-        answer.setRejectedExecutionHandler(rejectedExecutionHandler);
-        return answer;
+        return ThreadPoolFactoryType.from(threadFactory, corePoolSize, 
maxPoolSize, maxQueueSize).newThreadPool(
+                corePoolSize, maxPoolSize, keepAliveTime, timeUnit, 
maxQueueSize, allowCoreThreadTimeOut,
+                rejectedExecutionHandler, threadFactory);
     }
 
     @Override
     public ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
-        RejectedExecutionHandler rejectedExecutionHandler = 
profile.getRejectedExecutionHandler();
-        if (rejectedExecutionHandler == null) {
-            rejectedExecutionHandler = new 
ThreadPoolExecutor.CallerRunsPolicy();
+        return ThreadPoolFactoryType.from(threadFactory, 
profile).newScheduledThreadPool(profile, threadFactory);
+    }
+
+    private enum ThreadPoolFactoryType {
+        PLATFORM {
+            ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
+                return Executors.newCachedThreadPool(threadFactory);
+            }
+
+            ExecutorService newThreadPool(
+                    int corePoolSize, int maxPoolSize, long keepAliveTime, 
TimeUnit timeUnit, int maxQueueSize,
+                    boolean allowCoreThreadTimeOut,
+                    RejectedExecutionHandler rejectedExecutionHandler, 
ThreadFactory threadFactory)
+                    throws IllegalArgumentException {
+
+                BlockingQueue<Runnable> workQueue;
+                if (corePoolSize == 0 && maxQueueSize <= 0) {
+                    // use a synchronous queue for direct-handover (no tasks 
stored on the queue)
+                    workQueue = new SynchronousQueue<>();
+                    // and force 1 as pool size to be able to create the 
thread pool by the JDK
+                    corePoolSize = 1;
+                    maxPoolSize = 1;
+                } else if (maxQueueSize <= 0) {
+                    // use a synchronous queue for direct-handover (no tasks 
stored on the queue)
+                    workQueue = new SynchronousQueue<>();
+                } else {
+                    // bounded task queue to store tasks on the queue
+                    workQueue = new LinkedBlockingQueue<>(maxQueueSize);
+                }
+
+                ThreadPoolExecutor answer
+                        = new RejectableThreadPoolExecutor(corePoolSize, 
maxPoolSize, keepAliveTime, timeUnit, workQueue);
+                answer.setThreadFactory(threadFactory);
+                answer.allowCoreThreadTimeOut(allowCoreThreadTimeOut);
+                if (rejectedExecutionHandler == null) {
+                    rejectedExecutionHandler = new 
ThreadPoolExecutor.CallerRunsPolicy();
+                }
+                answer.setRejectedExecutionHandler(rejectedExecutionHandler);
+                return answer;
+            }
+
+            ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
+                RejectedExecutionHandler rejectedExecutionHandler = 
profile.getRejectedExecutionHandler();
+                if (rejectedExecutionHandler == null) {
+                    rejectedExecutionHandler = new 
ThreadPoolExecutor.CallerRunsPolicy();
+                }
+
+                ScheduledThreadPoolExecutor answer
+                        = new RejectableScheduledThreadPoolExecutor(
+                                profile.getPoolSize(), threadFactory, 
rejectedExecutionHandler);
+                answer.setRemoveOnCancelPolicy(true);
+
+                // need to wrap the thread pool in a sized to guard against 
the problem that the
+                // JDK created thread pool has an unbounded queue (see class 
javadoc), which mean
+                // we could potentially keep adding tasks, and run out of 
memory.
+                if (profile.getMaxPoolSize() > 0) {
+                    return new SizedScheduledExecutorService(answer, 
profile.getMaxQueueSize());
+                } else {
+                    return answer;
+                }
+            }
+        },
+        VIRTUAL {
+            @Override
+            ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
+                return Executors.newThreadPerTaskExecutor(threadFactory);
+            }
+
+            @Override
+            ExecutorService newThreadPool(
+                    int corePoolSize, int maxPoolSize, long keepAliveTime, 
TimeUnit timeUnit,
+                    int maxQueueSize, boolean allowCoreThreadTimeOut,
+                    RejectedExecutionHandler rejectedExecutionHandler,
+                    ThreadFactory threadFactory)
+                    throws IllegalArgumentException {
+                return Executors.newThreadPerTaskExecutor(threadFactory);
+            }
+
+            @Override
+            ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
+                return Executors.newScheduledThreadPool(0, threadFactory);
+            }
+        };
+
+        static ThreadPoolFactoryType from(ThreadFactory threadFactory, 
ThreadPoolProfile profile) {
+            return from(threadFactory, profile.getPoolSize(), 
profile.getMaxPoolSize(), profile.getMaxQueueSize());
         }
 
-        ScheduledThreadPoolExecutor answer
-                = new 
RejectableScheduledThreadPoolExecutor(profile.getPoolSize(), threadFactory, 
rejectedExecutionHandler);
-        answer.setRemoveOnCancelPolicy(true);
-
-        // need to wrap the thread pool in a sized to guard against the 
problem that the
-        // JDK created thread pool has an unbounded queue (see class javadoc), 
which mean
-        // we could potentially keep adding tasks, and run out of memory.
-        if (profile.getMaxPoolSize() > 0) {
-            return new SizedScheduledExecutorService(answer, 
profile.getMaxQueueSize());
-        } else {
-            return answer;
+        static ThreadPoolFactoryType from(ThreadFactory threadFactory, int 
corePoolSize, int maxPoolSize, int maxQueueSize) {
+            return from(threadFactory, corePoolSize == 0 && maxQueueSize <= 0 
? 1 : maxPoolSize);
+        }
+
+        static ThreadPoolFactoryType from(ThreadFactory threadFactory, int 
maxPoolSize) {
+            if (ThreadType.current() == ThreadType.PLATFORM) {
+                return ThreadPoolFactoryType.PLATFORM;
+            }
+            return maxPoolSize > 1 && threadFactory instanceof 
ThreadFactoryTypeAware factoryTypeAware
+                    && factoryTypeAware.isVirtual() ? 
ThreadPoolFactoryType.VIRTUAL : ThreadPoolFactoryType.PLATFORM;
         }
-    }
 
+        abstract ExecutorService newCachedThreadPool(ThreadFactory 
threadFactory);
+
+        abstract ExecutorService newThreadPool(
+                int corePoolSize, int maxPoolSize, long keepAliveTime, 
TimeUnit timeUnit, int maxQueueSize,
+                boolean allowCoreThreadTimeOut,
+                RejectedExecutionHandler rejectedExecutionHandler, 
ThreadFactory threadFactory)
+                throws IllegalArgumentException;
+
+        abstract ScheduledExecutorService 
newScheduledThreadPool(ThreadPoolProfile profile, ThreadFactory threadFactory);
+    }
 }
diff --git 
a/core/camel-support/src/main/java21/org/apache/camel/support/DefaultThreadPoolFactory.java
 
b/core/camel-support/src/main/java21/org/apache/camel/support/DefaultThreadPoolFactory.java
deleted file mode 100644
index 8fee4c9efd82..000000000000
--- 
a/core/camel-support/src/main/java21/org/apache/camel/support/DefaultThreadPoolFactory.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.support;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.SynchronousQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
-import org.apache.camel.StaticService;
-import org.apache.camel.spi.ThreadPoolFactory;
-import org.apache.camel.spi.ThreadPoolProfile;
-import org.apache.camel.support.service.ServiceSupport;
-import org.apache.camel.util.concurrent.RejectableScheduledThreadPoolExecutor;
-import org.apache.camel.util.concurrent.RejectableThreadPoolExecutor;
-import org.apache.camel.util.concurrent.SizedScheduledExecutorService;
-import org.apache.camel.util.concurrent.ThreadType;
-import org.apache.camel.util.concurrent.ThreadFactoryTypeAware;
-
-/**
- * Factory for thread pools that uses the JDK {@link Executors} for creating 
the thread pools.
- */
-public class DefaultThreadPoolFactory extends ServiceSupport implements 
CamelContextAware, ThreadPoolFactory, StaticService {
-
-    private CamelContext camelContext;
-
-    @Override
-    public CamelContext getCamelContext() {
-        return camelContext;
-    }
-
-    @Override
-    public void setCamelContext(CamelContext camelContext) {
-        this.camelContext = camelContext;
-    }
-
-    @Override
-    public ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
-        return ThreadPoolFactoryType.from(threadFactory, 
Integer.MAX_VALUE).newCachedThreadPool(threadFactory);
-    }
-
-    @Override
-    public ExecutorService newThreadPool(ThreadPoolProfile profile, 
ThreadFactory factory) {
-        // allow core thread timeout is default true if not configured
-        boolean allow = profile.getAllowCoreThreadTimeOut() != null ? 
profile.getAllowCoreThreadTimeOut() : true;
-        return newThreadPool(profile.getPoolSize(),
-                profile.getMaxPoolSize(),
-                profile.getKeepAliveTime(),
-                profile.getTimeUnit(),
-                profile.getMaxQueueSize(),
-                allow,
-                profile.getRejectedExecutionHandler(),
-                factory);
-    }
-
-    public ExecutorService newThreadPool(
-            int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit 
timeUnit, int maxQueueSize,
-            boolean allowCoreThreadTimeOut,
-            RejectedExecutionHandler rejectedExecutionHandler, ThreadFactory 
threadFactory)
-            throws IllegalArgumentException {
-        // the core pool size must be 0 or higher
-        if (corePoolSize < 0) {
-            throw new IllegalArgumentException("CorePoolSize must be >= 0, was 
" + corePoolSize);
-        }
-
-        // validate max >= core
-        if (maxPoolSize < corePoolSize) {
-            throw new IllegalArgumentException(
-                    "MaxPoolSize must be >= corePoolSize, was " + maxPoolSize 
+ " >= " + corePoolSize);
-        }
-        return ThreadPoolFactoryType.from(threadFactory, corePoolSize, 
maxPoolSize, maxQueueSize).newThreadPool(
-                corePoolSize, maxPoolSize, keepAliveTime, timeUnit, 
maxQueueSize, allowCoreThreadTimeOut,
-                rejectedExecutionHandler, threadFactory);
-    }
-
-    @Override
-    public ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
-        return ThreadPoolFactoryType.from(threadFactory, 
profile).newScheduledThreadPool(profile, threadFactory);
-    }
-
-    private enum ThreadPoolFactoryType {
-        PLATFORM {
-            ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
-                return Executors.newCachedThreadPool(threadFactory);
-            }
-
-            ExecutorService newThreadPool(
-                    int corePoolSize, int maxPoolSize, long keepAliveTime, 
TimeUnit timeUnit, int maxQueueSize,
-                    boolean allowCoreThreadTimeOut,
-                    RejectedExecutionHandler rejectedExecutionHandler, 
ThreadFactory threadFactory)
-                    throws IllegalArgumentException {
-
-                BlockingQueue<Runnable> workQueue;
-                if (corePoolSize == 0 && maxQueueSize <= 0) {
-                    // use a synchronous queue for direct-handover (no tasks 
stored on the queue)
-                    workQueue = new SynchronousQueue<>();
-                    // and force 1 as pool size to be able to create the 
thread pool by the JDK
-                    corePoolSize = 1;
-                    maxPoolSize = 1;
-                } else if (maxQueueSize <= 0) {
-                    // use a synchronous queue for direct-handover (no tasks 
stored on the queue)
-                    workQueue = new SynchronousQueue<>();
-                } else {
-                    // bounded task queue to store tasks on the queue
-                    workQueue = new LinkedBlockingQueue<>(maxQueueSize);
-                }
-
-                ThreadPoolExecutor answer
-                        = new RejectableThreadPoolExecutor(corePoolSize, 
maxPoolSize, keepAliveTime, timeUnit, workQueue);
-                answer.setThreadFactory(threadFactory);
-                answer.allowCoreThreadTimeOut(allowCoreThreadTimeOut);
-                if (rejectedExecutionHandler == null) {
-                    rejectedExecutionHandler = new 
ThreadPoolExecutor.CallerRunsPolicy();
-                }
-                answer.setRejectedExecutionHandler(rejectedExecutionHandler);
-                return answer;
-            }
-
-            ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
-                RejectedExecutionHandler rejectedExecutionHandler = 
profile.getRejectedExecutionHandler();
-                if (rejectedExecutionHandler == null) {
-                    rejectedExecutionHandler = new 
ThreadPoolExecutor.CallerRunsPolicy();
-                }
-
-                ScheduledThreadPoolExecutor answer
-                        = new 
RejectableScheduledThreadPoolExecutor(profile.getPoolSize(), threadFactory, 
rejectedExecutionHandler);
-                answer.setRemoveOnCancelPolicy(true);
-
-                // need to wrap the thread pool in a sized to guard against 
the problem that the
-                // JDK created thread pool has an unbounded queue (see class 
javadoc), which mean
-                // we could potentially keep adding tasks, and run out of 
memory.
-                if (profile.getMaxPoolSize() > 0) {
-                    return new SizedScheduledExecutorService(answer, 
profile.getMaxQueueSize());
-                } else {
-                    return answer;
-                }
-            }
-        },
-        VIRTUAL {
-            @Override
-            ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
-                return Executors.newThreadPerTaskExecutor(threadFactory);
-            }
-
-            @Override
-            ExecutorService newThreadPool(int corePoolSize, int maxPoolSize, 
long keepAliveTime, TimeUnit timeUnit,
-                                          int maxQueueSize, boolean 
allowCoreThreadTimeOut,
-                                          RejectedExecutionHandler 
rejectedExecutionHandler,
-                                          ThreadFactory threadFactory) throws 
IllegalArgumentException {
-                return Executors.newThreadPerTaskExecutor(threadFactory);
-            }
-
-            @Override
-            ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile 
profile, ThreadFactory threadFactory) {
-                return Executors.newScheduledThreadPool(0, threadFactory);
-            }
-        };
-
-        static ThreadPoolFactoryType from(ThreadFactory threadFactory, 
ThreadPoolProfile profile) {
-            return from(threadFactory, profile.getPoolSize(), 
profile.getMaxPoolSize(), profile.getMaxQueueSize());
-        }
-
-        static ThreadPoolFactoryType from(ThreadFactory threadFactory, int 
corePoolSize, int maxPoolSize, int maxQueueSize) {
-            return from(threadFactory, corePoolSize == 0 && maxQueueSize <= 0 
? 1 : maxPoolSize);
-        }
-
-        static ThreadPoolFactoryType from(ThreadFactory threadFactory, int 
maxPoolSize) {
-            if (ThreadType.current() == ThreadType.PLATFORM) {
-                return ThreadPoolFactoryType.PLATFORM;
-            }
-            return maxPoolSize > 1 && threadFactory instanceof 
ThreadFactoryTypeAware factoryTypeAware && factoryTypeAware.isVirtual() ?
-                    ThreadPoolFactoryType.VIRTUAL : 
ThreadPoolFactoryType.PLATFORM;
-        }
-
-        abstract ExecutorService newCachedThreadPool(ThreadFactory 
threadFactory);
-
-        abstract ExecutorService newThreadPool(
-                int corePoolSize, int maxPoolSize, long keepAliveTime, 
TimeUnit timeUnit, int maxQueueSize,
-                boolean allowCoreThreadTimeOut,
-                RejectedExecutionHandler rejectedExecutionHandler, 
ThreadFactory threadFactory)
-                throws IllegalArgumentException;
-
-        abstract ScheduledExecutorService 
newScheduledThreadPool(ThreadPoolProfile profile, ThreadFactory threadFactory);
-    }
-}
diff --git a/core/camel-util/pom.xml b/core/camel-util/pom.xml
index 1f5d4115a181..242635ad773f 100644
--- a/core/camel-util/pom.xml
+++ b/core/camel-util/pom.xml
@@ -272,52 +272,5 @@
                 </plugins>
             </build>
         </profile>
-        <profile>
-            <id>java-21-sources</id>
-            <activation>
-                <jdk>[21,)</jdk>
-            </activation>
-            <build>
-                <plugins>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-compiler-plugin</artifactId>
-                        <version>${maven-compiler-plugin-version}</version>
-                        <executions>
-                            <execution>
-                                <id>default-compile</id>
-                                <phase>compile</phase>
-                                <goals>
-                                    <goal>compile</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>compile-java-21</id>
-                                <phase>compile</phase>
-                                <goals>
-                                    <goal>compile</goal>
-                                </goals>
-                                <configuration>
-                                    <release>21</release>
-                                    
<compileSourceRoots>${project.basedir}/src/main/java21</compileSourceRoots>
-                                    
<multiReleaseOutput>true</multiReleaseOutput>
-                                </configuration>
-                            </execution>
-                        </executions>
-                    </plugin>
-                    <plugin>
-                        <groupId>org.apache.maven.plugins</groupId>
-                        <artifactId>maven-jar-plugin</artifactId>
-                        <configuration>
-                            <archive>
-                                <manifestEntries>
-                                    <Multi-Release>true</Multi-Release>
-                                </manifestEntries>
-                            </archive>
-                        </configuration>
-                    </plugin>
-                </plugins>
-            </build>
-        </profile>
     </profiles>
 </project>
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/concurrent/CamelThreadFactory.java
 
b/core/camel-util/src/main/java/org/apache/camel/util/concurrent/CamelThreadFactory.java
index 570e02796c09..9c179c7ba198 100644
--- 
a/core/camel-util/src/main/java/org/apache/camel/util/concurrent/CamelThreadFactory.java
+++ 
b/core/camel-util/src/main/java/org/apache/camel/util/concurrent/CamelThreadFactory.java
@@ -16,32 +16,40 @@
  */
 package org.apache.camel.util.concurrent;
 
-import java.util.concurrent.ThreadFactory;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Thread factory which creates threads supporting a naming pattern.
+ * Thread factory which creates threads supporting a naming pattern. The 
factory creates virtual threads in case the
+ * System property {@code camel.threads.virtual.enabled} set to {@code true}.
  */
-public final class CamelThreadFactory implements ThreadFactory {
+public final class CamelThreadFactory implements ThreadFactoryTypeAware {
     private static final Logger LOG = 
LoggerFactory.getLogger(CamelThreadFactory.class);
 
+    private static final ThreadFactoryType TYPE = ThreadFactoryType.current();
+
     private final String pattern;
     private final String name;
     private final boolean daemon;
+    private final ThreadFactoryType threadType;
 
     public CamelThreadFactory(String pattern, String name, boolean daemon) {
         this.pattern = pattern;
         this.name = name;
         this.daemon = daemon;
+        this.threadType = daemon ? TYPE : ThreadFactoryType.PLATFORM;
+    }
+
+    @Override
+    public boolean isVirtual() {
+        return threadType == ThreadFactoryType.VIRTUAL;
     }
 
     @Override
     public Thread newThread(Runnable runnable) {
         String threadName = ThreadHelper.resolveThreadName(pattern, name);
-        Thread answer = new Thread(runnable, threadName);
-        answer.setDaemon(daemon);
+
+        Thread answer = threadType.newThread(threadName, daemon, runnable);
 
         LOG.trace("Created thread[{}] -> {}", threadName, answer);
         return answer;
@@ -55,4 +63,27 @@ public final class CamelThreadFactory implements 
ThreadFactory {
     public String toString() {
         return "CamelThreadFactory[" + name + "]";
     }
+
+    private enum ThreadFactoryType {
+        PLATFORM {
+            Thread.Builder newThreadBuilder(String threadName, boolean daemon) 
{
+                return Thread.ofPlatform().name(threadName).daemon(daemon);
+            }
+        },
+        VIRTUAL {
+            Thread.Builder newThreadBuilder(String threadName, boolean daemon) 
{
+                return Thread.ofVirtual().name(threadName);
+            }
+        };
+
+        Thread newThread(String threadName, boolean daemon, Runnable runnable) 
{
+            return newThreadBuilder(threadName, daemon).unstarted(runnable);
+        }
+
+        abstract Thread.Builder newThreadBuilder(String threadName, boolean 
daemon);
+
+        static ThreadFactoryType current() {
+            return ThreadType.current() == ThreadType.VIRTUAL ? VIRTUAL : 
PLATFORM;
+        }
+    }
 }
diff --git 
a/core/camel-util/src/main/java/org/apache/camel/util/concurrent/ThreadType.java
 
b/core/camel-util/src/main/java/org/apache/camel/util/concurrent/ThreadType.java
index b048a2640c9c..c43926be2df6 100644
--- 
a/core/camel-util/src/main/java/org/apache/camel/util/concurrent/ThreadType.java
+++ 
b/core/camel-util/src/main/java/org/apache/camel/util/concurrent/ThreadType.java
@@ -16,15 +16,29 @@
  */
 package org.apache.camel.util.concurrent;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 /**
- * Defines the existing type of threads. The virtual threads can only be used 
with JDK 21+ and the system property
- * {@code camel.threads.virtual.enabled} set to {@code true}.
+ * Defines the existing type of threads. The virtual threads can only be used 
with the system property
+ * {@code camel.threads.virtual.enabled} set to {@code true}. The default 
value is {@code false} which means that
+ * platform threads are used by default.
  */
 public enum ThreadType {
     PLATFORM,
     VIRTUAL;
 
+    private static final Logger LOG = 
LoggerFactory.getLogger(ThreadType.class);
+    private static final ThreadType CURRENT = 
Boolean.getBoolean("camel.threads.virtual.enabled") ? VIRTUAL : PLATFORM;
+    static {
+        if (CURRENT == VIRTUAL) {
+            LOG.info("The type of thread detected is: {}", CURRENT);
+        } else {
+            LOG.debug("The type of thread detected is: {}", CURRENT);
+        }
+    }
+
     public static ThreadType current() {
-        return PLATFORM;
+        return CURRENT;
     }
 }
diff --git 
a/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/CamelThreadFactory.java
 
b/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/CamelThreadFactory.java
deleted file mode 100644
index d6c54ddc692a..000000000000
--- 
a/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/CamelThreadFactory.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.util.concurrent;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Thread factory which creates threads supporting a naming pattern.
- * The factory creates virtual threads in case the System property {@code 
camel.threads.virtual.enabled} set to
- * {@code true}.
- */
-public final class CamelThreadFactory implements ThreadFactoryTypeAware {
-    private static final Logger LOG = 
LoggerFactory.getLogger(CamelThreadFactory.class);
-
-    private static final ThreadFactoryType TYPE = ThreadFactoryType.current();
-
-    private final String pattern;
-    private final String name;
-    private final boolean daemon;
-    private final ThreadFactoryType threadType;
-
-    public CamelThreadFactory(String pattern, String name, boolean daemon) {
-        this.pattern = pattern;
-        this.name = name;
-        this.daemon = daemon;
-        this.threadType = daemon ? TYPE : ThreadFactoryType.PLATFORM;
-    }
-
-    @Override
-    public boolean isVirtual() {
-        return threadType == ThreadFactoryType.VIRTUAL;
-    }
-
-    @Override
-    public Thread newThread(Runnable runnable) {
-        String threadName = ThreadHelper.resolveThreadName(pattern, name);
-
-        Thread answer = threadType.newThread(threadName, daemon, runnable);
-
-        LOG.trace("Created thread[{}] -> {}", threadName, answer);
-        return answer;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public String toString() {
-        return "CamelThreadFactory[" + name + "]";
-    }
-
-    private enum ThreadFactoryType {
-        PLATFORM {
-            Thread.Builder newThreadBuilder(String threadName, boolean daemon) 
{
-                return Thread.ofPlatform().name(threadName).daemon(daemon);
-            }
-        },
-        VIRTUAL {
-            Thread.Builder newThreadBuilder(String threadName, boolean daemon) 
{
-                return Thread.ofVirtual().name(threadName);
-            }
-        };
-
-        Thread newThread(String threadName, boolean daemon, Runnable runnable) 
{
-            return newThreadBuilder(threadName, daemon).unstarted(runnable);
-        }
-
-        abstract Thread.Builder newThreadBuilder(String threadName, boolean 
daemon);
-
-        static ThreadFactoryType current() {
-            return ThreadType.current() == ThreadType.VIRTUAL ? VIRTUAL : 
PLATFORM;
-        }
-    }
-}
-
diff --git 
a/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/ThreadType.java
 
b/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/ThreadType.java
deleted file mode 100644
index 16a9401371d2..000000000000
--- 
a/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/ThreadType.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.camel.util.concurrent;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Defines the existing type of threads. The virtual threads can only be used 
with JDK 21+ and the system property
- * {@code camel.threads.virtual.enabled} set to {@code true}.
- * The default value is {@code false} which means that platform threads are 
used by default.
- */
-public enum ThreadType {
-    PLATFORM,
-    VIRTUAL;
-    private static final Logger LOG = 
LoggerFactory.getLogger(ThreadType.class);
-    private static final ThreadType CURRENT = 
Boolean.getBoolean("camel.threads.virtual.enabled") ? VIRTUAL : PLATFORM;
-    static {
-        if (CURRENT == VIRTUAL) {
-            LOG.info("The type of thread detected is: {}", CURRENT);
-        } else {
-            LOG.debug("The type of thread detected is: {}", CURRENT);
-        }
-    }
-    public static ThreadType current() {
-        return CURRENT;
-    }
-}
diff --git a/docs/main/modules/contributing/pages/building.adoc 
b/docs/main/modules/contributing/pages/building.adoc
index 1a15528e9059..af9419733302 100644
--- a/docs/main/modules/contributing/pages/building.adoc
+++ b/docs/main/modules/contributing/pages/building.adoc
@@ -18,7 +18,7 @@
 
 == Prerequisites for Camel 4.x
 
-* Java 17 (we test using https://adoptium.net/[OpenJDK], but any modern JDK 
should be fine).
+* Java 21 (we test using https://adoptium.net/[OpenJDK], but any modern JDK 
should be fine).
 
 * https://github.com/takari/maven-wrapper[Maven Wrapper] can be used and is 
bundled.
 
@@ -33,7 +33,7 @@ Running the Maven Wrapper `mvnw` script with `-v` parameter 
from the root direct
 ./mvnw -v
 Apache Maven 1.2.3
 Maven home: 
/home/user/.m2/wrapper/dists/apache-maven-1.2.3-bin/deadbeef/apache-maven-1.2.3
-Java version: 17.0.5, vendor: Eclipse Adoptium, runtime: 
/home/user/java/17.0.5-tem
+Java version: 21.0.10, vendor: Eclipse Adoptium, runtime: 
/home/user/java/21.0.10-tem
 Default locale: en_IE, platform encoding: UTF-8
 OS name: "linux", version: "6.3.7-200.fc38.x86_64", arch: "amd64", family: 
"unix"
 ----
diff --git a/docs/main/modules/contributing/pages/index.adoc 
b/docs/main/modules/contributing/pages/index.adoc
index 9df2eabad0c5..246d385b6b33 100644
--- a/docs/main/modules/contributing/pages/index.adoc
+++ b/docs/main/modules/contributing/pages/index.adoc
@@ -127,7 +127,7 @@ If you are an Apache Camel committer, then you may also 
clone the https://gitbox
 
 To build the project, you need http://maven.apache.org/download.html[Apache 
Maven].
 
-- To build Camel 4, you need Java 17 Apache Maven version 3.9.6 or higher.
+- To build Camel 4, you need Java 21 and Apache Maven version 3.9.6 or higher.
 
 === Building Camel 4
 
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index f8337ba60480..875d9b496b11 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -4153,7 +4153,7 @@ The camel.jbang supports 45 options, which are listed 
below.
 | *camel.jbang.groovyFiles* | Additional groovy source files to export to 
src/main/resources/camel-groovy directory (Use commas to separate multiple 
files) |  | String
 | *camel.jbang.health* | Health check at /observe/health on local HTTP server 
(port 8080 by default) | false | boolean
 | *camel.jbang.ignoreLoadingError* | Whether to ignore route loading and 
compilation errors (use this with care!) | false | boolean
-| *camel.jbang.javaVersion* | Java version (17 or 21) | 21 | String
+| *camel.jbang.javaVersion* | Java version | 21 | String
 | *camel.jbang.jfr* | Enables Java Flight Recorder saving recording to disk on 
exit | false | boolean
 | *camel.jbang.jfr-profile* | Java Flight Recorder profile to use (such as 
default or profile) | default | String
 | *camel.jbang.jib-maven-plugin-version* | Version to use for jib-maven-plugin 
if exporting to camel-main and have Kubernetes enabled (jkube.xxx options) | 
3.4.5 | String
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
index 01c0f4bbcdec..7249ffadeb29 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-configuration-metadata.json
@@ -19,7 +19,7 @@
     { "name": "camel.jbang.groovyFiles", "required": false, "description": 
"Additional groovy source files to export to src\/main\/resources\/camel-groovy 
directory (Use commas to separate multiple files)", "type": "string", 
"javaType": "String", "secret": false },
     { "name": "camel.jbang.health", "required": false, "description": "Health 
check at \/observe\/health on local HTTP server (port 8080 by default)", 
"type": "boolean", "javaType": "boolean", "defaultValue": false, "secret": 
false, "deprecated": true },
     { "name": "camel.jbang.ignoreLoadingError", "required": false, 
"description": "Whether to ignore route loading and compilation errors (use 
this with care!)", "label": "advanced", "type": "boolean", "javaType": 
"boolean", "defaultValue": false, "secret": false },
-    { "name": "camel.jbang.javaVersion", "required": false, "description": 
"Java version (17 or 21)", "type": "enum", "javaType": "String", 
"defaultValue": "21", "secret": false, "enum": [ "17", "21" ] },
+    { "name": "camel.jbang.javaVersion", "required": false, "description": 
"Java version", "type": "enum", "javaType": "String", "defaultValue": "21", 
"secret": false, "enum": [ "21" ] },
     { "name": "camel.jbang.jfr", "required": false, "description": "Enables 
Java Flight Recorder saving recording to disk on exit", "type": "boolean", 
"javaType": "boolean", "defaultValue": false, "secret": false },
     { "name": "camel.jbang.jfr-profile", "required": false, "description": 
"Java Flight Recorder profile to use (such as default or profile)", "type": 
"string", "javaType": "String", "defaultValue": "default", "secret": false },
     { "name": "camel.jbang.jib-maven-plugin-version", "required": false, 
"description": "Version to use for jib-maven-plugin if exporting to camel-main 
and have Kubernetes enabled (jkube.xxx options)", "label": "kubernetes", 
"type": "string", "javaType": "String", "defaultValue": "3.4.5", "secret": 
false },
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
index 7ac476c14e9b..8b63fe340bc6 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
@@ -368,10 +368,8 @@ public class Export extends ExportBaseCommand {
         Path docker = Path.of(buildDir).resolve("src/main/docker");
         Files.createDirectories(docker);
         String[] ids = gav.split(":");
-        // we only support and have docker files for java 17 or 21
-        String v = javaVersion.equals("17") ? "17" : "21";
         InputStream is
-                = 
ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/Dockerfile"
 + v + ".tmpl");
+                = 
ExportCamelMain.class.getClassLoader().getResourceAsStream("templates/Dockerfile21.tmpl");
         String context = IOHelper.loadText(is);
         IOHelper.close(is);
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
index 435119ffe579..81f5970955c7 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java
@@ -64,8 +64,8 @@ public final class CamelJBangConstants {
               javaType = "String")
     public static final String GAV = "camel.jbang.gav";
 
-    @Metadata(description = "Java version (17 or 21)",
-              javaType = "String", enums = "17,21", defaultValue = "21")
+    @Metadata(description = "Java version",
+              javaType = "String", enums = "21", defaultValue = "21")
     public static final String JAVA_VERSION = "camel.jbang.javaVersion";
 
     @Metadata(description = "Apache Camel Kamelets version. By default the 
Kamelets are the same version as Camel.",
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile17.tmpl
 
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile17.tmpl
deleted file mode 100644
index c57a8c7abdc1..000000000000
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile17.tmpl
+++ /dev/null
@@ -1,97 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements.  See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-# The ASF licenses this file to You under the Apache License, Version 2.0
-# (the "License"); you may not use this file except in compliance with
-# the License.  You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-####
-# This Dockerfile is used in order to build a container that runs the Camel 
application
-#
-# ./mvnw clean package
-# docker build -f src/main/docker/Dockerfile -t {{ .ArtifactId }}:{{ .Version 
}} .
-# docker run -it {{ .ArtifactId }}:{{ .Version }}
-#
-# This image uses the `run-java.sh` script to run the application.
-# This scripts computes the command line to execute your Java application, and
-# includes memory/GC tuning.
-# You can configure the behavior using the following environment properties:
-# - JAVA_OPTS: JVM options passed to the `java` command (example: 
"-verbose:class")
-# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated 
options
-#   in JAVA_OPTS (example: "-Dsome.property=foo")
-# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. 
This is
-#   used to calculate a default maximal heap memory based on a containers 
restriction.
-#   If used in a container without any memory constraints for the container 
then this
-#   option has no effect. If there is a memory constraint then `-Xmx` is set 
to a ratio
-#   of the container available memory as set here. The default is `50` which 
means 50%
-#   of the available memory is used as an upper boundary. You can skip this 
mechanism by
-#   setting this value to `0` in which case no `-Xmx` option is added.
-# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in 
JAVA_OPTS. This
-#   is used to calculate a default initial heap memory based on the maximum 
heap memory.
-#   If used in a container without any memory constraints for the container 
then this
-#   option has no effect. If there is a memory constraint then `-Xms` is set 
to a ratio
-#   of the `-Xmx` memory as set here. The default is `25` which means 25% of 
the `-Xmx`
-#   is used as the initial heap size. You can skip this mechanism by setting 
this value
-#   to `0` in which case no `-Xms` option is added (example: "25")
-# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
-#   This is used to calculate the maximum value of the initial heap memory. If 
used in
-#   a container without any memory constraints for the container then this 
option has
-#   no effect. If there is a memory constraint then `-Xms` is limited to the 
value set
-#   here. The default is 4096MB which means the calculated value of `-Xms` 
never will
-#   be greater than 4096MB. The value of this variable is expressed in MB 
(example: "4096")
-# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard 
output
-#   when things are happening. This option, if set to true, will set
-#  `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
-# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by 
default (example:
-#    true").
-# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 
(example: "8787").
-# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
-#   https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. 
(example: "2")
-# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: 
"1024").
-# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid 
expansion.
-#   (example: "20")
-# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid 
shrinking.
-#   (example: "40")
-# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage 
collection.
-#   (example: "4")
-# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time 
versus
-#   previous GC times. (example: "90")
-# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
-# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
-# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable 
should
-#   contain the necessary JRE command-line options to specify the required GC, 
which
-#   will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
-# - HTTPS_PROXY: The location of the https proxy. (example: 
"[email protected]:8080")
-# - HTTP_PROXY: The location of the http proxy. (example: 
"[email protected]:8080")
-# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that 
can be
-#   accessed directly. (example: "foo.example.com,bar.example.com")
-#
-# If you want to include the debug port into your docker image
-# you will have to expose the debug port (default 5005 being the default) like 
this :  EXPOSE 8080 5005.
-# Additionally you will have to set -e JAVA_DEBUG=true and -e 
JAVA_DEBUG_PORT=*:5005
-# when running the container
-#
-###
-FROM registry.access.redhat.com/ubi8/openjdk-17:1.23
-
-COPY --chown=185 target/{{ .AppJar }} /deployments/
-
-# Uncomment to expose any given port
-# EXPOSE 8080
-USER 185
-# Uncomment to provide any Java option
-# ENV JAVA_OPTS=""
-ENV JAVA_APP_JAR="/deployments/{{ .AppJar }}"
-
-ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
-
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
index 8039058119dd..26e025f61cb6 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportMainJibTest.java
@@ -61,14 +61,14 @@ class ExportMainJibTest {
 
     @ParameterizedTest
     @MethodSource("runtimeProvider")
-    public void shouldGenerateJava17(RuntimeType rt) throws Exception {
+    public void shouldGenerateExplicitJava21(RuntimeType rt) throws Exception {
         // prepare as we need application.properties that contains jib settings
         Files.copy(new 
File("src/test/resources/application-jib.properties").toPath(), 
profile.toPath(),
                 StandardCopyOption.REPLACE_EXISTING);
 
         Export command = new Export(new CamelJBangMain());
         CommandLine.populateCommand(command, "--gav=examples:route:1.0.0", 
"--dir=" + workingDir,
-                "--runtime=%s".formatted(rt.runtime()), "--java-version=17", 
"target/test-classes/route.yaml");
+                "--runtime=%s".formatted(rt.runtime()), "--java-version=21", 
"target/test-classes/route.yaml");
         int exit = command.doCall();
 
         Assertions.assertEquals(0, exit);
@@ -76,9 +76,9 @@ class ExportMainJibTest {
         Assertions.assertEquals("examples", model.getGroupId());
         Assertions.assertEquals("route", model.getArtifactId());
         Assertions.assertEquals("1.0.0", model.getVersion());
-        Assertions.assertEquals("17", 
model.getProperties().getProperty("java.version"));
+        Assertions.assertEquals("21", 
model.getProperties().getProperty("java.version"));
         Assertions.assertEquals("abc", 
model.getProperties().getProperty("jib.label"));
-        Assertions.assertEquals("mirror.gcr.io/library/eclipse-temurin:17-jre",
+        Assertions.assertEquals("mirror.gcr.io/library/eclipse-temurin:21-jre",
                 model.getProperties().getProperty("jib.from.image"));
 
         // should contain jib plugin
diff --git a/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java 
b/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java
index d47edb0f7140..57a7fd7f673d 100755
--- a/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java
+++ b/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java
@@ -17,7 +17,7 @@
  * limitations under the License.
  */
 
-//JAVA 17+
+//JAVA 21+
 //REPOS 
central=https://repo1.maven.org/maven2,apache-snapshot=https://repository.apache.org/content/groups/snapshots/
 //DEPS org.apache.camel:camel-bom:${camel.jbang.version:4.18.0}@pom
 //DEPS org.apache.camel:camel-jbang-core:${camel.jbang.version:4.18.0}
diff --git 
a/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java 
b/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java
index d47edb0f7140..57a7fd7f673d 100755
--- a/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java
+++ b/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java
@@ -17,7 +17,7 @@
  * limitations under the License.
  */
 
-//JAVA 17+
+//JAVA 21+
 //REPOS 
central=https://repo1.maven.org/maven2,apache-snapshot=https://repository.apache.org/content/groups/snapshots/
 //DEPS org.apache.camel:camel-bom:${camel.jbang.version:4.18.0}@pom
 //DEPS org.apache.camel:camel-jbang-core:${camel.jbang.version:4.18.0}
diff --git 
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/MigrationTools.java
 
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/MigrationTools.java
index 24654dd5f4c0..f62bc97157e2 100644
--- 
a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/MigrationTools.java
+++ 
b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/MigrationTools.java
@@ -128,11 +128,25 @@ public class MigrationTools {
         if (javaVersion != null && !javaVersion.isBlank()) {
             int javaVer = parseJavaVersion(javaVersion);
             boolean javaCompatible = true;
-            String requiredVersion = "17";
-
-            if (targetMajor >= 4 && javaVer < 17) {
-                javaCompatible = false;
-                blockers.add("Camel 4.x requires Java 17+. Current Java 
version is " + javaVersion + ".");
+            String requiredVersion;
+
+            if (targetMajor >= 4) {
+                int targetMinor = parseMinorVersion(targetVersion);
+                if (targetMajor > 4 || targetMinor >= 19) {
+                    requiredVersion = "21";
+                    if (javaVer < 21) {
+                        javaCompatible = false;
+                        blockers.add("Camel 4.19+ requires Java 21+. Current 
Java version is " + javaVersion + ".");
+                    }
+                } else {
+                    requiredVersion = "17";
+                    if (javaVer < 17) {
+                        javaCompatible = false;
+                        blockers.add("Camel 4.x requires Java 17+. Current 
Java version is " + javaVersion + ".");
+                    }
+                }
+            } else {
+                requiredVersion = "11";
             }
 
             javaCompat = new JavaCompatibility(javaVersion, requiredVersion, 
javaCompatible);
@@ -247,13 +261,9 @@ public class MigrationTools {
         List<String> javaUpgradeSuggestions = new ArrayList<>();
         if (javaVersion != null && !javaVersion.isBlank()) {
             int javaVer = parseJavaVersion(javaVersion);
-            if (javaVer < 17) {
+            if (javaVer < 21) {
                 javaUpgradeSuggestions.add(
-                        "Consider upgrading to Java 17. "
-                                           + "OpenRewrite recipe: 
org.openrewrite.java.migrate.UpgradeToJava17");
-            } else if (javaVer < 21) {
-                javaUpgradeSuggestions.add(
-                        "Consider upgrading to Java 21 for virtual threads 
support. "
+                        "Camel 4.19+ requires Java 21+. "
                                            + "OpenRewrite recipe: 
org.openrewrite.java.migrate.UpgradeToJava21");
             }
         }
@@ -325,6 +335,21 @@ public class MigrationTools {
         }
     }
 
+    private int parseMinorVersion(String version) {
+        if (version == null) {
+            return 0;
+        }
+        try {
+            String[] parts = version.split("\\.");
+            if (parts.length >= 2) {
+                return Integer.parseInt(parts[1]);
+            }
+            return 0;
+        } catch (NumberFormatException e) {
+            return 0;
+        }
+    }
+
     private int parseJavaVersion(String version) {
         if (version == null) {
             return 0;
diff --git a/pom.xml b/pom.xml
index 61815c06f3c1..70736b0783b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -110,7 +110,7 @@
         
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
         
<site-repo-url>scpexe://people.apache.org/www/camel.apache.org/maven/</site-repo-url>
-        <jdk.version>17</jdk.version>
+        <jdk.version>21</jdk.version>
         <!-- These two are here only to prevent the versions for the Apache 
parent pom from leaking-->
         <maven.compiler.source>${jdk.version}</maven.compiler.source>
         <maven.compiler.target>${jdk.version}</maven.compiler.target>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/customized-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/customized-v3/pom.xml
index eb7375e01afe..4988dbca8a88 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/customized-v3/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/customized-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <build>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/expanded-v3-yaml/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/expanded-v3-yaml/pom.xml
index 78fd49ec4d51..bb549c5814ad 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/expanded-v3-yaml/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/expanded-v3-yaml/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <dependencies>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-dto-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-dto-v3/pom.xml
index 621468eecf14..7c248f8d3742 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-dto-v3/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-dto-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <dependencies>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3-yaml/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3-yaml/pom.xml
index 308765b9d7b8..a02c2f5a541c 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3-yaml/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3-yaml/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <dependencies>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3/pom.xml
index 70cef1e80c53..25db335cca8f 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <dependencies>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-dto-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-dto-v3/pom.xml
index 9e98a3d9a456..d27608d2110a 100644
--- 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-dto-v3/pom.xml
+++ 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-dto-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <dependencies>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-v3/pom.xml
index 0340e5021494..5a7326b23674 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-v3/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-xml-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <build>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-dto-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-dto-v3/pom.xml
index 559095996dac..6cfc2c233e11 100644
--- 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-dto-v3/pom.xml
+++ 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-dto-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <dependencies>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-kamelet-v3/pom.xml
 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-kamelet-v3/pom.xml
index 7526d4e050b7..703d59d902b4 100644
--- 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-kamelet-v3/pom.xml
+++ 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-kamelet-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <build>
diff --git 
a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-v3/pom.xml 
b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-v3/pom.xml
index c0932b98d0d5..2b4d48d9abc5 100644
--- a/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-v3/pom.xml
+++ b/tooling/maven/camel-restdsl-openapi-plugin/src/it/simple-yaml-v3/pom.xml
@@ -29,9 +29,9 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <maven.compiler.release>17</maven.compiler.release>
-    <maven.compiler.source>17</maven.compiler.source>
-    <maven.compiler.target>17</maven.compiler.target>
+    <maven.compiler.release>21</maven.compiler.release>
+    <maven.compiler.source>21</maven.compiler.source>
+    <maven.compiler.target>21</maven.compiler.target>
   </properties>
 
   <build>

Reply via email to