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

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new 2b2f006d61 Register Agroal flush for reflection and test SQL / JDBC 
secret rotation pool eviction
2b2f006d61 is described below

commit 2b2f006d61f10bf229854c5ec78367ca177e56cb
Author: James Netherton <[email protected]>
AuthorDate: Thu Oct 22 07:07:51 2026 +0100

    Register Agroal flush for reflection and test SQL / JDBC secret rotation 
pool eviction
    
    Fixes #9252
    
    Co-authored-by: Claude Opus 5.5 <[email protected]>
---
 .../component/jdbc/deployment/JdbcProcessor.java   |  9 +++++
 .../component/sql/deployment/SqlProcessor.java     |  4 +++
 .../quarkus/component/jdbc/h2/H2JdbcResource.java  | 18 ++++++++++
 .../h2/src/main/resources/application.properties   |  1 +
 .../quarkus/component/jdbc/h2/CamelH2JdbcTest.java | 25 +++++++++++++
 .../quarkus/component/sql/it/SqlResource.java      | 18 ++++++++++
 .../sql/src/main/resources/application.properties  |  1 +
 .../camel/quarkus/component/sql/it/SqlTest.java    | 42 ++++++++++++++++++++++
 8 files changed, 118 insertions(+)

diff --git 
a/extensions/jdbc/deployment/src/main/java/org/apache/camel/quarkus/component/jdbc/deployment/JdbcProcessor.java
 
b/extensions/jdbc/deployment/src/main/java/org/apache/camel/quarkus/component/jdbc/deployment/JdbcProcessor.java
index baae7be50b..a63990ef9a 100644
--- 
a/extensions/jdbc/deployment/src/main/java/org/apache/camel/quarkus/component/jdbc/deployment/JdbcProcessor.java
+++ 
b/extensions/jdbc/deployment/src/main/java/org/apache/camel/quarkus/component/jdbc/deployment/JdbcProcessor.java
@@ -16,8 +16,10 @@
  */
 package org.apache.camel.quarkus.component.jdbc.deployment;
 
+import io.agroal.api.AgroalDataSource;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 
 class JdbcProcessor {
 
@@ -28,4 +30,11 @@ class JdbcProcessor {
         return new FeatureBuildItem(FEATURE);
     }
 
+    @BuildStep
+    ReflectiveClassBuildItem registerAgroalFlushForReflection() {
+        // Required by DataSourceHelper to evict pool connections on secret 
rotation
+        return ReflectiveClassBuildItem.builder(AgroalDataSource.class, 
AgroalDataSource.FlushMode.class)
+                .methods()
+                .build();
+    }
 }
diff --git 
a/extensions/sql/deployment/src/main/java/org/apache/camel/quarkus/component/sql/deployment/SqlProcessor.java
 
b/extensions/sql/deployment/src/main/java/org/apache/camel/quarkus/component/sql/deployment/SqlProcessor.java
index 886ded6984..0b7bd82b73 100644
--- 
a/extensions/sql/deployment/src/main/java/org/apache/camel/quarkus/component/sql/deployment/SqlProcessor.java
+++ 
b/extensions/sql/deployment/src/main/java/org/apache/camel/quarkus/component/sql/deployment/SqlProcessor.java
@@ -18,6 +18,7 @@ package org.apache.camel.quarkus.component.sql.deployment;
 
 import java.sql.Types;
 
+import io.agroal.api.AgroalDataSource;
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
@@ -43,5 +44,8 @@ class SqlProcessor {
     void registerForReflection(BuildProducer<ReflectiveClassBuildItem> 
reflectiveClass) {
         reflectiveClass.produce(
                 ReflectiveClassBuildItem.builder(Types.class, 
DefaultExchangeHolder.class).fields().build());
+        // Required by DataSourceHelper to evict pool connections on secret 
rotation
+        reflectiveClass.produce(
+                ReflectiveClassBuildItem.builder(AgroalDataSource.class, 
AgroalDataSource.FlushMode.class).methods().build());
     }
 }
diff --git 
a/integration-test-groups/jdbc/h2/src/main/java/org/apache/camel/quarkus/component/jdbc/h2/H2JdbcResource.java
 
