From ee3e8f16ace6b7ed7ed77f4a3c31d6e12118ea46 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/23] 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 89c1dd4c283be302f6a8bb49bf2db211ff87abe5 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/23] 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 5da03dfc5d68aeb245237c8856cce7bac24f590c 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/23] 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 2a553d5d0d07691de7c2cf5e7bdd47d61d46aa6b 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/23] 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 bf06bb1311b414f29c9487b2e6fa66f72272cf36 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/23] 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 612bb7c24a075507c46276ceb65d904c4ad55991 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/23] 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 f94acbf05069705ad9f09f59f859328e2f5e5e0d 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/23] 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 9eb3080d6385ea8149b39a7a3d32c3a2f9c4961d 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/23] 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 891600a5bf0fb58d44548308bdfac81b5c127d52 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/23] 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 f5338fd6c620b93bb0fc777ebfc93025a99792b7 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/23] 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 7ea48b93ba55d09b2a5a005439808bd1d4bee0d9 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/23] 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 7927aea464..24d1a53386 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 4bd1cd9ffd..a332e610e7 100644 --- a/pom.xml +++ b/pom.xml @@ -968,13 +968,12 @@ true 1 true - -enableassertions false true true - -Xmx512m + -enableassertions -Xmx1G From ca5e5fda92ffbf44bb2786511f69cccab0b6f1d1 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/23] 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 a1a98780e2..8d6c6dfab1 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 f2e05b96726d22919a50e2a63081addaf042930a 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/23] 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 24d1a53386..7927aea464 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 8d6c6dfab1..b9cbf8c44d 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 a332e610e7..d9c040457a 100644 --- a/pom.xml +++ b/pom.xml @@ -973,7 +973,7 @@ true true - -enableassertions -Xmx1G + -enableassertions From 24caa5e06991779c02f360ad093a00ccde1d0518 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Tue, 16 Dec 2025 15:47:31 +0100 Subject: [PATCH 14/23] 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 4db1f61fa14113e3ce67f2cb242cca9a73fddcea Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Tue, 16 Dec 2025 19:39:28 +0100 Subject: [PATCH 15/23] 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 7cf0f5ab495566636bcf7ce6800582b55ec677e8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Tue, 16 Dec 2025 20:41:49 +0100 Subject: [PATCH 16/23] 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 5af2d2ef03ccbf7054319f3461fc99ac010bcab7 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 00:30:22 +0100 Subject: [PATCH 17/23] 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 00a53522c62bd71fe375119ff44fd4fd40eff765 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 12:18:16 +0100 Subject: [PATCH 18/23] 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 d351d0efed96495488384f4239c845210cbb8753 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 13:39:27 +0100 Subject: [PATCH 19/23] [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 fb8a1bc2515f4b152a434405433fcab7984d1c71 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Wed, 17 Dec 2025 22:23:33 +0100 Subject: [PATCH 20/23] 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 a0af1e247a4c707e7bce054f3568e8c746e495ed Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Thu, 18 Dec 2025 11:55:32 +0100 Subject: [PATCH 21/23] 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 91d1f5bca5983fa792d8922481ce27ac3d2793db Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Thu, 18 Dec 2025 15:12:52 +0100 Subject: [PATCH 22/23] 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 0809b4f32317a1d401b738191377ea7c9bf5a9c4 Mon Sep 17 00:00:00 2001 From: Jean-Louis Monteiro Date: Thu, 18 Dec 2025 22:21:50 +0100 Subject: [PATCH 23/23] 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() {