From 50b25183d4d4dbef40a3230516c0d24fcc2a9cc6 Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Mon, 2 Mar 2026 10:55:14 +0100 Subject: [PATCH 1/4] 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 --- .../workflows/alternative-os-build-main.yml | 2 +- .github/workflows/generate-sbom-main.yml | 2 +- .github/workflows/pr-build-main.yml | 5 +- .../workflows/pr-manual-component-test.yml | 2 +- .github/workflows/security-scan.yml | 4 +- AGENTS.md | 2 +- Jenkinsfile | 33 +------ Jenkinsfile.deploy | 2 +- Jenkinsfile.jbangtest | 2 +- .../modules/contributing/pages/building.adoc | 4 +- .../modules/contributing/pages/index.adoc | 2 +- .../camel/dsl/jbang/core/commands/Export.java | 4 +- .../resources/templates/Dockerfile17.tmpl | 97 ------------------- 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 +- 24 files changed, 49 insertions(+), 174 deletions(-) delete mode 100644 dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile17.tmpl diff --git a/.github/workflows/alternative-os-build-main.yml b/.github/workflows/alternative-os-build-main.yml index 170688ce45209..fc81eab36209b 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 113d6096abab7..6b0460766395a 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 569680d03531d..9467f7fe951e5 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 1e186e1e199f0..ef88b148f140c 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 2d7bfdc3ef49e..c5fa606e36436 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 f2f3385bef390..632f852c83825 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 b49f2bab0cc38..bbabca5708eb0 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 405b786d93af7..5c1db358ac001 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 63729151045c7..7b0b4807f0243 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/docs/main/modules/contributing/pages/building.adoc b/docs/main/modules/contributing/pages/building.adoc index 1a15528e90591..af94197333021 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 9df2eabad0c55..246d385b6b33d 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/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 7ac476c14e9b9..8b63fe340bc68 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 @@ protected void copyDockerFiles(String buildDir) throws Exception { 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/resources/templates/Dockerfile17.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile17.tmpl deleted file mode 100644 index c57a8c7abdc10..0000000000000 --- 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: "myuser@127.0.0.1:8080") -# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1: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/pom.xml b/pom.xml index 61815c06f3c16..70736b0783b10 100644 --- a/pom.xml +++ b/pom.xml @@ -110,7 +110,7 @@ UTF-8 scpexe://people.apache.org/www/camel.apache.org/maven/ - 17 + 21 ${jdk.version} ${jdk.version} 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 eb7375e01afeb..4988dbca8a882 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 78fd49ec4d51a..bb549c5814ade 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 621468eecf14f..7c248f8d3742f 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 308765b9d7b80..a02c2f5a541c6 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 70cef1e80c53c..25db335cca8f0 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 9e98a3d9a4563..d27608d2110a8 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 0340e50214942..5a7326b23674c 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 559095996dac1..6cfc2c233e113 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 7526d4e050b7e..703d59d902b44 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 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 c0932b98d0d59..2b4d48d9abc56 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 @@ UTF-8 - 17 - 17 - 17 + 21 + 21 + 21 From ce62c6d5882530093195df2a546332cf22531415 Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Tue, 3 Mar 2026 19:45:36 +0100 Subject: [PATCH 2/4] 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 --- core/camel-support/pom.xml | 49 ----- .../support/DefaultThreadPoolFactory.java | 151 +++++++++---- .../support/DefaultThreadPoolFactory.java | 208 ------------------ core/camel-util/pom.xml | 47 ---- .../util/concurrent/CamelThreadFactory.java | 42 +++- .../camel/util/concurrent/ThreadType.java | 18 +- .../util/concurrent/CamelThreadFactory.java | 91 -------- .../camel/util/concurrent/ThreadType.java | 42 ---- 8 files changed, 161 insertions(+), 487 deletions(-) delete mode 100644 core/camel-support/src/main/java21/org/apache/camel/support/DefaultThreadPoolFactory.java delete mode 100644 core/camel-util/src/main/java21/org/apache/camel/util/concurrent/CamelThreadFactory.java delete mode 100644 core/camel-util/src/main/java21/org/apache/camel/util/concurrent/ThreadType.java diff --git a/core/camel-support/pom.xml b/core/camel-support/pom.xml index cc010e72eb6da..9480c6c1b48bf 100644 --- a/core/camel-support/pom.xml +++ b/core/camel-support/pom.xml @@ -85,53 +85,4 @@ - - - java-21-sources - - [21,) - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin-version} - - - default-compile - compile - - compile - - - - compile-java-21 - compile - - compile - - - 21 - ${project.basedir}/src/main/java21 - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - true - - - - - - - - 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 aa9c68845dab7..8fee4c9efd828 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.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. @@ -57,7 +59,7 @@ public void setCamelContext(CamelContext camelContext) { @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 ExecutorService newThreadPool( 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,118 @@ public ExecutorService newThreadPool( throw new IllegalArgumentException( "MaxPoolSize must be >= corePoolSize, was " + maxPoolSize + " >= " + corePoolSize); } - - BlockingQueue 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 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 8fee4c9efd828..0000000000000 --- 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 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 1f5d4115a181c..242635ad773f2 100644 --- a/core/camel-util/pom.xml +++ b/core/camel-util/pom.xml @@ -272,52 +272,5 @@ - - java-21-sources - - [21,) - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin-version} - - - default-compile - compile - - compile - - - - compile-java-21 - compile - - compile - - - 21 - ${project.basedir}/src/main/java21 - true - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - true - - - - - - - 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 570e02796c09d..2ecd57f91c859 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,41 @@ */ 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. + * 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 +64,27 @@ public String getName() { 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 b048a2640c9c0..9ec785c510a27 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,27 @@ */ 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 + * 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 d6c54ddc692ad..0000000000000 --- 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 16a9401371d24..0000000000000 --- 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; - } -} From dd8b2b642e86d9f7f3b1e224d1a14e3cedde1ceb Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Tue, 3 Mar 2026 20:38:13 +0100 Subject: [PATCH 3/4] 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 --- .../camel-jbang-configuration-metadata.json | 2 +- .../modules/ROOT/pages/camel-jbang.adoc | 2 +- .../camel-jbang-configuration-metadata.json | 2 +- .../core/common/CamelJBangConstants.java | 4 +- .../core/commands/ExportMainJibTest.java | 8 ++-- .../camel-jbang-main/dist/CamelJBang.java | 2 +- .../src/main/jbang/main/CamelJBang.java | 2 +- .../core/commands/mcp/MigrationTools.java | 47 ++++++++++++++----- 8 files changed, 47 insertions(+), 22 deletions(-) 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 01c0f4bbcdec2..7249ffadeb292 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/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc index f8337ba604803..875d9b496b110 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 01c0f4bbcdec2..7249ffadeb292 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/common/CamelJBangConstants.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/CamelJBangConstants.java index 435119ffe579e..81f5970955c76 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/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 8039058119dd5..26e025f61cb67 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 @@ private static Stream runtimeProvider() { @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 @@ public void shouldGenerateJava17(RuntimeType rt) throws Exception { 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 d47edb0f71406..57a7fd7f673d0 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 d47edb0f71406..57a7fd7f673d0 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 24654dd5f4c0a..f62bc97157e2d 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 CompatibilityResult camel_migration_compatibility( 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 MigrationRecipesResult camel_migration_recipes( List 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 @@ private int parseMajorVersion(String version) { } } + 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; From 8effdef9ae6e93274bc4b38c8eb9e052ee72f4ab Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Wed, 4 Mar 2026 10:05:06 +0100 Subject: [PATCH 4/4] Regen Signed-off-by: Andrea Cosentino --- .../support/DefaultThreadPoolFactory.java | 19 +++++++++++-------- .../util/concurrent/CamelThreadFactory.java | 5 ++--- .../camel/util/concurrent/ThreadType.java | 6 ++++-- 3 files changed, 17 insertions(+), 13 deletions(-) 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 8fee4c9efd828..c69d555511b1d 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,8 +37,8 @@ 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; +import org.apache.camel.util.concurrent.ThreadType; /** * Factory for thread pools that uses the JDK {@link Executors} for creating the thread pools. @@ -146,7 +146,8 @@ ScheduledExecutorService newScheduledThreadPool(ThreadPoolProfile profile, Threa } ScheduledThreadPoolExecutor answer - = new RejectableScheduledThreadPoolExecutor(profile.getPoolSize(), threadFactory, rejectedExecutionHandler); + = 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 @@ -166,10 +167,12 @@ ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { } @Override - ExecutorService newThreadPool(int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit timeUnit, - int maxQueueSize, boolean allowCoreThreadTimeOut, - RejectedExecutionHandler rejectedExecutionHandler, - ThreadFactory threadFactory) throws IllegalArgumentException { + ExecutorService newThreadPool( + int corePoolSize, int maxPoolSize, long keepAliveTime, TimeUnit timeUnit, + int maxQueueSize, boolean allowCoreThreadTimeOut, + RejectedExecutionHandler rejectedExecutionHandler, + ThreadFactory threadFactory) + throws IllegalArgumentException { return Executors.newThreadPerTaskExecutor(threadFactory); } @@ -191,8 +194,8 @@ 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; + return maxPoolSize > 1 && threadFactory instanceof ThreadFactoryTypeAware factoryTypeAware + && factoryTypeAware.isVirtual() ? ThreadPoolFactoryType.VIRTUAL : ThreadPoolFactoryType.PLATFORM; } abstract ExecutorService newCachedThreadPool(ThreadFactory threadFactory); 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 2ecd57f91c859..9c179c7ba1981 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,9 +20,8 @@ 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. 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); 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 9ec785c510a27..c43926be2df67 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 @@ -21,12 +21,13 @@ /** * 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. + * {@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 { @@ -36,6 +37,7 @@ public enum ThreadType { LOG.debug("The type of thread detected is: {}", CURRENT); } } + public static ThreadType current() { return CURRENT; }