b/integration-test-groups/jdbc/h2/src/main/java/org/apache/camel/quarkus/component/jdbc/h2/H2JdbcResource.java
index b6517a850c..7c20b687f3 100644
--- 
a/integration-test-groups/jdbc/h2/src/main/java/org/apache/camel/quarkus/component/jdbc/h2/H2JdbcResource.java
+++ 
b/integration-test-groups/jdbc/h2/src/main/java/org/apache/camel/quarkus/component/jdbc/h2/H2JdbcResource.java
@@ -22,11 +22,16 @@ import io.quarkus.runtime.annotations.RegisterForReflection;
 import jakarta.annotation.PostConstruct;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
 import org.apache.camel.CamelContext;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.quarkus.test.support.jdbc.BaseCamelJdbcResource;
 import org.apache.camel.quarkus.test.support.jdbc.model.Camel;
+import org.apache.camel.spi.SecretRotationAware;
 
 @Path("/test/h2")
 @ApplicationScoped
@@ -45,4 +50,17 @@ public class H2JdbcResource extends BaseCamelJdbcResource {
     void postConstruct() throws Exception {
         super.initialize(postgresqlDataSource, dbKind, context, template);
     }
+
+    @Path("/datasource/flushCount")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public long getDataSourceFlushCount() {
+        return postgresqlDataSource.getMetrics().flushCount();
+    }
+
+    @Path("/secretRotation")
+    @POST
+    public void secretRotation() throws Exception {
+        ((SecretRotationAware) 
context.getComponent("jdbc")).onSecretRotation("test");
+    }
 }
diff --git 
a/integration-test-groups/jdbc/h2/src/main/resources/application.properties 
b/integration-test-groups/jdbc/h2/src/main/resources/application.properties
index ce8eb39566..3dc3635c77 100644
--- a/integration-test-groups/jdbc/h2/src/main/resources/application.properties
+++ b/integration-test-groups/jdbc/h2/src/main/resources/application.properties
@@ -20,5 +20,6 @@
 #
 quarkus.datasource.h2.db-kind=h2
 quarkus.datasource.h2.jdbc.max-size=8
+quarkus.datasource.h2.jdbc.metrics.enabled=true
 
 
quarkus.native.resources.includes=postgresql.sql,mysql.sql,mariadb.sql,oracle.sql,h2.sql,db2.sql,inserts.sql,mssql.sql,droptables.sql
\ No newline at end of file
diff --git 
a/integration-test-groups/jdbc/h2/src/test/java/org/apache/camel/quarkus/component/jdbc/h2/CamelH2JdbcTest.java
 
b/integration-test-groups/jdbc/h2/src/test/java/org/apache/camel/quarkus/component/jdbc/h2/CamelH2JdbcTest.java
index f6ebc8054d..a777240c88 100644
--- 
a/integration-test-groups/jdbc/h2/src/test/java/org/apache/camel/quarkus/component/jdbc/h2/CamelH2JdbcTest.java
+++ 
b/integration-test-groups/jdbc/h2/src/test/java/org/apache/camel/quarkus/component/jdbc/h2/CamelH2JdbcTest.java
@@ -17,12 +17,14 @@
 package org.apache.camel.quarkus.component.jdbc.h2;
 
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
 import org.junit.jupiter.api.Test;
 
+import static org.awaitility.Awaitility.await;
 import static org.hamcrest.Matchers.containsStringIgnoringCase;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.equalToIgnoringCase;
@@ -164,4 +166,27 @@ public class CamelH2JdbcTest {
                 .then()
                 .body(equalTo(camelsDbResult));
     }
+
+    @Test
+    void testSecretRotation() {
+        // Ensure the pool holds an idle connection to flush
+        RestAssured.when().get("/test/" + dbKind + 
"/species/1").then().statusCode(200);
+
+        long flushCountBefore = getDataSourceFlushCount();
+
+        RestAssured.post("/test/" + dbKind + "/secretRotation")
+                .then()
+                .statusCode(204);
+
+        await().atMost(10, TimeUnit.SECONDS)
+                .until(() -> getDataSourceFlushCount() > flushCountBefore);
+    }
+
+    private long getDataSourceFlushCount() {
+        return Long.parseLong(RestAssured.get("/test/" + dbKind + 
"/datasource/flushCount")
+                .then()
+                .statusCode(200)
+                .extract()
+                .asString());
+    }
 }
diff --git 
a/integration-tests/sql/src/main/java/org/apache/camel/quarkus/component/sql/it/SqlResource.java
 
