From bc273bc684366a5176ebbed98b6052ce692564f1 Mon Sep 17 00:00:00 2001 From: Torsten Mielke Date: Mon, 18 May 2026 13:59:56 +0200 Subject: [PATCH 1/4] [CAMEL-23481] first preparation to replace Derby with HSQL --- components/camel-sql/pom.xml | 36 ++++++++++----- .../SqlConsumerMaxMessagesPerPollTest.java | 2 +- .../component/sql/SqlGeneratedKeysTest.java | 2 +- .../stored/CallableStatementWrapperTest.java | 2 +- .../sql/stored/ProducerBatchInvalidTest.java | 2 +- .../sql/stored/ProducerBatchTest.java | 2 +- .../sql/stored/ProducerBodyArrayTest.java | 2 +- .../sql/stored/ProducerInOutTest.java | 31 ++++++++++--- .../stored/ProducerNamedParameterTest.java | 2 +- .../component/sql/stored/ProducerTest.java | 44 ++++++++++++++++--- ...ProducerUseMessageBodyForTemplateTest.java | 2 +- .../sql/stored/SqlFunctionDataSourceTest.java | 2 +- .../sql/stored/SqlStoredDataSourceTest.java | 2 +- .../sql/stored/TemplateCacheTest.java | 2 +- .../sql/stored/TestStoredProcedure.java | 23 ++++++++++ ...bcLoopTransactedSplitterStackSizeTest.java | 35 +++++---------- .../sql/createAndPopulateDatabase3.sql | 5 ++- .../sql/createAndPopulateDatabase4.sql | 2 +- .../resources/sql/storedProcedureTest.sql | 36 +++------------ parent/pom.xml | 1 - 20 files changed, 146 insertions(+), 89 deletions(-) diff --git a/components/camel-sql/pom.xml b/components/camel-sql/pom.xml index cdb0227c310a1..4fd3c6106041f 100644 --- a/components/camel-sql/pom.xml +++ b/components/camel-sql/pom.xml @@ -48,7 +48,20 @@ + + + org.apache.derby + derby + 10.16.1.1 + test + + org.apache.derby + derbytools + 10.16.1.1 + test + + org.apache.camel camel-test-spring-junit6 test @@ -70,17 +83,11 @@ ${hamcrest-version} test - - - org.apache.derby - derby - ${derby-version} - test - + - org.apache.derby - derbytools - ${derby-version} + com.h2database + h2 + ${h2-version} test @@ -119,8 +126,15 @@ + + + maven-surefire-plugin + + + org.apache.camel.component.sql.stored.* + + - diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java index 60f3116567f7f..608ec778cfbf2 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java @@ -39,7 +39,7 @@ public class SqlConsumerMaxMessagesPerPollTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.H2) .addScript("sql/createAndPopulateDatabase4.sql") .build(); diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java index 5d4445df24ac1..f27719b73441c 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java @@ -163,7 +163,7 @@ public void testRetrieveGeneratedKeysForBatch() { List> generatedKeys = out.getMessage().getHeader(SqlConstants.SQL_GENERATED_KEYS_DATA, List.class); assertNotNull(generatedKeys, "out body could not be converted to a List - was: " + out.getMessage().getBody()); - // it seems not to work with Derby... + // it seems not to work with H2... assertEquals(4, generatedKeys.size()); int id = 3; diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java index c8cf78b537081..ce56529fc42ab 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java @@ -45,7 +45,7 @@ public class CallableStatementWrapperTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); jdbcTemplate = new JdbcTemplate(db); diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchInvalidTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchInvalidTest.java index c2cb662cb5f16..34d5db7ed4811 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchInvalidTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchInvalidTest.java @@ -40,7 +40,7 @@ public class ProducerBatchInvalidTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchTest.java index 53324b58a66c8..6bb13ffa31364 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBatchTest.java @@ -42,7 +42,7 @@ public class ProducerBatchTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBodyArrayTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBodyArrayTest.java index 5cae4169500f5..58bb109b8d624 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBodyArrayTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerBodyArrayTest.java @@ -39,7 +39,7 @@ public class ProducerBodyArrayTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java index 6f783b8476452..4bd897a752ee7 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java @@ -40,7 +40,7 @@ public class ProducerInOutTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } @@ -77,11 +77,32 @@ protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() { - // required for the sql component - getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db); - + // H2 doesn't support CallableStatement.registerOutParameter() + // Instead, we call the H2 alias directly as a query and extract the result from("direct:query") - .to("sql-stored:INOUTDEMO(INTEGER ${headers.in1},INOUT INTEGER ${headers.in2} out1,OUT INTEGER out2)") + .process(exchange -> { + Integer in1 = exchange.getIn().getHeader("in1", Integer.class); + Integer in2 = exchange.getIn().getHeader("in2", Integer.class); + + // Call H2 alias which returns a ResultSet + String sql = "SELECT * FROM INOUTDEMO(?, ?)"; + java.sql.Connection conn = db.getConnection(); + try (java.sql.PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, in1); + stmt.setInt(2, in2); + java.sql.ResultSet rs = stmt.executeQuery(); + + java.util.Map result = new java.util.HashMap<>(); + if (rs.next()) { + result.put("out1", rs.getInt("OUT1")); + result.put("out2", rs.getInt("OUT2")); + } + exchange.getIn().setBody(result); + exchange.getIn().setHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT, 0); + } finally { + conn.close(); + } + }) .to("mock:query"); } }; diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerNamedParameterTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerNamedParameterTest.java index 5f2292000c66f..180cc7beb4af7 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerNamedParameterTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerNamedParameterTest.java @@ -40,7 +40,7 @@ public class ProducerNamedParameterTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java index fc62fb7f8530a..d4df1803343be 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java @@ -36,13 +36,11 @@ public class ProducerTest extends CamelTestSupport { EmbeddedDatabase db; @Override - public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); - } @Override @@ -78,11 +76,47 @@ public void configure() { // required for the sql component getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db); - from("direct:query").to("sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers" - + ".num2},OUT INTEGER resultofsub)") + from("direct:query").to( + "sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers" + ".num2},OUT INTEGER resultofsub)") .to("mock:query"); } }; } + /* + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + // H2 doesn't support CallableStatement.registerOutParameter() + // Instead, we call the H2 alias directly as a query and extract the result + from("direct:query") + .process(exchange -> { + Integer num1 = exchange.getIn().getHeader("num1", Integer.class); + Integer num2 = exchange.getIn().getHeader("num2", Integer.class); + + // Call H2 alias which returns a ResultSet + String sql = "SELECT * FROM SUBNUMBERS(?, ?)"; + java.sql.Connection conn = db.getConnection(); + try (java.sql.PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, num1); + stmt.setInt(2, num2); + java.sql.ResultSet rs = stmt.executeQuery(); + + java.util.Map result = new java.util.HashMap<>(); + if (rs.next()) { + result.put("resultofsub", rs.getInt("RESULTOFSUB")); + } + exchange.getIn().setBody(result); + exchange.getIn().setHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT, 0); + } finally { + conn.close(); + } + }) + .to("mock:query"); + } + }; + }*/ + } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerUseMessageBodyForTemplateTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerUseMessageBodyForTemplateTest.java index 1ce48a217f25d..3165d28f73a35 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerUseMessageBodyForTemplateTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerUseMessageBodyForTemplateTest.java @@ -39,7 +39,7 @@ public class ProducerUseMessageBodyForTemplateTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java index eab747df4ec99..41902c011095e 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java @@ -39,7 +39,7 @@ public class SqlFunctionDataSourceTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredDataSourceTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredDataSourceTest.java index 5ee3c6158d785..7f0a946afa842 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredDataSourceTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlStoredDataSourceTest.java @@ -38,7 +38,7 @@ protected void bindToRegistry(Registry registry) throws Exception { // this is the database we create with some initial data for our unit test db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); // END SNIPPET: e2 diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TemplateCacheTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TemplateCacheTest.java index 5796f7951b75d..b36b94a8b0e28 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TemplateCacheTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TemplateCacheTest.java @@ -37,7 +37,7 @@ public class TemplateCacheTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.DERBY) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/storedProcedureTest.sql").build(); } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java index 50e100a327fcf..eb647d4d75c5d 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java @@ -35,6 +35,17 @@ public static void subnumbers(int val1, int val2, int[] ret) { ret[0] = val1 - val2; } + public static void subnumbersHSQL(int val1, int val2, Integer[] ret) { + LOG.info("calling subnumbersHSQL:{} + {}", val1, val2); + ret[0] = val1 - val2; + } + + public static int subnumbers2(int val1, int val2) { + LOG.info("calling subnumbers2:{} + {}", val1, val2); + System.out.println("calling subnumbers2: " + val1 + ", " + val2); + return val1 - val2; + } + public static void batchfn(String val1) { LOG.info("calling batchfn:{}", val1); if (val1 == null) { @@ -52,4 +63,16 @@ public static void inoutdemo(int in1, int[] inout1, int[] out1) { inout1[0] = 1; out1[0] = 2; } + + public static void inoutdemoHSQL(int in1, Integer[] inout1, Integer[] out1) { + LOG.info("calling inoutdemo: {}, {}", inout1[0], out1[0]); + inout1[0] = 1; + out1[0] = 2; + } + + public static int inoutdemo2(int[] inout1, int in1) { + LOG.info("calling inoutdemo: {}, {}", inout1[0]); + inout1[0] = 1; + return 2; + } } diff --git a/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java index 0222eec494e70..621179dad455f 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java @@ -16,14 +16,10 @@ */ package org.apache.camel.processor.aggregate.jdbc; -import java.io.File; -import java.sql.DriverManager; - import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spi.Registry; import org.apache.camel.spring.spi.SpringTransactionPolicy; -import org.apache.camel.util.FileUtil; -import org.apache.derby.jdbc.EmbeddedDataSource; +import org.h2.jdbcx.JdbcDataSource; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -45,7 +41,7 @@ public class JdbcLoopTransactedSplitterStackSizeTest extends AbstractJdbcAggrega private int total = 500; private static final String DSNAME = "ds"; - private static EmbeddedDataSource ds; + private static JdbcDataSource ds; private static PlatformTransactionManager txManager; private static SpringTransactionPolicy txPolicy; @@ -61,7 +57,7 @@ public class JdbcLoopTransactedSplitterStackSizeTest extends AbstractJdbcAggrega @Override protected void bindToRegistry(Registry registry) throws Exception { - ds = Derby.init(DSNAME); + ds = H2Db.init(DSNAME); txManager = new DataSourceTransactionManager(ds); @@ -79,7 +75,7 @@ protected void bindToRegistry(Registry registry) throws Exception { @AfterAll public static void tearDownOnce() { - Derby.close("ds"); + H2Db.close("ds"); } @Test @@ -145,30 +141,21 @@ public static int currentStackSize() { return depth; } - private static class Derby { + private static class H2Db { - public static EmbeddedDataSource init(String db) { - deleteDatabaseFiles(db); - EmbeddedDataSource ds = new EmbeddedDataSource(); - ds.setDataSourceName(db); - ds.setDatabaseName(db); - ds.setConnectionAttributes("create=true"); + public static JdbcDataSource init(String db) { + JdbcDataSource ds = new JdbcDataSource(); + ds.setURL("jdbc:h2:mem:" + db + ";DB_CLOSE_DELAY=-1"); return ds; } public static void close(String dbName) { - // unload the driver - try { - DriverManager.getConnection("jdbc:derby:;shutdown=true"); - } catch (Exception e) { - // ignore - } - deleteDatabaseFiles(dbName); + // H2 in-memory databases are automatically cleaned up + // when all connections are closed } private static void deleteDatabaseFiles(String dbName) { - FileUtil.deleteFile(new File("derby.log")); - FileUtil.removeDir(new File(dbName)); + // No files to delete for in-memory H2 } } } diff --git a/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase3.sql b/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase3.sql index 2499f1cd79028..88443226e6021 100644 --- a/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase3.sql +++ b/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase3.sql @@ -16,12 +16,13 @@ -- -- START SNIPPET: e1 -create table projects (id integer primary key GENERATED ALWAYS AS IDENTITY, project varchar(10), license varchar(5), description varchar(1000) default null); +create table projects (id integer primary key IDENTITY, project varchar(10), license varchar(5), description varchar(1000) default null); insert into projects (project, license, description) values ('Camel', 'ASF', ''); insert into projects (project, license, description) values ('AMQ', 'ASF', ''); insert into projects (project, license, description) values ('Linux', 'XXX', ''); -- END SNIPPET: e1 -- START SNIPPET: e2 -create table developers (id1 integer primary key GENERATED ALWAYS AS IDENTITY (START WITH 5), name varchar(20), position varchar(20), id2 integer GENERATED ALWAYS AS (id1+1)); +create table developers (id1 integer IDENTITY primary key, name varchar(20), position varchar(20), id2 integer GENERATED ALWAYS AS (id1+1)); +ALTER TABLE developers ALTER COLUMN id1 RESTART WITH 5; -- END SNIPPET: e2 \ No newline at end of file diff --git a/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql b/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql index e62a4e0820119..b616a40d72ac3 100644 --- a/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql +++ b/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql @@ -15,7 +15,7 @@ -- limitations under the License. -- -create table projects (id integer primary key GENERATED ALWAYS AS IDENTITY, project varchar(10), license varchar(5), description varchar(1000) default null, processed boolean); +create table projects (id integer primary key AUTO_INCREMENT, project varchar(10), license varchar(5), description varchar(1000) default null, processed boolean); insert into projects (project, license, description, processed) values ('Camel', 'ASF', '', false); insert into projects (project, license, description, processed) values ('AMQ', 'ASF', '', false); insert into projects (project, license, description, processed) values ('Linux', 'XXX', '', false); diff --git a/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql b/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql index a6316d04d0547..4fe0329de2fac 100644 --- a/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql +++ b/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql @@ -15,33 +15,11 @@ -- limitations under the License. -- -CREATE PROCEDURE SUBNUMBERS(VALUE1 INTEGER, VALUE2 INTEGER,OUT RESULT INTEGER) - PARAMETER STYLE JAVA - LANGUAGE JAVA - EXTERNAL NAME -'org.apache.camel.component.sql.stored.TestStoredProcedure.subnumbers'; +-- H2 stored procedures that return ResultSet instead of using OUT parameters +-- These reference Java methods that have been adapted for H2 -CREATE PROCEDURE NILADIC() - PARAMETER STYLE JAVA - LANGUAGE JAVA - EXTERNAL NAME -'org.apache.camel.component.sql.stored.TestStoredProcedure.niladic'; - -CREATE PROCEDURE BATCHFN(VALUE1 CHAR(10)) - PARAMETER STYLE JAVA - LANGUAGE JAVA - EXTERNAL NAME -'org.apache.camel.component.sql.stored.TestStoredProcedure.batchfn'; - -CREATE PROCEDURE INOUTDEMO(IN1 INTEGER, INOUT IN2 INTEGER, OUT OUT1 INTEGER) - PARAMETER STYLE JAVA - LANGUAGE JAVA - EXTERNAL NAME -'org.apache.camel.component.sql.stored.TestStoredProcedure.inoutdemo'; - -CREATE FUNCTION SUBNUMBERS_FUNCTION(VALUE1 INTEGER, VALUE2 INTEGER) - RETURNS INTEGER - PARAMETER STYLE JAVA - LANGUAGE JAVA - EXTERNAL NAME -'org.apache.camel.component.sql.stored.TestStoredFunction.subnumbers'; +CREATE ALIAS SUBNUMBERS FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.subnumbers'; +CREATE ALIAS NILADIC FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.niladic'; +CREATE ALIAS BATCHFN FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.batchfn'; +CREATE ALIAS INOUTDEMO FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.inoutdemo'; +CREATE ALIAS SUBNUMBERS_FUNCTION FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.subnumbersFunction'; diff --git a/parent/pom.xml b/parent/pom.xml index ab486eef0face..0e352b34d0aef 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -138,7 +138,6 @@ 3.0.1.3 3.5.0.Final 9.7.0 - 10.16.1.1 3.0.2 2.17 0.19.1 From 5b35f70f58643a3ad8e32a836ce14d9c5bf1c94e Mon Sep 17 00:00:00 2001 From: Torsten Mielke Date: Thu, 28 May 2026 09:57:47 +0200 Subject: [PATCH 2/4] [CAMEL-23481] replacing retired Apache Derby with HSQL and MariaDB for stored procedures and stored function tests in sql-stored: component. While HSQL has support for stored procedures, it does not support SQL stored functions, neither does H2 support them. So using an embedded MariaDB4j instance to test SQL stored functions in class SqlFunctionDataSourceTest. Running an embedded MariaDB4j instance is slower to initialize, so using it only for the single test class SqlFunctionDataSourceTest. Made with help from AI tools. --- components/camel-sql/pom.xml | 37 +++--- .../SqlConsumerMaxMessagesPerPollTest.java | 8 +- .../component/sql/SqlGeneratedKeysTest.java | 1 - .../stored/CallableStatementWrapperTest.java | 42 ++----- .../sql/stored/ProducerInOutTest.java | 41 +++--- .../component/sql/stored/ProducerTest.java | 54 +++----- .../sql/stored/SqlFunctionDataSourceTest.java | 119 +++++++++++++++--- .../sql/stored/TestStoredFunction.java | 7 +- .../sql/stored/TestStoredProcedure.java | 31 +---- ...bcLoopTransactedSplitterStackSizeTest.java | 22 ++-- .../sql/createAndPopulateDatabase4.sql | 4 +- .../resources/sql/storedFunctionMariaDB.sql | 24 ++++ .../resources/sql/storedProcedureTest.sql | 32 +++-- parent/pom.xml | 2 + 14 files changed, 238 insertions(+), 186 deletions(-) create mode 100644 components/camel-sql/src/test/resources/sql/storedFunctionMariaDB.sql diff --git a/components/camel-sql/pom.xml b/components/camel-sql/pom.xml index 4fd3c6106041f..cd9d0cd9b4af9 100644 --- a/components/camel-sql/pom.xml +++ b/components/camel-sql/pom.xml @@ -36,7 +36,6 @@ - org.apache.camel camel-support @@ -48,20 +47,7 @@ - - - org.apache.derby - derby - 10.16.1.1 - test - - - org.apache.derby - derbytools - 10.16.1.1 - test - - + org.apache.camel camel-test-spring-junit6 test @@ -83,11 +69,10 @@ ${hamcrest-version} test - com.h2database h2 - ${h2-version} + ${h2-version} test @@ -96,17 +81,23 @@ ${hsqldb-version} test + - com.h2database - h2 - 2.4.240 + ch.vorburger.mariaDB4j + mariaDB4j + ${mariadb4j-version} + test + + + org.mariadb.jdbc + mariadb-java-client + ${mariadb-version} test - org.codehaus.mojo @@ -126,11 +117,13 @@ - + maven-surefire-plugin + org.apache.camel.component.sql.stored.* diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java index 608ec778cfbf2..9cadb24d0a8d8 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlConsumerMaxMessagesPerPollTest.java @@ -39,7 +39,7 @@ public class SqlConsumerMaxMessagesPerPollTest extends CamelTestSupport { public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.H2) + .setType(EmbeddedDatabaseType.HSQL) .addScript("sql/createAndPopulateDatabase4.sql") .build(); @@ -60,19 +60,19 @@ public void maxMessagesPerPoll() throws Exception { MockEndpoint.assertIsSatisfied(context); List exchanges = mock.getReceivedExchanges(); - assertBodyMapValue(1, "ID", exchanges.get(0)); + assertBodyMapValue(0, "ID", exchanges.get(0)); assertBodyMapValue("Camel", "PROJECT", exchanges.get(0)); assertProperty(0, "CamelBatchIndex", exchanges.get(0)); assertProperty(2, "CamelBatchSize", exchanges.get(0)); assertProperty(Boolean.FALSE, "CamelBatchComplete", exchanges.get(0)); - assertBodyMapValue(2, "ID", exchanges.get(1)); + assertBodyMapValue(1, "ID", exchanges.get(1)); assertBodyMapValue("AMQ", "PROJECT", exchanges.get(1)); assertProperty(1, "CamelBatchIndex", exchanges.get(1)); assertProperty(2, "CamelBatchSize", exchanges.get(1)); assertProperty(Boolean.TRUE, "CamelBatchComplete", exchanges.get(1)); // end of the first batch - assertBodyMapValue(3, "ID", exchanges.get(2)); + assertBodyMapValue(2, "ID", exchanges.get(2)); assertBodyMapValue("Linux", "PROJECT", exchanges.get(2)); assertProperty(0, "CamelBatchIndex", exchanges.get(2)); // the second batch assertProperty(1, "CamelBatchSize", exchanges.get(2)); // only one entry in this batch diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java index f27719b73441c..7ecb0b3ec97e1 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/SqlGeneratedKeysTest.java @@ -163,7 +163,6 @@ public void testRetrieveGeneratedKeysForBatch() { List> generatedKeys = out.getMessage().getHeader(SqlConstants.SQL_GENERATED_KEYS_DATA, List.class); assertNotNull(generatedKeys, "out body could not be converted to a List - was: " + out.getMessage().getBody()); - // it seems not to work with H2... assertEquals(4, generatedKeys.size()); int id = 3; diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java index ce56529fc42ab..f54841dd6892b 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/CallableStatementWrapperTest.java @@ -35,13 +35,24 @@ public class CallableStatementWrapperTest extends CamelTestSupport { + /* This is necessary when debugging tests to enable HSQLDB to find + the classes in the classpath. */ + /* + static { + if (System.getProperty("hsqldb.method_class_names") == null) { + System.setProperty( + "hsqldb.method_class_names", + "org.apache.camel.component.sql.stored.*"); + } + } + */ + private TemplateParser templateParser; private EmbeddedDatabase db; private JdbcTemplate jdbcTemplate; private CallableStatementWrapperFactory factory; @Override - public void doPreSetup() throws Exception { db = new EmbeddedDatabaseBuilder() .setName(getClass().getSimpleName()) @@ -60,32 +71,7 @@ void setupTest() { @Test public void shouldExecuteStoredProcedure() throws Exception { CallableStatementWrapper wrapper = new CallableStatementWrapper( - "SUBNUMBERS" - + "(INTEGER ${header.v1},INTEGER ${header.v2},OUT INTEGER resultofsub)", - factory); - - final Exchange exchange = createExchangeWithBody(null); - exchange.getIn().setHeader("v1", 1); - exchange.getIn().setHeader("v2", 2); - - wrapper.call(new WrapperExecuteCallback() { - @Override - public void execute(StatementWrapper statementWrapper) throws SQLException, DataAccessException { - statementWrapper.populateStatement(null, exchange); - - Map resultOfQuery = (Map) statementWrapper.executeStatement(); - assertEquals(-1, resultOfQuery.get("resultofsub")); - } - }); - } - - @Test - public void shouldExecuteStoredFunction() throws Exception { - CallableStatementWrapperFactory factory = new CallableStatementWrapperFactory(jdbcTemplate, templateParser, true); - - CallableStatementWrapper wrapper = new CallableStatementWrapper( - "SUBNUMBERS_FUNCTION" - + "(OUT INTEGER resultofsub, INTEGER ${header.v1},INTEGER ${header.v2})", + "SUBNUMBERS(INTEGER ${header.v1},INTEGER ${header.v2},OUT INTEGER resultofsub)", factory); final Exchange exchange = createExchangeWithBody(null); @@ -116,7 +102,6 @@ public void execute(StatementWrapper statementWrapper) throws SQLException, Data //no output parameter in stored procedure NILADIC() //Spring sets #update-count-1 assertNotNull(result.get("#update-count-1")); - } }); } @@ -127,5 +112,4 @@ public void doPostTearDown() throws Exception { db.shutdown(); } } - } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java index 4bd897a752ee7..79915cfb64087 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerInOutTest.java @@ -33,6 +33,18 @@ public class ProducerInOutTest extends CamelTestSupport { + /* This is necessary when debugging tests to enable HSQLDB to find + the classes in the classpath. */ + /* + static { + if (System.getProperty("hsqldb.method_class_names") == null) { + System.setProperty( + "hsqldb.method_class_names", + "org.apache.camel.component.sql.stored.*"); + } + } + */ + EmbeddedDatabase db; @Override @@ -77,32 +89,11 @@ protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() { - // H2 doesn't support CallableStatement.registerOutParameter() - // Instead, we call the H2 alias directly as a query and extract the result + // required for the sql component + getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db); + from("direct:query") - .process(exchange -> { - Integer in1 = exchange.getIn().getHeader("in1", Integer.class); - Integer in2 = exchange.getIn().getHeader("in2", Integer.class); - - // Call H2 alias which returns a ResultSet - String sql = "SELECT * FROM INOUTDEMO(?, ?)"; - java.sql.Connection conn = db.getConnection(); - try (java.sql.PreparedStatement stmt = conn.prepareStatement(sql)) { - stmt.setInt(1, in1); - stmt.setInt(2, in2); - java.sql.ResultSet rs = stmt.executeQuery(); - - java.util.Map result = new java.util.HashMap<>(); - if (rs.next()) { - result.put("out1", rs.getInt("OUT1")); - result.put("out2", rs.getInt("OUT2")); - } - exchange.getIn().setBody(result); - exchange.getIn().setHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT, 0); - } finally { - conn.close(); - } - }) + .to("sql-stored:INOUTDEMO(INTEGER ${headers.in1}, INOUT INTEGER ${headers.in2} out1, OUT INTEGER out2)") .to("mock:query"); } }; diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java index d4df1803343be..98b42efd51231 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java @@ -33,6 +33,18 @@ public class ProducerTest extends CamelTestSupport { + /* This is necessary when debugging tests to enable HSQLDB to find + the classes in the classpath. */ + /* + static { + if (System.getProperty("hsqldb.method_class_names") == null) { + System.setProperty( + "hsqldb.method_class_names", + "org.apache.camel.component.sql.stored.*"); + } + } + */ + EmbeddedDatabase db; @Override @@ -76,47 +88,11 @@ public void configure() { // required for the sql component getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db); - from("direct:query").to( - "sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers" + ".num2},OUT INTEGER resultofsub)") - .to("mock:query"); - } - }; - } - - /* - @Override - protected RouteBuilder createRouteBuilder() { - return new RouteBuilder() { - @Override - public void configure() { - // H2 doesn't support CallableStatement.registerOutParameter() - // Instead, we call the H2 alias directly as a query and extract the result from("direct:query") - .process(exchange -> { - Integer num1 = exchange.getIn().getHeader("num1", Integer.class); - Integer num2 = exchange.getIn().getHeader("num2", Integer.class); - - // Call H2 alias which returns a ResultSet - String sql = "SELECT * FROM SUBNUMBERS(?, ?)"; - java.sql.Connection conn = db.getConnection(); - try (java.sql.PreparedStatement stmt = conn.prepareStatement(sql)) { - stmt.setInt(1, num1); - stmt.setInt(2, num2); - java.sql.ResultSet rs = stmt.executeQuery(); - - java.util.Map result = new java.util.HashMap<>(); - if (rs.next()) { - result.put("resultofsub", rs.getInt("RESULTOFSUB")); - } - exchange.getIn().setBody(result); - exchange.getIn().setHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT, 0); - } finally { - conn.close(); - } - }) - .to("mock:query"); + .to("sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers" + ".num2},OUT INTEGER resultofsub)") + .to("mock:query"); } }; - }*/ + } } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java index 41902c011095e..03f11ea077092 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java @@ -16,56 +16,140 @@ */ package org.apache.camel.component.sql.stored; +import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import javax.sql.DataSource; + +import ch.vorburger.mariadb4j.DB; +import ch.vorburger.mariadb4j.DBConfigurationBuilder; import org.apache.camel.Exchange; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.component.sql.stored.template.TemplateParser; import org.apache.camel.test.junit6.CamelTestSupport; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.core.io.ClassPathResource; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import static org.junit.jupiter.api.Assertions.assertEquals; +/** + * This test evaluates SQL stored function call with sql-stored component against a MariaDB database because HSQLDB + * doesn't support SQL stored functions. + */ public class SqlFunctionDataSourceTest extends CamelTestSupport { - private EmbeddedDatabase db; + private static final String DB_NAME = "test"; + private static final Object DB_LOCK = new Object(); + private static DB sharedMariaDb; + private static DataSource sharedDataSource; + + private DataSource db; + private static JdbcTemplate jdbcTemplate; + private TemplateParser templateParser; + + /** Initialize the shared MariaDB database for the tests. */ + private static void initSharedMariaDb() throws Exception { + DBConfigurationBuilder config = DBConfigurationBuilder.newBuilder(); + config.setPort(0); + sharedMariaDb = DB.newEmbeddedDB(config.build()); + sharedMariaDb.start(); + + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.mariadb.jdbc.Driver"); + dataSource.setUrl(sharedMariaDb.getConfiguration().getURL(DB_NAME)); + dataSource.setUsername("root"); + dataSource.setPassword(""); + sharedDataSource = dataSource; + + ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); + populator.addScript(new ClassPathResource("sql/storedFunctionMariaDB.sql")); + populator.setSeparator("$$"); + populator.execute(sharedDataSource); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + if (sharedMariaDb != null) { + try { + sharedMariaDb.stop(); + } catch (Exception e) { + // best-effort cleanup on JVM shutdown + } + } + })); + jdbcTemplate = new JdbcTemplate(sharedDataSource); + } + /** Initialize the database for the tests. */ @Override - public void doPreSetup() throws Exception { - db = new EmbeddedDatabaseBuilder() - .setName(getClass().getSimpleName()) - .setType(EmbeddedDatabaseType.HSQL) - .addScript("sql/storedProcedureTest.sql").build(); - + synchronized (DB_LOCK) { + if (sharedMariaDb == null) { + initSharedMariaDb(); + } + } + db = sharedDataSource; } @Override public void doPostTearDown() throws Exception { - if (db != null) { - db.shutdown(); - } + db = null; } + @BeforeEach + void setupTest() { + templateParser = new TemplateParser(context().getClassResolver()); + } + + /* Testing SQL stored function call with sql-stored component against + MariaDB database. + */ @Test - public void shouldExecuteStoredProcedure() throws InterruptedException { + public void shouldExecuteStoredFunction() throws InterruptedException { MockEndpoint mock = getMockEndpoint("mock:query"); mock.expectedMessageCount(1); Map headers = new HashMap<>(); - headers.put("num1", 1); - headers.put("num2", 2); + headers.put("num1", 11); + headers.put("num2", 3); template.requestBodyAndHeaders("direct:query", null, headers); MockEndpoint.assertIsSatisfied(context); Exchange exchange = mock.getExchanges().get(0); + assertEquals(Integer.valueOf(8), exchange.getIn().getBody(Map.class).get("resultofsub")); + } + + /* Test moved from CallableStatementWrapperTest to here as HSQLDB doesn't + support SQL stored functions. This test evaluates SQL stored function + call using CallableStatementWrapper against a MariaDB database. + */ + @Test + public void shouldExecuteStoredFunctionDirect() throws Exception { + CallableStatementWrapperFactory factory = new CallableStatementWrapperFactory(jdbcTemplate, templateParser, true); + + CallableStatementWrapper wrapper = new CallableStatementWrapper( + "SUBNUMBERS_FUNCTION(OUT INTEGER resultofsub, INTEGER ${header.v1},INTEGER ${header.v2})", + factory); - assertEquals(Integer.valueOf(-1), exchange.getIn().getBody(Map.class).get("resultofsub")); + final Exchange exchange = createExchangeWithBody(null); + exchange.getIn().setHeader("v1", 12); + exchange.getIn().setHeader("v2", 5); + + wrapper.call(new WrapperExecuteCallback() { + @Override + public void execute(StatementWrapper statementWrapper) throws SQLException, DataAccessException { + statementWrapper.populateStatement(null, exchange); + + Map resultOfQuery = (Map) statementWrapper.executeStatement(); + assertEquals(7, resultOfQuery.get("resultofsub")); + } + }); } @Override @@ -73,7 +157,6 @@ protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() { - // required for the sql component getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db); from("direct:query") diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredFunction.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredFunction.java index 03b7acb69648a..48f4303a48ff0 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredFunction.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredFunction.java @@ -26,8 +26,9 @@ public final class TestStoredFunction { private TestStoredFunction() { } - public static int subnumbers(int val1, int val2) { - LOG.info("calling subnumbers:{} - {}", val1, val2); - return val1 - val2; + /* HSQLDB style requires Integer instead of int for any out parameters. */ + public static void subnumbers(Integer[] result, int val1, int val2) { + LOG.info("calling subnumbers: {} - {}", val1, val2); + result[0] = val1 - val2; } } diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java index eb647d4d75c5d..d691f8a50db26 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/TestStoredProcedure.java @@ -30,22 +30,12 @@ public final class TestStoredProcedure { private TestStoredProcedure() { } - public static void subnumbers(int val1, int val2, int[] ret) { - LOG.info("calling addnumbers:{} + {}", val1, val2); + /** HSQLDB style requires Integer instead of int for the return value. */ + public static void subnumbers(int val1, int val2, Integer[] ret) { + LOG.info("calling subnumbers:{} - {}", val1, val2); ret[0] = val1 - val2; } - public static void subnumbersHSQL(int val1, int val2, Integer[] ret) { - LOG.info("calling subnumbersHSQL:{} + {}", val1, val2); - ret[0] = val1 - val2; - } - - public static int subnumbers2(int val1, int val2) { - LOG.info("calling subnumbers2:{} + {}", val1, val2); - System.out.println("calling subnumbers2: " + val1 + ", " + val2); - return val1 - val2; - } - public static void batchfn(String val1) { LOG.info("calling batchfn:{}", val1); if (val1 == null) { @@ -58,21 +48,10 @@ public static void niladic() { LOG.info("nilacid called"); } - public static void inoutdemo(int in1, int[] inout1, int[] out1) { + /** HSQLDB style requires Integer instead of int for the out parameters. */ + public static void inoutdemo(int in1, Integer[] inout1, Integer[] out1) { LOG.info("calling inoutdemo: {}, {}", inout1[0], out1[0]); inout1[0] = 1; out1[0] = 2; } - - public static void inoutdemoHSQL(int in1, Integer[] inout1, Integer[] out1) { - LOG.info("calling inoutdemo: {}, {}", inout1[0], out1[0]); - inout1[0] = 1; - out1[0] = 2; - } - - public static int inoutdemo2(int[] inout1, int in1) { - LOG.info("calling inoutdemo: {}, {}", inout1[0]); - inout1[0] = 1; - return 2; - } } diff --git a/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java index 621179dad455f..d0121ebf2d5f9 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/processor/aggregate/jdbc/JdbcLoopTransactedSplitterStackSizeTest.java @@ -19,7 +19,7 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.spi.Registry; import org.apache.camel.spring.spi.SpringTransactionPolicy; -import org.h2.jdbcx.JdbcDataSource; +import org.hsqldb.jdbc.JDBCDataSource; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -41,7 +41,7 @@ public class JdbcLoopTransactedSplitterStackSizeTest extends AbstractJdbcAggrega private int total = 500; private static final String DSNAME = "ds"; - private static JdbcDataSource ds; + private static JDBCDataSource ds; private static PlatformTransactionManager txManager; private static SpringTransactionPolicy txPolicy; @@ -57,7 +57,7 @@ public class JdbcLoopTransactedSplitterStackSizeTest extends AbstractJdbcAggrega @Override protected void bindToRegistry(Registry registry) throws Exception { - ds = H2Db.init(DSNAME); + ds = HsqlDb.init(DSNAME); txManager = new DataSourceTransactionManager(ds); @@ -75,7 +75,7 @@ protected void bindToRegistry(Registry registry) throws Exception { @AfterAll public static void tearDownOnce() { - H2Db.close("ds"); + HsqlDb.close("ds"); } @Test @@ -141,21 +141,23 @@ public static int currentStackSize() { return depth; } - private static class H2Db { + private static class HsqlDb { - public static JdbcDataSource init(String db) { - JdbcDataSource ds = new JdbcDataSource(); - ds.setURL("jdbc:h2:mem:" + db + ";DB_CLOSE_DELAY=-1"); + public static JDBCDataSource init(String db) { + JDBCDataSource ds = new JDBCDataSource(); + ds.setUrl("jdbc:hsqldb:mem:" + db); + ds.setUser("sa"); + ds.setPassword(""); return ds; } public static void close(String dbName) { - // H2 in-memory databases are automatically cleaned up + // HSQLDB in-memory databases are automatically cleaned up // when all connections are closed } private static void deleteDatabaseFiles(String dbName) { - // No files to delete for in-memory H2 + // No files to delete for in-memory HSQLDB } } } diff --git a/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql b/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql index b616a40d72ac3..7eda67af05599 100644 --- a/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql +++ b/components/camel-sql/src/test/resources/sql/createAndPopulateDatabase4.sql @@ -15,7 +15,7 @@ -- limitations under the License. -- -create table projects (id integer primary key AUTO_INCREMENT, project varchar(10), license varchar(5), description varchar(1000) default null, processed boolean); +create table projects (id integer primary key IDENTITY, project varchar(10), license varchar(5), description varchar(1000) default null, processed boolean); insert into projects (project, license, description, processed) values ('Camel', 'ASF', '', false); insert into projects (project, license, description, processed) values ('AMQ', 'ASF', '', false); -insert into projects (project, license, description, processed) values ('Linux', 'XXX', '', false); +insert into projects (project, license, description, processed) values ('Linux', 'XXX', '', false); \ No newline at end of file diff --git a/components/camel-sql/src/test/resources/sql/storedFunctionMariaDB.sql b/components/camel-sql/src/test/resources/sql/storedFunctionMariaDB.sql new file mode 100644 index 0000000000000..24d5962b3d1a6 --- /dev/null +++ b/components/camel-sql/src/test/resources/sql/storedFunctionMariaDB.sql @@ -0,0 +1,24 @@ +-- +-- 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. +-- + +-- MariaDB/MySQL stored procedures and functions (SQL-based; no Java EXTERNAL NAME) +-- Statement separator is $$ (see SqlFunctionDataSourceTest ResourceDatabasePopulator) +-- MariaDB4J does not support calling Java methods from the SQL stored procedure or function. +DROP FUNCTION IF EXISTS SUBNUMBERS_FUNCTION$$ +CREATE FUNCTION SUBNUMBERS_FUNCTION(param1 INT, param2 INT) RETURNS INT +DETERMINISTIC + RETURN param1 - param2$$ diff --git a/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql b/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql index 4fe0329de2fac..d90725fcabc3d 100644 --- a/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql +++ b/components/camel-sql/src/test/resources/sql/storedProcedureTest.sql @@ -15,11 +15,29 @@ -- limitations under the License. -- --- H2 stored procedures that return ResultSet instead of using OUT parameters --- These reference Java methods that have been adapted for H2 +-- HSQLDB stored procedures using PARAMETER STYLE JAVA with OUT parameters +-- These reference Java methods from TestStoredProcedure class -CREATE ALIAS SUBNUMBERS FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.subnumbers'; -CREATE ALIAS NILADIC FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.niladic'; -CREATE ALIAS BATCHFN FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.batchfn'; -CREATE ALIAS INOUTDEMO FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.inoutdemo'; -CREATE ALIAS SUBNUMBERS_FUNCTION FOR 'org.apache.camel.component.sql.stored.H2StoredProcedures.subnumbersFunction'; +CREATE PROCEDURE SUBNUMBERS(IN param1 INTEGER, IN param2 INTEGER, OUT param3 INTEGER) +LANGUAGE JAVA +PARAMETER STYLE JAVA +NO SQL +EXTERNAL NAME 'CLASSPATH:org.apache.camel.component.sql.stored.TestStoredProcedure.subnumbers'; + +CREATE PROCEDURE NILADIC() +LANGUAGE JAVA +PARAMETER STYLE JAVA +NO SQL +EXTERNAL NAME 'CLASSPATH:org.apache.camel.component.sql.stored.TestStoredProcedure.niladic'; + +CREATE PROCEDURE BATCHFN(IN param1 VARCHAR(100)) +LANGUAGE JAVA +PARAMETER STYLE JAVA +NO SQL +EXTERNAL NAME 'CLASSPATH:org.apache.camel.component.sql.stored.TestStoredProcedure.batchfn'; + +CREATE PROCEDURE INOUTDEMO(IN param1 INTEGER, INOUT param2 INTEGER, OUT param3 INTEGER) +LANGUAGE JAVA +PARAMETER STYLE JAVA +NO SQL +EXTERNAL NAME 'CLASSPATH:org.apache.camel.component.sql.stored.TestStoredProcedure.inoutdemo'; \ No newline at end of file diff --git a/parent/pom.xml b/parent/pom.xml index 0e352b34d0aef..10688d1649a00 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -226,6 +226,8 @@ 9.1.0.Final 6.3.2.Final 2.7.4 + 3.5.3 + 3.3.1 5.4.2 5.5.2 4.4.16 From 0c4e554a1394ff403b0e5b97ec82f22747f5aee7 Mon Sep 17 00:00:00 2001 From: Torsten Mielke Date: Thu, 28 May 2026 13:35:15 +0200 Subject: [PATCH 3/4] [CAMEL-23481] need to reintroduce in parent/pom.xml until no component uses Derby. --- .../org/apache/camel/component/sql/stored/ProducerTest.java | 5 +++-- parent/pom.xml | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java index 98b42efd51231..7783188a2460f 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/ProducerTest.java @@ -89,8 +89,9 @@ public void configure() { getContext().getComponent("sql-stored", SqlStoredComponent.class).setDataSource(db); from("direct:query") - .to("sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers" + ".num2},OUT INTEGER resultofsub)") - .to("mock:query"); + .to("sql-stored:SUBNUMBERS(INTEGER ${headers.num1},INTEGER ${headers" + + ".num2},OUT INTEGER resultofsub)") + .to("mock:query"); } }; } diff --git a/parent/pom.xml b/parent/pom.xml index c9d1af05aa287..80ced7df1df24 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -137,7 +137,8 @@ 1.17.2 3.0.1.3 3.5.1.Final - 9.7.0 + 9.7.0 + 10.16.1.1 3.0.2 2.17 0.19.1 From c7cf75ff4e5cb1193faf8a49f032dd1b37488fbb Mon Sep 17 00:00:00 2001 From: Torsten Mielke Date: Fri, 29 May 2026 13:52:07 +0200 Subject: [PATCH 4/4] [CAMEL-23481] - adding a few improvements for camel-sql - replace any tab characters with white spaces - upgrade MariaDB client to latest 3.5.8 release - restrict SqlFunctionDataSourceTest to be only run on Linux, MacOS and Windows Made with help from AI tools. --- components/camel-sql/pom.xml | 6 ++- .../sql/stored/SqlFunctionDataSourceTest.java | 7 ++++ .../idempotent/jdbc/cached-spring.xml | 36 ++++++++-------- .../idempotent/jdbc/customized-spring.xml | 42 +++++++++---------- .../jdbc/customized-tablename-spring.xml | 34 +++++++-------- .../processor/idempotent/jdbc/spring.xml | 36 ++++++++-------- parent/pom.xml | 6 +-- 7 files changed, 88 insertions(+), 79 deletions(-) diff --git a/components/camel-sql/pom.xml b/components/camel-sql/pom.xml index cd9d0cd9b4af9..abac5452be814 100644 --- a/components/camel-sql/pom.xml +++ b/components/camel-sql/pom.xml @@ -47,7 +47,7 @@ - + org.apache.camel camel-test-spring-junit6 test @@ -72,7 +72,7 @@ com.h2database h2 - ${h2-version} + ${h2-version} test @@ -97,6 +97,8 @@ + diff --git a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java index 03f11ea077092..e8ffe8bab1c38 100644 --- a/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java +++ b/components/camel-sql/src/test/java/org/apache/camel/component/sql/stored/SqlFunctionDataSourceTest.java @@ -31,6 +31,9 @@ import org.apache.camel.test.junit6.CamelTestSupport; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.springframework.core.io.ClassPathResource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; @@ -43,6 +46,10 @@ * This test evaluates SQL stored function call with sql-stored component against a MariaDB database because HSQLDB * doesn't support SQL stored functions. */ +@EnabledOnOs(value = { OS.LINUX, OS.WINDOWS, OS.MAC }, + architectures = { "amd64", "x86_64", "aarch64", "aarch_64" }) +@DisabledOnOs(value = OS.LINUX, architectures = { "aarch64", "aarch_64" }, + disabledReason = "MariaDB4j has no Linux ARM64 native binary (mariadb4j-db-linux64 is x86_64 only)") public class SqlFunctionDataSourceTest extends CamelTestSupport { private static final String DB_NAME = "test"; diff --git a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/cached-spring.xml b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/cached-spring.xml index 7a32a81db61a7..29ffb855c2429 100644 --- a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/cached-spring.xml +++ b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/cached-spring.xml @@ -26,28 +26,28 @@ http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - + + - + - - + + - + - - - - - - - - messageId - - - + + + + + + + + messageId + + + - \ No newline at end of file + diff --git a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-spring.xml b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-spring.xml index 0ef71e927a5dd..ec9964148af66 100644 --- a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-spring.xml +++ b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-spring.xml @@ -27,30 +27,30 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - + - - - - - - - + + + + + + + - + - - - - - - - - messageId - - - + + + + + + + + messageId + + + - \ No newline at end of file + diff --git a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-tablename-spring.xml b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-tablename-spring.xml index b5d255f3f4f59..053660685304a 100644 --- a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-tablename-spring.xml +++ b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/customized-tablename-spring.xml @@ -27,26 +27,26 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - + - - - + + + - + - - - - - - - - messageId - - - + + + + + + + + messageId + + + - \ No newline at end of file + diff --git a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/spring.xml b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/spring.xml index 4175f44ae67a7..c18e08d627474 100644 --- a/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/spring.xml +++ b/components/camel-sql/src/test/resources/org/apache/camel/processor/idempotent/jdbc/spring.xml @@ -26,28 +26,28 @@ http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - + + - + - - + + - + - - - - - - - - messageId - - - + + + + + + + + messageId + + + - \ No newline at end of file + diff --git a/parent/pom.xml b/parent/pom.xml index c8e4f01e9639a..793d95b642be9 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -137,8 +137,8 @@ 1.17.2 3.0.1.3 3.5.1.Final - 9.7.0 - 10.16.1.1 + 9.7.0 + 10.16.1.1 3.0.2 2.17 0.19.1 @@ -226,7 +226,7 @@ 9.1.0.Final 6.3.2.Final 2.7.4 - 3.5.3 + 3.5.8 3.3.1 5.4.2 5.5.2