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 <[email protected]>
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 <[email protected]>
---
 .../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 {

Reply via email to