b/integration-tests/sql/src/main/java/org/apache/camel/quarkus/component/sql/it/SqlResource.java
index 1b4c0b38ec..adaa8f68f4 100644
--- 
a/integration-tests/sql/src/main/java/org/apache/camel/quarkus/component/sql/it/SqlResource.java
+++ 
b/integration-tests/sql/src/main/java/org/apache/camel/quarkus/component/sql/it/SqlResource.java
@@ -20,6 +20,7 @@ import java.net.URI;
 import java.util.*;
 import java.util.stream.Collectors;
 
+import io.agroal.api.AgroalDataSource;
 import io.quarkus.arc.profile.UnlessBuildProfile;
 import jakarta.enterprise.context.ApplicationScoped;
 import jakarta.inject.Inject;
@@ -38,6 +39,7 @@ import org.apache.camel.CamelExecutionException;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.sql.SqlConstants;
 import org.apache.camel.quarkus.component.sql.it.model.Camel;
+import org.apache.camel.spi.SecretRotationAware;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
 import org.springframework.util.LinkedCaseInsensitiveMap;
 
@@ -59,6 +61,9 @@ public class SqlResource {
     @Inject
     CamelContext camelContext;
 
+    @Inject
+    AgroalDataSource dataSource;
+
     @Path("/get/{species}")
     @GET
     @Produces(MediaType.TEXT_PLAIN)
@@ -213,4 +218,17 @@ public class SqlResource {
         return dbKind;
     }
 
+    @Path("/flushCount")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public long getDataSourceFlushCount() {
+        return dataSource.getMetrics().flushCount();
+    }
+
+    @Path("/secretRotation/{componentName}")
+    @POST
+    public void secretRotation(@PathParam("componentName") String 
componentName) throws Exception {
+        SecretRotationAware component = (SecretRotationAware) 
camelContext.getComponent(componentName);
+        component.onSecretRotation("test");
+    }
 }
diff --git a/integration-tests/sql/src/main/resources/application.properties 
b/integration-tests/sql/src/main/resources/application.properties
index bafd5dbfbd..0f72f3b112 100644
--- a/integration-tests/sql/src/main/resources/application.properties
+++ b/integration-tests/sql/src/main/resources/application.properties
@@ -17,6 +17,7 @@
 
 # Default profile configuration
 %dev,test,prod.quarkus.datasource.db-kind=${cq.sqlJdbcKind:h2}
+%dev,test,prod.quarkus.datasource.jdbc.metrics.enabled=true
 
 # multi-ds-with-default profile to test multiple named DataSource beans with 
the default DataSource
 %multi-ds-with-default.quarkus.camel.routes-discovery.exclude-patterns=**/*
diff --git 
a/integration-tests/sql/src/test/java/org/apache/camel/quarkus/component/sql/it/SqlTest.java
 
b/integration-tests/sql/src/test/java/org/apache/camel/quarkus/component/sql/it/SqlTest.java
index 2f62442563..0889979f79 100644
--- 
a/integration-tests/sql/src/test/java/org/apache/camel/quarkus/component/sql/it/SqlTest.java
+++ 
b/integration-tests/sql/src/test/java/org/apache/camel/quarkus/component/sql/it/SqlTest.java
@@ -81,6 +81,48 @@ class SqlTest {
                 .body(is("15"));
     }
 
+    @Test
+    public void testSqlComponentSecretRotation() {
+        // Ensure the pool holds an idle connection to flush
+        RestAssured.get("/sql/get/Dromedarius")
+                .then()
+                .statusCode(200);
+
+        assertSecretRotationFlushesPool("sql");
+    }
+
+    @Test
+    public void testSqlStoredComponentSecretRotation() {
+        // Ensure the pool holds an idle connection to flush
+        RestAssured.given()
+                .queryParam("numA", 1)
+                .queryParam("numB", 2)
+                .get("/sql/storedproc")
+                .then()
+                .statusCode(200);
+
+        assertSecretRotationFlushesPool("sql-stored");
+    }
+
+    private void assertSecretRotationFlushesPool(String componentName) {
+        long flushCountBefore = getDataSourceFlushCount();
+
+        RestAssured.post("/sql/secretRotation/" + componentName)
+                .then()
+                .statusCode(204);
+
+        await().atMost(10, TimeUnit.SECONDS)
+                .until(() -> getDataSourceFlushCount() > flushCountBefore);
+    }
+
+    private long getDataSourceFlushCount() {
+        return Long.parseLong(RestAssured.get("/sql/flushCount")
+                .then()
+                .statusCode(200)
+                .extract()
+                .asString());
+    }
+
     @Test
     public void testConsumer() throws InterruptedException {
         testConsumer(1, "consumerRoute", "ViaSql");

Reply via email to