You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2026/03/13 14:00:16 UTC

(camel) branch camel-jdk17-support created (now 834705b03dcf)

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

gnodet pushed a change to branch camel-jdk17-support
in repository https://gitbox.apache.org/repos/asf/camel.git


      at 834705b03dcf Lower minimum JDK requirement from 21 to 17

This branch includes the following new commits:

     new 834705b03dcf Lower minimum JDK requirement from 21 to 17

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(camel) 01/01: Lower minimum JDK requirement from 21 to 17

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch camel-jdk17-support
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 834705b03dcfa366c263e07c59f334ad4f6e81cc
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Mar 13 15:00:00 2026 +0100

    Lower minimum JDK requirement from 21 to 17
    
    - Change jdk.version from 21 to 17 in root pom.xml
    - Create JDK 17 fallback for CamelThreadFactory using new Thread()
    - Move JDK 21 CamelThreadFactory (virtual threads) to MRJAR java21/ directory
    - Replace List.getLast() (JDK 21) with index-based access in JsonObject
    - Replace String.splitWithDelimiters() (JDK 21) with Pattern/Matcher in JsonObject
    - Add @EnabledForJreRange(min=JAVA_21) to ManagedVirtualThreadExecutorTest
    
    Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
 .../ManagedVirtualThreadExecutorTest.java          |  3 ++
 .../camel/util/concurrent/CamelThreadFactory.java  | 35 ++++------------------
 .../camel/util/concurrent/CamelThreadFactory.java  |  0
 pom.xml                                            |  2 +-
 .../org/apache/camel/util/json/JsonObject.java     | 22 ++++++++++++--
 5 files changed, 29 insertions(+), 33 deletions(-)

diff --git a/core/camel-management/src/test/java/org/apache/camel/management/ManagedVirtualThreadExecutorTest.java b/core/camel-management/src/test/java/org/apache/camel/management/ManagedVirtualThreadExecutorTest.java
index e6e4d500689d..bc823a9f2adb 100644
--- a/core/camel-management/src/test/java/org/apache/camel/management/ManagedVirtualThreadExecutorTest.java
+++ b/core/camel-management/src/test/java/org/apache/camel/management/ManagedVirtualThreadExecutorTest.java
@@ -26,12 +26,15 @@ import org.apache.camel.CamelContext;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.spi.LifecycleStrategy;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledForJreRange;
+import org.junit.jupiter.api.condition.JRE;
 
 import static org.apache.camel.management.DefaultManagementObjectNameStrategy.TYPE_THREAD_POOL;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+@EnabledForJreRange(min = JRE.JAVA_21)
 public class ManagedVirtualThreadExecutorTest extends ManagementTestSupport {
 
     private ExecutorService vte;
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 4bb630479974..638fcf1b399d 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
@@ -20,8 +20,9 @@ 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}.
+ * Thread factory which creates threads supporting a naming pattern. On JDK 21+, this factory creates virtual threads
+ * when the System property {@code camel.threads.virtual.enabled} is set to {@code true}. On JDK 17, only platform
+ * threads are available.
  */
 public final class CamelThreadFactory implements ThreadFactoryTypeAware {
     private static final Logger LOG = LoggerFactory.getLogger(CamelThreadFactory.class);
@@ -29,25 +30,24 @@ public final class CamelThreadFactory implements ThreadFactoryTypeAware {
     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 ? ThreadFactoryType.current() : ThreadFactoryType.PLATFORM;
     }
 
     @Override
     public boolean isVirtual() {
-        return threadType == ThreadFactoryType.VIRTUAL;
+        return false;
     }
 
     @Override
     public Thread newThread(Runnable runnable) {
         String threadName = ThreadHelper.resolveThreadName(pattern, name);
 
-        Thread answer = threadType.newThread(threadName, daemon, runnable);
+        Thread answer = new Thread(runnable, threadName);
+        answer.setDaemon(daemon);
 
         LOG.trace("Created thread[{}] -> {}", threadName, answer);
         return answer;
@@ -61,27 +61,4 @@ public final class CamelThreadFactory implements ThreadFactoryTypeAware {
     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/CamelThreadFactory.java b/core/camel-util/src/main/java21/org/apache/camel/util/concurrent/CamelThreadFactory.java
similarity index 100%
copy from core/camel-util/src/main/java/org/apache/camel/util/concurrent/CamelThreadFactory.java
copy to core/camel-util/src/main/java21/org/apache/camel/util/concurrent/CamelThreadFactory.java
diff --git a/pom.xml b/pom.xml
index 6690a991d31b..acf6827876ca 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>21</jdk.version>
+        <jdk.version>17</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/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java b/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
index d361e0b05179..a6be47747d96 100644
--- a/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
+++ b/tooling/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
@@ -20,12 +20,15 @@ import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.math.BigDecimal;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * JsonObject is a common non-thread safe data format for string to data mappings. The contents of a JsonObject are only
@@ -194,7 +197,7 @@ public class JsonObject extends LinkedHashMap<String, Object> implements Jsonabl
             if (pos != -1 && answer instanceof List<?> arr) {
                 jo = null;
                 if (pos == Integer.MAX_VALUE) {
-                    answer = arr.getLast();
+                    answer = arr.get(arr.size() - 1);
                 } else if (pos < arr.size()) {
                     answer = arr.get(pos);
                 } else {
@@ -230,10 +233,23 @@ public class JsonObject extends LinkedHashMap<String, Object> implements Jsonabl
         return JsonObject.class.cast(o);
     }
 
+    private static String[] splitWithDelimiters(String input, String regex) {
+        List<String> parts = new ArrayList<>();
+        Matcher m = Pattern.compile(regex).matcher(input);
+        int lastEnd = 0;
+        while (m.find()) {
+            parts.add(input.substring(lastEnd, m.start()));
+            parts.add(m.group());
+            lastEnd = m.end();
+        }
+        parts.add(input.substring(lastEnd));
+        return parts.toArray(new String[0]);
+    }
+
     private Optional<Object> doPath(final String path) {
         Object answer = null;
 
-        String[] split = path.splitWithDelimiters("(\\?\\.|\\.)", 0);
+        String[] split = splitWithDelimiters(path, "(\\?\\.|\\.)");
         for (int i = 0; i < split.length; i = i + 2) {
             String part = split[i];
             String dot = i > 0 ? split[i - 1] : null;
@@ -262,7 +278,7 @@ public class JsonObject extends LinkedHashMap<String, Object> implements Jsonabl
             }
             if (pos != -1 && answer instanceof List<?> arr) {
                 if (pos == Integer.MAX_VALUE) {
-                    answer = arr.getLast();
+                    answer = arr.get(arr.size() - 1);
                 } else if (pos < arr.size()) {
                     answer = arr.get(pos);
                 } else {