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");