From 05c3d1470467defc4520ff885c053371648aca14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Wed, 17 Sep 2025 22:41:13 +0200 Subject: [PATCH 01/24] Use of GitHub Actions, and enable dependabot Keep a backup of Jenkinsfile for now --- .asf.yaml | 25 ++++++++++++++-- .github/dependabot.yml | 36 +++++++++++++++++++++++ .github/workflows/build.yml | 52 ++++++++++++++++++++++++++++++++++ .github/workflows/deploy.yml | 41 +++++++++++++++++++++++++++ Jenkinsfile => Jenkinsfile.bak | 0 5 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/deploy.yml rename Jenkinsfile => Jenkinsfile.bak (100%) diff --git a/.asf.yaml b/.asf.yaml index 8c334b1714..211ce41674 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -29,12 +29,33 @@ github: - stomp - java - jms + enabled_merge_buttons: squash: true - merge: true - rebase: true + merge: false + rebase: false + + del_branch_on_merge: true + + protected_branches: + main: + required_pull_request_reviews: + require_code_owner_reviews: false + required_approving_review_count: 0 + required_linear_history: true + required_status_checks: + strict: false + contexts: + - build + + features: + wiki: false + issues: false + projects: false + autolink_jira: - AMQ + notifications: commits: commits@activemq.apache.org issues: gitbox@activemq.apache.org diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..686695e99a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,36 @@ +# +# 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. +# + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 50 + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..8534197e9a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,52 @@ +# +# 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. +# + +name: Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + permissions: + contents: read + + strategy: + matrix: + os: [ ubuntu-latest, windows-latest ] + java-version: [ 17, 21, 24 ] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java-version }} + - name: Build + run: mvn -U -B -e clean install -DskipTests + - name: Verify + run: mvn apache-rat:check + - name: Test + run: mvn -B -e -fae test -Dsurefire.rerunFailingTestsCount=3 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000..9b623ab17a --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,41 @@ +# +# 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. +# + +name: Deploy + +on: + schedule: + - cron: '0 0 * * *' + +jobs: + deploy: + + permissions: + contents: read + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: 17 + - name: Deploy + run: mvn -B -e deploy -Pdeploy -DskipTests diff --git a/Jenkinsfile b/Jenkinsfile.bak similarity index 100% rename from Jenkinsfile rename to Jenkinsfile.bak From fdcd933036cd0137bd438d25f11a66a39b661402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sat, 20 Sep 2025 08:51:21 +0200 Subject: [PATCH 02/24] Include push/PR on activemq-6.1.x and activemq-5.19.x branches --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8534197e9a..135e4b47c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,9 +21,9 @@ name: Build on: push: - branches: [ "main" ] + branches: [ "main", "activemq-6.1.x", "activemq-5.19.x" ] pull_request: - branches: [ "main" ] + branches: [ "main", "activemq-6.1.x", "activemq-5.19.x" ] jobs: build: From c23ef1d4c42a9e72e12d2b9c0898a0cbe2c210e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sat, 20 Sep 2025 08:59:55 +0200 Subject: [PATCH 03/24] Add new runners for the build --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 135e4b47c5..82fcbb7d31 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -33,7 +33,7 @@ jobs: strategy: matrix: - os: [ ubuntu-latest, windows-latest ] + os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] java-version: [ 17, 21, 24 ] runs-on: ${{ matrix.os }} From f6f60fcc2f7d9c488b6094994ca191bda08b2096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sun, 21 Sep 2025 15:48:45 +0200 Subject: [PATCH 04/24] Set Java distribution --- .github/workflows/build.yml | 1 + .github/workflows/deploy.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 82fcbb7d31..6f6473e3c0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,6 +44,7 @@ jobs: uses: actions/setup-java@v4 with: java-version: ${{ matrix.java-version }} + distribution: temurin - name: Build run: mvn -U -B -e clean install -DskipTests - name: Verify diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9b623ab17a..dd94e3cb0d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -37,5 +37,6 @@ jobs: uses: actions/setup-java@v4 with: java-version: 17 + distribution: temurin - name: Deploy run: mvn -B -e deploy -Pdeploy -DskipTests From 82985aa8b1bb50c7aa0890e4f12449e4dd180ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sun, 21 Sep 2025 16:06:02 +0200 Subject: [PATCH 05/24] Remove surefire rerun options as deprecated --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f6473e3c0..9a3370bc16 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -50,4 +50,4 @@ jobs: - name: Verify run: mvn apache-rat:check - name: Test - run: mvn -B -e -fae test -Dsurefire.rerunFailingTestsCount=3 + run: mvn -B -e -fae test From 2cf3e7c1f5f5bc3e21cd11f0e048439206f00aec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sun, 21 Sep 2025 16:19:24 +0200 Subject: [PATCH 06/24] Removing JDK 24 for now as the tests will fail due to the SecurityManager --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a3370bc16..316d3b2674 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: strategy: matrix: os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] - java-version: [ 17, 21, 24 ] + java-version: [ 17, 21 ] runs-on: ${{ matrix.os }} From 98a37d4ab716a55a89fc4c54e6b3c43323ac8f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sun, 21 Sep 2025 16:27:07 +0200 Subject: [PATCH 07/24] Remove JDK 21 as the tests will fail due to SecurityManager --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 316d3b2674..b80c51b609 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: strategy: matrix: os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] - java-version: [ 17, 21 ] + java-version: [ 17 ] runs-on: ${{ matrix.os }} From cbfd8d5926a50780935d1ebc5ca0f452f92fdbfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Mon, 22 Sep 2025 07:44:34 +0200 Subject: [PATCH 08/24] Use separated jobs for build and test (to use different JDK matrix) Re-add -Dsurefire.rerunFailingTestsCount=3 option to tests --- .asf.yaml | 1 + .github/workflows/build.yml | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index 211ce41674..ff4712e1fa 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -47,6 +47,7 @@ github: strict: false contexts: - build + - test features: wiki: false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b80c51b609..0befa462da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -34,7 +34,7 @@ jobs: strategy: matrix: os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] - java-version: [ 17 ] + java-version: [ 17, 21, 24 ] runs-on: ${{ matrix.os }} @@ -49,5 +49,25 @@ jobs: run: mvn -U -B -e clean install -DskipTests - name: Verify run: mvn apache-rat:check + + test: + + permissions: + contents: read + + strategy: + matrix: + os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] + java-version: [ 17 ] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java-version }} + distribution: temurin - name: Test - run: mvn -B -e -fae test + run: mvn -B -e -fae test -Dsurefire.rerunFailingTestsCount=3 From 95a17dda26986c996b8fafd4b781c4d59e2ff9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Mon, 22 Sep 2025 07:50:35 +0200 Subject: [PATCH 09/24] Update right GitHub Action syntax for options --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0befa462da..785dc55a2f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,4 +70,4 @@ jobs: java-version: ${{ matrix.java-version }} distribution: temurin - name: Test - run: mvn -B -e -fae test -Dsurefire.rerunFailingTestsCount=3 + run: mvn -B -e -fae test "-Dsurefire.rerunFailingTestsCount=3" From ab3f6e8b9993a2cccb1629984232035ad5495c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Mon, 22 Sep 2025 11:45:26 +0200 Subject: [PATCH 10/24] Re-add Jenkinsfile with daily schedule, building only on s390x and including Sonar stage --- Jenkinsfile.bak => Jenkinsfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) rename Jenkinsfile.bak => Jenkinsfile (98%) diff --git a/Jenkinsfile.bak b/Jenkinsfile similarity index 98% rename from Jenkinsfile.bak rename to Jenkinsfile index 94a8c7a772..4022a4f5b5 100644 --- a/Jenkinsfile.bak +++ b/Jenkinsfile @@ -27,6 +27,10 @@ pipeline { } } + triggers { + cron('0 0 * * *') + } + tools { // ... tell Jenkins what java version, maven version or other tools are required ... maven 'maven_3_latest' @@ -42,7 +46,7 @@ pipeline { } parameters { - choice(name: 'nodeLabel', choices: ['ubuntu', 's390x', 'arm', 'Windows']) + choice(name: 'nodeLabel', choices: [ 's390x']) choice(name: 'jdkVersion', choices: ['jdk_17_latest', 'jdk_21_latest', 'jdk_24_latest', 'jdk_17_latest_windows', 'jdk_21_latest_windows', 'jdk_24_latest_windows']) booleanParam(name: 'deployEnabled', defaultValue: false) booleanParam(name: 'parallelTestsEnabled', defaultValue: true) From 7864a66816b5d676429b03d5a16d9ddde7706cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Mon, 22 Sep 2025 11:48:51 +0200 Subject: [PATCH 11/24] Fix surefire argLine and set memory configuration --- activemq-kahadb-store/pom.xml | 4 ++++ pom.xml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/activemq-kahadb-store/pom.xml b/activemq-kahadb-store/pom.xml index b069f36d7c..5af77791c7 100644 --- a/activemq-kahadb-store/pom.xml +++ b/activemq-kahadb-store/pom.xml @@ -30,6 +30,10 @@ ActiveMQ :: KahaDB Store The ActiveMQ KahaDB Store Implementation + + -Xmx512M + + diff --git a/pom.xml b/pom.xml index e7b3ad99d3..f4812925cb 100644 --- a/pom.xml +++ b/pom.xml @@ -969,13 +969,12 @@ true 1 true - -enableassertions false true true - -Xmx512m + -enableassertions -Xmx1G From 29151fec2d8b13909d3c663059e96cebd67e0b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Sat, 27 Sep 2025 08:28:34 +0200 Subject: [PATCH 12/24] Temporary ignore JournalCorruptionEofIndexRecoveryTest to test the GitHub Action CI --- .../store/kahadb/JournalCorruptionEofIndexRecoveryTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java b/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java index a9b4c52258..8623d8b736 100644 --- a/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java +++ b/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java @@ -63,12 +63,13 @@ import org.apache.logging.log4j.core.layout.MessageLayout; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.event.LoggingEvent; - +@Ignore("Temporary to test GitHub Action") public class JournalCorruptionEofIndexRecoveryTest { private static final Logger LOG = LoggerFactory.getLogger(JournalCorruptionEofIndexRecoveryTest.class); From 72072da02fb43809d0064b9ac8968525323eedd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Fri, 12 Dec 2025 14:28:45 +0100 Subject: [PATCH 13/24] Remove heap memory setting and renable KahaDB test --- activemq-kahadb-store/pom.xml | 4 ---- .../store/kahadb/JournalCorruptionEofIndexRecoveryTest.java | 1 - pom.xml | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/activemq-kahadb-store/pom.xml b/activemq-kahadb-store/pom.xml index 5af77791c7..b069f36d7c 100644 --- a/activemq-kahadb-store/pom.xml +++ b/activemq-kahadb-store/pom.xml @@ -30,10 +30,6 @@ ActiveMQ :: KahaDB Store The ActiveMQ KahaDB Store Implementation - - -Xmx512M - - diff --git a/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java b/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java index 8623d8b736..c3b9fc2046 100644 --- a/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java +++ b/activemq-kahadb-store/src/test/java/org/apache/activemq/store/kahadb/JournalCorruptionEofIndexRecoveryTest.java @@ -69,7 +69,6 @@ import org.slf4j.LoggerFactory; import org.slf4j.event.LoggingEvent; -@Ignore("Temporary to test GitHub Action") public class JournalCorruptionEofIndexRecoveryTest { private static final Logger LOG = LoggerFactory.getLogger(JournalCorruptionEofIndexRecoveryTest.class); diff --git a/pom.xml b/pom.xml index f4812925cb..819b2b0e8c 100644 --- a/pom.xml +++ b/pom.xml @@ -974,7 +974,7 @@ true true - -enableassertions -Xmx1G + -enableassertions From 2473f968e9e817c826ddc5cb6df1e1b86a7b45f6 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Tue, 16 Dec 2025 15:47:31 +0100 Subject: [PATCH 14/24] Clear separation between development cycle and nightly full check --- .github/workflows/ci-nightly.yml | 69 +++++++++++++++++++ .github/workflows/{build.yml => ci-quick.yml} | 25 +++---- 2 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/ci-nightly.yml rename .github/workflows/{build.yml => ci-quick.yml} (74%) diff --git a/.github/workflows/ci-nightly.yml b/.github/workflows/ci-nightly.yml new file mode 100644 index 0000000000..51421af4c7 --- /dev/null +++ b/.github/workflows/ci-nightly.yml @@ -0,0 +1,69 @@ +# 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. + +name: CI Nightly + +on: + schedule: + - cron: '0 3 * * *' + +jobs: + build: + + permissions: + contents: read + + strategy: + matrix: + os: [ ubuntu-latest, ubuntu-22.04, macos-latest, macos-14, windows-latest, windows-2022 ] + java-version: [ 17, 21, 24 ] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java-version }} + distribution: temurin + - name: Build + run: mvn -U -B -e clean install -DskipTests + - name: Verify + run: mvn apache-rat:check + + test: + + permissions: + contents: read + + strategy: + matrix: + os: [ ubuntu-latest, ubuntu-22.04, macos-latest, macos-14, windows-latest, windows-2022 ] + java-version: [ 17, 21, 24 ] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java-version }} + distribution: temurin + - name: Test + run: mvn -B -e -fae test diff --git a/.github/workflows/build.yml b/.github/workflows/ci-quick.yml similarity index 74% rename from .github/workflows/build.yml rename to .github/workflows/ci-quick.yml index 785dc55a2f..f2e1a22a66 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/ci-quick.yml @@ -1,4 +1,3 @@ -# # 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 @@ -15,9 +14,8 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -# -name: Build +name: CI Quick on: push: @@ -33,14 +31,14 @@ jobs: strategy: matrix: - os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] - java-version: [ 17, 21, 24 ] + os: [ ubuntu-latest, macos-latest, windows-latest ] + java-version: [ 17, 21 ] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Set up JDK + - name: Set up JDK uses: actions/setup-java@v4 with: java-version: ${{ matrix.java-version }} @@ -51,23 +49,18 @@ jobs: run: mvn apache-rat:check test: - + permissions: contents: read - strategy: - matrix: - os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, macos-14, macos-13, windows-2025, windows-2022 ] - java-version: [ 17 ] - - runs-on: ${{ matrix.os }} + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up JDK + - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: ${{ matrix.java-version }} + java-version: 17 distribution: temurin - name: Test - run: mvn -B -e -fae test "-Dsurefire.rerunFailingTestsCount=3" + run: mvn -B -e -fae test From dcdabdb804ebdb34c43f1d871501846d29eea3de Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Tue, 16 Dec 2025 19:39:28 +0100 Subject: [PATCH 15/24] Adding logs to trigger a new build --- .../activemq/jms/pool/PooledConnectionSecurityExceptionTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java index 445f40feb3..d5b94b3d0f 100644 --- a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java +++ b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java @@ -111,6 +111,7 @@ public void onException(JMSException exception) { @Test public void testFailureGetsNewConnectionOnRetryLooped() throws Exception { for (int i = 0; i < 10; ++i) { + LOG.info("Iteration: {}", i); testFailureGetsNewConnectionOnRetry(); } } From 25ebb49bb10cc67558b0135f68dbbf7797bab5df Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Tue, 16 Dec 2025 20:41:49 +0100 Subject: [PATCH 16/24] Revert latest for OS versions --- .github/workflows/ci-nightly.yml | 4 ++-- .github/workflows/ci-quick.yml | 4 ++-- .github/workflows/deploy.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-nightly.yml b/.github/workflows/ci-nightly.yml index 51421af4c7..db29edce9e 100644 --- a/.github/workflows/ci-nightly.yml +++ b/.github/workflows/ci-nightly.yml @@ -29,7 +29,7 @@ jobs: strategy: matrix: - os: [ ubuntu-latest, ubuntu-22.04, macos-latest, macos-14, windows-latest, windows-2022 ] + os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, windows-2025, windows-2022 ] java-version: [ 17, 21, 24 ] runs-on: ${{ matrix.os }} @@ -53,7 +53,7 @@ jobs: strategy: matrix: - os: [ ubuntu-latest, ubuntu-22.04, macos-latest, macos-14, windows-latest, windows-2022 ] + os: [ ubuntu-24.04, ubuntu-22.04, macos-26, macos-15, windows-2025, windows-2022 ] java-version: [ 17, 21, 24 ] runs-on: ${{ matrix.os }} diff --git a/.github/workflows/ci-quick.yml b/.github/workflows/ci-quick.yml index f2e1a22a66..4fbd7fdabe 100644 --- a/.github/workflows/ci-quick.yml +++ b/.github/workflows/ci-quick.yml @@ -31,7 +31,7 @@ jobs: strategy: matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] + os: [ ubuntu-24.04, macos-26, windows-2025 ] java-version: [ 17, 21 ] runs-on: ${{ matrix.os }} @@ -53,7 +53,7 @@ jobs: permissions: contents: read - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dd94e3cb0d..253277c6c9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,7 +29,7 @@ jobs: permissions: contents: read - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 From deefb42ad731dbca5f03e8511ad7258109b90d31 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 00:30:22 +0100 Subject: [PATCH 17/24] Do not leak connections while constantly checking if the new connection is different from the failed one --- .../PooledConnectionSecurityExceptionTest.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java index d5b94b3d0f..3a7e86a1b3 100644 --- a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java +++ b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java @@ -16,6 +16,13 @@ */ package org.apache.activemq.jms.pool; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.List; + import jakarta.jms.Connection; import jakarta.jms.ExceptionListener; import jakarta.jms.JMSException; @@ -23,6 +30,7 @@ import jakarta.jms.MessageProducer; import jakarta.jms.Queue; import jakarta.jms.Session; + import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.broker.BrokerPlugin; import org.apache.activemq.broker.BrokerService; @@ -42,13 +50,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - /** * Test Pooled connections ability to handle security exceptions */ From b051180151096dd1d121b063b8810f8c3dfaa831 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 12:18:16 +0100 Subject: [PATCH 18/24] Avoid race conditions by waiting for the log before creating the second consumer. --- .../org/apache/activemq/usecases/UsageBlockedDispatchTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/usecases/UsageBlockedDispatchTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/usecases/UsageBlockedDispatchTest.java index d371076675..59c8b3934c 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/usecases/UsageBlockedDispatchTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/usecases/UsageBlockedDispatchTest.java @@ -26,6 +26,7 @@ import org.apache.activemq.command.ActiveMQQueue; import org.apache.activemq.usage.SystemUsage; import org.apache.activemq.util.DefaultTestAppender; +import org.apache.activemq.util.Wait; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LogEvent; @@ -154,6 +155,8 @@ public void append(LogEvent event) { try { + assertTrue("Timed out waiting for cursor to block", Wait.waitFor(() -> gotExpectedLogEvent.get())); + MessageConsumer noDispatchConsumer = consumerSession.createConsumer(shouldBeStuckForDispatch); Message m = noDispatchConsumer.receive(messageReceiveTimeout); From f2f9a26d40c0c8f44430f1b5b99e0996c2aa2487 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 13:39:27 +0100 Subject: [PATCH 19/24] [AMQ-9820]: closed connections leaking into the pool when reconnectOnException is used --- .../activemq/jms/pool/ConnectionPool.java | 1 + .../jms/pool/PooledConnectionFactory.java | 7 +---- ...PooledConnectionSecurityExceptionTest.java | 30 ++++++++++--------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java b/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java index b9830d3954..21c170cf67 100644 --- a/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java +++ b/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java @@ -125,6 +125,7 @@ public void start() throws JMSException { connection.start(); } catch (JMSException e) { started.set(false); + setHasExpired(true); if (isReconnectOnException()) { close(); } diff --git a/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/PooledConnectionFactory.java b/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/PooledConnectionFactory.java index 1b11531b45..d3a64e1934 100644 --- a/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/PooledConnectionFactory.java +++ b/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/PooledConnectionFactory.java @@ -129,12 +129,7 @@ public void destroyObject(ConnectionKey connectionKey, PooledObject pooledObject) { ConnectionPool connection = pooledObject.getObject(); - if (connection == null || connection.getConnection() == null) { - LOG.trace("Connection has been closed and will be destroyed: {}", connection); - return false; - } - - if (connection.expiredCheck()) { + if (connection != null && connection.expiredCheck()) { LOG.trace("Connection has expired: {} and will be destroyed", connection); return false; } diff --git a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java index 3a7e86a1b3..65def726dc 100644 --- a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java +++ b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java @@ -16,13 +16,6 @@ */ package org.apache.activemq.jms.pool; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; - import jakarta.jms.Connection; import jakarta.jms.ExceptionListener; import jakarta.jms.JMSException; @@ -30,7 +23,6 @@ import jakarta.jms.MessageProducer; import jakarta.jms.Queue; import jakarta.jms.Session; - import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.activemq.broker.BrokerPlugin; import org.apache.activemq.broker.BrokerService; @@ -50,6 +42,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + /** * Test Pooled connections ability to handle security exceptions */ @@ -112,7 +111,6 @@ public void onException(JMSException exception) { @Test public void testFailureGetsNewConnectionOnRetryLooped() throws Exception { for (int i = 0; i < 10; ++i) { - LOG.info("Iteration: {}", i); testFailureGetsNewConnectionOnRetry(); } } @@ -136,13 +134,15 @@ public void testFailureGetsNewConnectionOnRetry() throws Exception { @Override public boolean isSatisified() throws Exception { try (final PooledConnection newConnection = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { - return connection1.getConnection() != newConnection.getConnection(); + return connection1.pool != ((PooledConnection)newConnection).pool; + } catch (Exception e) { + return false; } } })); final PooledConnection connection2 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials"); - assertNotSame(connection1.getConnection(), connection2.getConnection()); + assertNotSame(connection1.pool, connection2.pool); try { connection2.start(); @@ -235,13 +235,15 @@ public void testFailoverWithInvalidCredentials() throws Exception { @Override public boolean isSatisified() throws Exception { try (final PooledConnection newConnection = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { - return connection1.getConnection() != newConnection.getConnection(); + return connection1.pool != ((PooledConnection)newConnection).pool; + } catch (Exception e) { + return false; } } })); final PooledConnection connection2 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials"); - assertNotSame(connection1.getConnection(), connection2.getConnection()); + assertNotSame(connection1.pool, connection2.pool); try { connection2.start(); @@ -412,4 +414,4 @@ protected BrokerPlugin configureAuthorization() throws Exception { return authorizationPlugin; } -} +} \ No newline at end of file From e25c8a087d01f266cf6a06e30ba9147fa274208e Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 22:23:33 +0100 Subject: [PATCH 20/24] try to avoid failures when stats are not fully synchronized --- .../NetworkAdvancedStatisticsTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java index e18a66c3b0..80846de0ff 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java @@ -164,6 +164,8 @@ public boolean isSatisified() throws Exception { assertTrue(receivedExceptions.isEmpty()); assertEquals(Integer.valueOf(MESSAGE_COUNT), Integer.valueOf(receivedMessages.size())); + waitForIncludedStatsToUpdate(); + //Make sure stats are correct for local -> remote assertEquals(MESSAGE_COUNT, localBroker.getDestination(includedDestination).getDestinationStatistics().getEnqueues().getCount()); assertEquals(MESSAGE_COUNT, localBroker.getDestination(includedDestination).getDestinationStatistics().getDequeues().getCount()); @@ -249,6 +251,24 @@ public boolean isSatisified() throws Exception { remoteConsumer.close(); } + private void waitForIncludedStatsToUpdate() throws Exception { + assertTrue("Included destination stats did not reach expected counts", + Wait.waitFor(new Condition() { + @Override + public boolean isSatisified() throws Exception { + return MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getEnqueues().getCount() + && MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getDequeues().getCount() + && MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getForwards().getCount() + && MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkDequeues().getCount() + && 0 == localBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkEnqueues().getCount() + && MESSAGE_COUNT == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getEnqueues().getCount() + && 0 == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getForwards().getCount() + && MESSAGE_COUNT == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkEnqueues().getCount() + && 0 == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkDequeues().getCount(); + } + }, 20000, 500)); + } + protected void assertNetworkBridgeStatistics(final long expectedLocalSent, final long expectedRemoteSent) throws Exception { final NetworkBridge localBridge = localBroker.getNetworkConnectors().get(0).activeBridges().iterator().next(); From 6a5b465f87dd4aba6e80230835fdfcc76d575474 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Thu, 18 Dec 2025 11:55:32 +0100 Subject: [PATCH 21/24] Increase the timeout to allow statistics to sync up --- .../NetworkAdvancedStatisticsTest.java | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java index 80846de0ff..c3cde8008e 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/network/NetworkAdvancedStatisticsTest.java @@ -110,7 +110,7 @@ protected String getLocalBrokerURI() { } //Added for AMQ-9437 test advancedStatistics for networkEnqueue and networkDequeue - @Test(timeout = 60 * 1000) + @Test(timeout = 120 * 1000) public void testNetworkAdvancedStatistics() throws Exception { // create a remote durable consumer to create demand @@ -159,13 +159,11 @@ public boolean isSatisified() throws Exception { // The number of message that remain is due to the exclude queue return receivedMessages.size() == MESSAGE_COUNT; } - }, 10000, 500)); + }, 30000, 500)); assertTrue(receivedExceptions.isEmpty()); assertEquals(Integer.valueOf(MESSAGE_COUNT), Integer.valueOf(receivedMessages.size())); - waitForIncludedStatsToUpdate(); - //Make sure stats are correct for local -> remote assertEquals(MESSAGE_COUNT, localBroker.getDestination(includedDestination).getDestinationStatistics().getEnqueues().getCount()); assertEquals(MESSAGE_COUNT, localBroker.getDestination(includedDestination).getDestinationStatistics().getDequeues().getCount()); @@ -238,7 +236,7 @@ public boolean isSatisified() throws Exception { public boolean isSatisified() throws Exception { return localBroker.getSystemUsage().getMemoryUsage().getUsage() == 0; } - }, 10000, 500)); + }, 30000, 500)); } else { assertTrue(Wait.waitFor(new Condition() { @Override @@ -246,29 +244,11 @@ public boolean isSatisified() throws Exception { // The number of message that remain is due to the exclude queue return localBroker.getAdminView().getTotalMessageCount() == MESSAGE_COUNT; } - }, 10000, 500)); + }, 30000, 500)); } remoteConsumer.close(); } - private void waitForIncludedStatsToUpdate() throws Exception { - assertTrue("Included destination stats did not reach expected counts", - Wait.waitFor(new Condition() { - @Override - public boolean isSatisified() throws Exception { - return MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getEnqueues().getCount() - && MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getDequeues().getCount() - && MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getForwards().getCount() - && MESSAGE_COUNT == localBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkDequeues().getCount() - && 0 == localBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkEnqueues().getCount() - && MESSAGE_COUNT == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getEnqueues().getCount() - && 0 == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getForwards().getCount() - && MESSAGE_COUNT == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkEnqueues().getCount() - && 0 == remoteBroker.getDestination(includedDestination).getDestinationStatistics().getNetworkDequeues().getCount(); - } - }, 20000, 500)); - } - protected void assertNetworkBridgeStatistics(final long expectedLocalSent, final long expectedRemoteSent) throws Exception { final NetworkBridge localBridge = localBroker.getNetworkConnectors().get(0).activeBridges().iterator().next(); @@ -285,4 +265,4 @@ public boolean isSatisified() throws Exception { })); } -} +} \ No newline at end of file From 4c034ebb13c61de08fa5f0ef268c2be1037fb923 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Thu, 18 Dec 2025 15:12:52 +0100 Subject: [PATCH 22/24] switch the latch and the counter, to make sure we wait before asserting the values bellow --- .../apache/activemq/jms2/ActiveMQJMS2MessageListenerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/jms2/ActiveMQJMS2MessageListenerTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/jms2/ActiveMQJMS2MessageListenerTest.java index 873c45b207..2ca9209820 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/jms2/ActiveMQJMS2MessageListenerTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/jms2/ActiveMQJMS2MessageListenerTest.java @@ -91,8 +91,8 @@ public void testMessageListener() { jmsConsumer.setMessageListener(new MessageListener() { @Override public void onMessage(Message message) { - countDownLatch.countDown(); receivedMessageCount.incrementAndGet(); + countDownLatch.countDown(); try { switch(ackMode) { case Session.CLIENT_ACKNOWLEDGE: message.acknowledge(); break; From e12071bab9ad0dfc0f89a07245af32395dff3ff7 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Thu, 18 Dec 2025 22:21:50 +0100 Subject: [PATCH 23/24] See if we can better fix the ConnectionPool --- .../activemq/jms/pool/ConnectionPool.java | 1 + ...PooledConnectionSecurityExceptionTest.java | 229 +++++++----------- 2 files changed, 88 insertions(+), 142 deletions(-) diff --git a/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java b/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java index 21c170cf67..6b8754beea 100644 --- a/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java +++ b/activemq-jms-pool/src/main/java/org/apache/activemq/jms/pool/ConnectionPool.java @@ -378,6 +378,7 @@ void setParentExceptionListener(ExceptionListener parentExceptionListener) { @Override public void onException(JMSException exception) { + setHasExpired(true); if (isReconnectOnException()) { close(); } diff --git a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java index 65def726dc..70809f754f 100644 --- a/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java +++ b/activemq-jms-pool/src/test/java/org/apache/activemq/jms/pool/PooledConnectionSecurityExceptionTest.java @@ -44,8 +44,11 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CountDownLatch; import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -65,47 +68,42 @@ public class PooledConnectionSecurityExceptionTest { @Test public void testFailedConnectThenSucceeds() throws JMSException { - Connection connection = pooledConnFact.createConnection("invalid", "credentials"); + try (final Connection connection1 = pooledConnFact.createConnection("invalid", "credentials")) { + assertThrows(JMSSecurityException.class, connection1::start); - try { - connection.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - } - - connection = pooledConnFact.createConnection("system", "manager"); - connection.start(); + try (final Connection connection2 = pooledConnFact.createConnection("system", "manager")) { + connection2.start(); - LOG.info("Successfully create new connection."); + } catch (final JMSSecurityException ex) { + fail("Should have succeeded to connect on 2nd attempt"); + } - connection.close(); + } } @Test - public void testFailedConnectThenSucceedsWithListener() throws JMSException { - Connection connection = pooledConnFact.createConnection("invalid", "credentials"); - connection.setExceptionListener(new ExceptionListener() { + public void testFailedConnectThenSucceedsWithListener() throws JMSException, InterruptedException { + final CountDownLatch onExceptionCalled = new CountDownLatch(1); + try (final Connection connection1 = pooledConnFact.createConnection("invalid", "credentials")) { + connection1.setExceptionListener(new ExceptionListener() { + + @Override + public void onException(JMSException exception) { + LOG.warn("Connection get error: {}", exception.getMessage()); + onExceptionCalled.countDown(); + } + }); + assertThrows(JMSSecurityException.class, connection1::start); + + try (final Connection connection2 = pooledConnFact.createConnection("system", "manager")) { + connection2.start(); - @Override - public void onException(JMSException exception) { - LOG.warn("Connection get error: {}", exception.getMessage()); + } catch (final JMSSecurityException ex) { + fail("Should have succeeded to connect on 2nd attempt"); } - }); - try { - connection.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); } - - connection = pooledConnFact.createConnection("system", "manager"); - connection.start(); - - LOG.info("Successfully create new connection."); - - connection.close(); + assertTrue("onException called", onExceptionCalled.await(10, java.util.concurrent.TimeUnit.SECONDS)); } @Test @@ -119,67 +117,41 @@ public void testFailureGetsNewConnectionOnRetryLooped() throws Exception { public void testFailureGetsNewConnectionOnRetry() throws Exception { pooledConnFact.setMaxConnections(1); - final PooledConnection connection1 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials"); - - try { - connection1.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - } - - // The pool should process the async error - assertTrue("Should get new connection", Wait.waitFor(new Wait.Condition() { - - @Override - public boolean isSatisified() throws Exception { - try (final PooledConnection newConnection = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { - return connection1.pool != ((PooledConnection)newConnection).pool; - } catch (Exception e) { - return false; + try (final Connection connection1 = pooledConnFact.createConnection("invalid", "credentials")) { + assertThrows(JMSSecurityException.class, connection1::start); + + // The pool should process the async error + // we should eventually get a different connection instance from the pool regardless of the underlying connection + assertTrue("Should get new connection", Wait.waitFor(new Wait.Condition() { + @Override + public boolean isSatisified() throws Exception { + try (final PooledConnection newConnection = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { + return connection1 != newConnection; + } catch (Exception e) { + return false; + } } + })); + + try (final PooledConnection connection2 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { + assertNotSame(connection1, connection2); } - })); - - final PooledConnection connection2 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials"); - assertNotSame(connection1.pool, connection2.pool); - - try { - connection2.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - } finally { - connection2.close(); - } - connection1.close(); + assertNull(((PooledConnection)connection1).getConnection()); // underlying connection should have been closed + } } - @Test public void testFailureGetsNewConnectionOnRetryBigPool() throws JMSException { pooledConnFact.setMaxConnections(10); - Connection connection1 = pooledConnFact.createConnection("invalid", "credentials"); - try { - connection1.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - } - - Connection connection2 = pooledConnFact.createConnection("invalid", "credentials"); - try { - connection2.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); + try (final Connection connection1 = pooledConnFact.createConnection("invalid", "credentials")) { + assertThrows(JMSSecurityException.class, connection1::start); + try (final Connection connection2 = pooledConnFact.createConnection("invalid", "credentials")) { + assertThrows(JMSSecurityException.class, connection2::start); + assertNotSame(connection1, connection2); + } } - assertNotSame(connection1, connection2); - - connection1.close(); - connection2.close(); } @Test @@ -192,21 +164,14 @@ public void testFailoverWithInvalidCredentialsCanConnect() throws JMSException { pooledConnFact.setConnectionFactory(cf); pooledConnFact.setMaxConnections(1); - Connection connection = pooledConnFact.createConnection("invalid", "credentials"); + try (final Connection connection = pooledConnFact.createConnection("invalid", "credentials")) { + assertThrows(JMSSecurityException.class, connection::start); - try { - connection.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); + try (final Connection connection2 = pooledConnFact.createConnection("system", "manager")) { + connection2.start(); + LOG.info("Successfully create new connection."); + } } - - connection = pooledConnFact.createConnection("system", "manager"); - connection.start(); - - LOG.info("Successfully create new connection."); - - connection.close(); } @Test @@ -219,66 +184,46 @@ public void testFailoverWithInvalidCredentials() throws Exception { pooledConnFact.setConnectionFactory(cf); pooledConnFact.setMaxConnections(1); - final PooledConnection connection1 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials"); + try (final PooledConnection connection1 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { + assertThrows(JMSSecurityException.class, connection1::start); - try { - connection1.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - // Intentionally don't close here to see that async pool reconnect takes place. - } + // The pool should process the async error + assertTrue("Should get new connection", Wait.waitFor(new Wait.Condition() { - // The pool should process the async error - assertTrue("Should get new connection", Wait.waitFor(new Wait.Condition() { - - @Override - public boolean isSatisified() throws Exception { - try (final PooledConnection newConnection = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { - return connection1.pool != ((PooledConnection)newConnection).pool; - } catch (Exception e) { - return false; + @Override + public boolean isSatisified() throws Exception { + try (final PooledConnection newConnection = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { + return connection1 != newConnection; + } catch (Exception e) { + return false; + } } + })); + + try (final PooledConnection connection2 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials")) { + assertNotSame(connection1.pool, connection2.pool); + assertThrows(JMSSecurityException.class, connection2::start); } - })); - - final PooledConnection connection2 = (PooledConnection) pooledConnFact.createConnection("invalid", "credentials"); - assertNotSame(connection1.pool, connection2.pool); - - try { - connection2.start(); - fail("Should fail to connect"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - connection2.close(); - } finally { - connection2.close(); } - - connection1.close(); } @Test public void testFailedCreateConsumerConnectionStillWorks() throws JMSException { - Connection connection = pooledConnFact.createConnection("guest", "password"); - connection.start(); + try (final Connection connection = pooledConnFact.createConnection("guest", "password")) { + connection.start(); - Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - Queue queue = session.createQueue(name.getMethodName()); + try (final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) { + final Queue queue = session.createQueue(name.getMethodName()); - try { - session.createConsumer(queue); - fail("Should fail to create consumer"); - } catch (JMSSecurityException ex) { - LOG.info("Caught expected security error"); - } + assertThrows(JMSSecurityException.class, () -> session.createConsumer(queue)); - queue = session.createQueue("GUESTS." + name.getMethodName()); + final Queue guestsQueue = session.createQueue("GUESTS." + name.getMethodName()); - MessageProducer producer = session.createProducer(queue); - producer.close(); - - connection.close(); + try (final MessageProducer producer = session.createProducer(guestsQueue)) { + // We can still produce to the GUESTS queue. + } + } + } } public String getName() { From 6260b5689bcd74b81bb37596dec730586c931cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?JB=20Onofr=C3=A9?= Date: Fri, 9 Jan 2026 11:13:50 +0100 Subject: [PATCH 24/24] Add all platforms for on-demand Jenkins --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 4022a4f5b5..95fb388301 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,7 +46,7 @@ pipeline { } parameters { - choice(name: 'nodeLabel', choices: [ 's390x']) + choice(name: 'nodeLabel', choices: [ 'ubuntu', 's390x', 'arm', 'Windows' ]) choice(name: 'jdkVersion', choices: ['jdk_17_latest', 'jdk_21_latest', 'jdk_24_latest', 'jdk_17_latest_windows', 'jdk_21_latest_windows', 'jdk_24_latest_windows']) booleanParam(name: 'deployEnabled', defaultValue: false) booleanParam(name: 'parallelTestsEnabled', defaultValue: true)