You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/03/28 05:13:04 UTC

[camel] branch main updated: CAMEL-19211: camel-sql - Make it possible to configure custom RowMapper

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 48cbba0a58a CAMEL-19211: camel-sql - Make it possible to configure custom RowMapper
48cbba0a58a is described below

commit 48cbba0a58ab17394dd1b94b1283d35f84bc8afc
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Mar 28 07:12:47 2023 +0200

    CAMEL-19211: camel-sql - Make it possible to configure custom RowMapper
---
 .../org/apache/camel/catalog/components/sql.json   |  1 +
 .../camel/component/sql/SqlEndpointConfigurer.java |  6 ++
 .../camel/component/sql/SqlEndpointUriFactory.java |  3 +-
 .../org/apache/camel/component/sql/sql.json        |  1 +
 .../component/sql/DefaultRowMapperFactory.java     | 37 +++++++++
 .../camel/component/sql/DefaultSqlEndpoint.java    | 29 +++++--
 .../camel/component/sql/RowMapperFactory.java      | 38 +++++++++
 .../endpoint/dsl/SqlEndpointBuilderFactory.java    | 96 ++++++++++++++++++++++
 8 files changed, 202 insertions(+), 9 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
index a5cbbc08764..24c8d8e53e9 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/sql.json
@@ -69,6 +69,7 @@
     "parametersCount": { "kind": "parameter", "displayName": "Parameters Count", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "If set greater than zero, then Camel will use this count value of parameters to replace instead of querying via JDBC metadata API. This is useful if the JDBC vendor could not return correct parameters count, then user may override instead." },
     "placeholder": { "kind": "parameter", "displayName": "Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "#", "description": "Specifies a character that will be replaced to in SQL query. Notice, that it is simple String.replaceAll() operation and no SQL parsing is involved (quoted strings will also change)." },
     "prepareStatementStrategy": { "kind": "parameter", "displayName": "Prepare Statement Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sql.SqlPrepareStatementStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to plugin to use a custom org.apache.camel.component.sql.SqlPrepareStatementStrategy to control preparation of the query and prepared statement." },
+    "rowMapperFactory": { "kind": "parameter", "displayName": "Row Mapper Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sql.RowMapperFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Factory for creating RowMapper" },
     "templateOptions": { "kind": "parameter", "displayName": "Template Options", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "template.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Configures the Spring JdbcTemplate with the key\/values from the Map" },
     "usePlaceholder": { "kind": "parameter", "displayName": "Use Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use placeholder and replace all placeholder characters with sign in the SQL queries." },
     "backoffErrorThreshold": { "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
diff --git a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
index cdee3121a92..823812b8fd6 100644
--- a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
+++ b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointConfigurer.java
@@ -78,6 +78,8 @@ public class SqlEndpointConfigurer extends PropertyConfigurerSupport implements
         case "repeatCount": target.setRepeatCount(property(camelContext, long.class, value)); return true;
         case "routeemptyresultset":
         case "routeEmptyResultSet": target.setRouteEmptyResultSet(property(camelContext, boolean.class, value)); return true;
+        case "rowmapperfactory":
+        case "rowMapperFactory": target.setRowMapperFactory(property(camelContext, org.apache.camel.component.sql.RowMapperFactory.class, value)); return true;
         case "runlogginglevel":
         case "runLoggingLevel": target.setRunLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
         case "scheduledexecutorservice":
@@ -172,6 +174,8 @@ public class SqlEndpointConfigurer extends PropertyConfigurerSupport implements
         case "repeatCount": return long.class;
         case "routeemptyresultset":
         case "routeEmptyResultSet": return boolean.class;
+        case "rowmapperfactory":
+        case "rowMapperFactory": return org.apache.camel.component.sql.RowMapperFactory.class;
         case "runlogginglevel":
         case "runLoggingLevel": return org.apache.camel.LoggingLevel.class;
         case "scheduledexecutorservice":
@@ -262,6 +266,8 @@ public class SqlEndpointConfigurer extends PropertyConfigurerSupport implements
         case "repeatCount": return target.getRepeatCount();
         case "routeemptyresultset":
         case "routeEmptyResultSet": return target.isRouteEmptyResultSet();
+        case "rowmapperfactory":
+        case "rowMapperFactory": return target.getRowMapperFactory();
         case "runlogginglevel":
         case "runLoggingLevel": return target.getRunLoggingLevel();
         case "scheduledexecutorservice":
diff --git a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
index 1931acee130..32afd2d2a8d 100644
--- a/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
+++ b/components/camel-sql/src/generated/java/org/apache/camel/component/sql/SqlEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class SqlEndpointUriFactory extends org.apache.camel.support.component.En
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(46);
+        Set<String> props = new HashSet<>(47);
         props.add("allowNamedParameters");
         props.add("alwaysPopulateStatement");
         props.add("backoffErrorThreshold");
@@ -54,6 +54,7 @@ public class SqlEndpointUriFactory extends org.apache.camel.support.component.En
         props.add("query");
         props.add("repeatCount");
         props.add("routeEmptyResultSet");
+        props.add("rowMapperFactory");
         props.add("runLoggingLevel");
         props.add("scheduledExecutorService");
         props.add("scheduler");
diff --git a/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/sql.json b/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/sql.json
index a5cbbc08764..24c8d8e53e9 100644
--- a/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/sql.json
+++ b/components/camel-sql/src/generated/resources/org/apache/camel/component/sql/sql.json
@@ -69,6 +69,7 @@
     "parametersCount": { "kind": "parameter", "displayName": "Parameters Count", "group": "advanced", "label": "advanced", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "If set greater than zero, then Camel will use this count value of parameters to replace instead of querying via JDBC metadata API. This is useful if the JDBC vendor could not return correct parameters count, then user may override instead." },
     "placeholder": { "kind": "parameter", "displayName": "Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "#", "description": "Specifies a character that will be replaced to in SQL query. Notice, that it is simple String.replaceAll() operation and no SQL parsing is involved (quoted strings will also change)." },
     "prepareStatementStrategy": { "kind": "parameter", "displayName": "Prepare Statement Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sql.SqlPrepareStatementStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to plugin to use a custom org.apache.camel.component.sql.SqlPrepareStatementStrategy to control preparation of the query and prepared statement." },
+    "rowMapperFactory": { "kind": "parameter", "displayName": "Row Mapper Factory", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.sql.RowMapperFactory", "deprecated": false, "autowired": false, "secret": false, "description": "Factory for creating RowMapper" },
     "templateOptions": { "kind": "parameter", "displayName": "Template Options", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "template.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "Configures the Spring JdbcTemplate with the key\/values from the Map" },
     "usePlaceholder": { "kind": "parameter", "displayName": "Use Placeholder", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether to use placeholder and replace all placeholder characters with sign in the SQL queries." },
     "backoffErrorThreshold": { "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultRowMapperFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultRowMapperFactory.java
new file mode 100644
index 00000000000..4adc16a4819
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultRowMapperFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+package org.apache.camel.component.sql;
+
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.ColumnMapRowMapper;
+import org.springframework.jdbc.core.RowMapper;
+
+/**
+ * Default {@link RowMapperFactory}.
+ */
+public class DefaultRowMapperFactory implements RowMapperFactory {
+
+    @Override
+    public RowMapper<?> newColumnRowMapper() {
+        return new ColumnMapRowMapper();
+    }
+
+    @Override
+    public RowMapper<?> newBeanRowMapper(Class<?> mappedClass) {
+        return new BeanPropertyRowMapper<>(mappedClass);
+    }
+}
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
index a31f961ad71..b5d47c7770b 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/DefaultSqlEndpoint.java
@@ -30,8 +30,6 @@ import org.apache.camel.Component;
 import org.apache.camel.spi.Metadata;
 import org.apache.camel.spi.UriParam;
 import org.apache.camel.support.DefaultPollingEndpoint;
-import org.springframework.jdbc.core.BeanPropertyRowMapper;
-import org.springframework.jdbc.core.ColumnMapRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.jdbc.core.RowMapperResultSetExtractor;
@@ -128,6 +126,10 @@ public abstract class DefaultSqlEndpoint extends DefaultPollingEndpoint {
               description = "Configures the Spring JdbcTemplate with the key/values from the Map")
     private Map<String, Object> templateOptions;
 
+    @UriParam(label = "advanced",
+              description = "Factory for creating RowMapper")
+    private RowMapperFactory rowMapperFactory = new DefaultRowMapperFactory();
+
     public DefaultSqlEndpoint() {
     }
 
@@ -449,16 +451,27 @@ public abstract class DefaultSqlEndpoint extends DefaultPollingEndpoint {
         this.templateOptions = templateOptions;
     }
 
+    public RowMapperFactory getRowMapperFactory() {
+        return rowMapperFactory;
+    }
+
+    /**
+     * Factory for creating RowMapper
+     */
+    public void setRowMapperFactory(RowMapperFactory rowMapperFactory) {
+        this.rowMapperFactory = rowMapperFactory;
+    }
+
     @SuppressWarnings("unchecked")
     public List<?> queryForList(ResultSet rs, boolean allowMapToClass) throws SQLException {
         if (allowMapToClass && outputClass != null) {
             Class<?> outputClazz = getCamelContext().getClassResolver().resolveClass(outputClass);
-            RowMapper rowMapper = new BeanPropertyRowMapper(outputClazz);
+            RowMapper rowMapper = rowMapperFactory.newBeanRowMapper(outputClazz);
             RowMapperResultSetExtractor<?> mapper = new RowMapperResultSetExtractor(rowMapper);
             List<?> data = mapper.extractData(rs);
             return data;
         } else {
-            ColumnMapRowMapper rowMapper = new ColumnMapRowMapper();
+            RowMapper rowMapper = rowMapperFactory.newColumnRowMapper();
             RowMapperResultSetExtractor<Map<String, Object>> mapper = new RowMapperResultSetExtractor<>(rowMapper);
             List<Map<String, Object>> data = mapper.extractData(rs);
             return data;
@@ -469,7 +482,7 @@ public abstract class DefaultSqlEndpoint extends DefaultPollingEndpoint {
     public Object queryForObject(ResultSet rs) throws SQLException {
         Object result = null;
         if (outputClass == null) {
-            RowMapper rowMapper = new ColumnMapRowMapper();
+            RowMapper rowMapper = rowMapperFactory.newColumnRowMapper();
             RowMapperResultSetExtractor<Map<String, Object>> mapper
                     = new RowMapperResultSetExtractor<Map<String, Object>>(rowMapper);
             List<Map<String, Object>> data = mapper.extractData(rs);
@@ -487,7 +500,7 @@ public abstract class DefaultSqlEndpoint extends DefaultPollingEndpoint {
             }
         } else {
             Class<?> outputClzz = getCamelContext().getClassResolver().resolveClass(outputClass);
-            RowMapper rowMapper = new BeanPropertyRowMapper(outputClzz);
+            RowMapper rowMapper = rowMapperFactory.newBeanRowMapper(outputClzz);
             RowMapperResultSetExtractor<?> mapper = new RowMapperResultSetExtractor(rowMapper);
             List<?> data = mapper.extractData(rs);
             if (data.size() > 1) {
@@ -505,11 +518,11 @@ public abstract class DefaultSqlEndpoint extends DefaultPollingEndpoint {
     @SuppressWarnings("unchecked")
     public ResultSetIterator queryForStreamList(Connection connection, Statement statement, ResultSet rs) throws SQLException {
         if (outputClass == null) {
-            RowMapper rowMapper = new ColumnMapRowMapper();
+            RowMapper rowMapper = rowMapperFactory.newColumnRowMapper();
             return new ResultSetIterator(connection, statement, rs, rowMapper);
         } else {
             Class<?> outputClzz = getCamelContext().getClassResolver().resolveClass(outputClass);
-            RowMapper rowMapper = new BeanPropertyRowMapper(outputClzz);
+            RowMapper rowMapper = rowMapperFactory.newBeanRowMapper(outputClzz);
             return new ResultSetIterator(connection, statement, rs, rowMapper);
         }
     }
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/RowMapperFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/RowMapperFactory.java
new file mode 100644
index 00000000000..d663c049097
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/RowMapperFactory.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+package org.apache.camel.component.sql;
+
+import org.springframework.jdbc.core.RowMapper;
+
+/**
+ * Factory for creating {@link RowMapper}.
+ */
+public interface RowMapperFactory {
+
+    /**
+     * Creates a new column based row mapper
+     */
+    RowMapper<?> newColumnRowMapper();
+
+    /**
+     * Creates a new bean based row mapper
+     *
+     * @param mappedClass the mapped class
+     */
+    RowMapper<?> newBeanRowMapper(Class<?> mappedClass);
+
+}
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
index 6b558f83aca..3365c077874 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SqlEndpointBuilderFactory.java
@@ -1325,6 +1325,38 @@ public interface SqlEndpointBuilderFactory {
             doSetProperty("prepareStatementStrategy", prepareStatementStrategy);
             return this;
         }
+        /**
+         * Factory for creating RowMapper.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.sql.RowMapperFactory&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param rowMapperFactory the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSqlEndpointConsumerBuilder rowMapperFactory(
+                org.apache.camel.component.sql.RowMapperFactory rowMapperFactory) {
+            doSetProperty("rowMapperFactory", rowMapperFactory);
+            return this;
+        }
+        /**
+         * Factory for creating RowMapper.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.sql.RowMapperFactory&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param rowMapperFactory the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSqlEndpointConsumerBuilder rowMapperFactory(
+                String rowMapperFactory) {
+            doSetProperty("rowMapperFactory", rowMapperFactory);
+            return this;
+        }
         /**
          * Configures the Spring JdbcTemplate with the key/values from the Map.
          * 
@@ -1899,6 +1931,38 @@ public interface SqlEndpointBuilderFactory {
             doSetProperty("prepareStatementStrategy", prepareStatementStrategy);
             return this;
         }
+        /**
+         * Factory for creating RowMapper.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.sql.RowMapperFactory&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param rowMapperFactory the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSqlEndpointProducerBuilder rowMapperFactory(
+                org.apache.camel.component.sql.RowMapperFactory rowMapperFactory) {
+            doSetProperty("rowMapperFactory", rowMapperFactory);
+            return this;
+        }
+        /**
+         * Factory for creating RowMapper.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.sql.RowMapperFactory&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param rowMapperFactory the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSqlEndpointProducerBuilder rowMapperFactory(
+                String rowMapperFactory) {
+            doSetProperty("rowMapperFactory", rowMapperFactory);
+            return this;
+        }
         /**
          * Configures the Spring JdbcTemplate with the key/values from the Map.
          * 
@@ -2320,6 +2384,38 @@ public interface SqlEndpointBuilderFactory {
             doSetProperty("prepareStatementStrategy", prepareStatementStrategy);
             return this;
         }
+        /**
+         * Factory for creating RowMapper.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.component.sql.RowMapperFactory&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param rowMapperFactory the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSqlEndpointBuilder rowMapperFactory(
+                org.apache.camel.component.sql.RowMapperFactory rowMapperFactory) {
+            doSetProperty("rowMapperFactory", rowMapperFactory);
+            return this;
+        }
+        /**
+         * Factory for creating RowMapper.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.component.sql.RowMapperFactory&lt;/code&gt; type.
+         * 
+         * Group: advanced
+         * 
+         * @param rowMapperFactory the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSqlEndpointBuilder rowMapperFactory(
+                String rowMapperFactory) {
+            doSetProperty("rowMapperFactory", rowMapperFactory);
+            return this;
+        }
         /**
          * Configures the Spring JdbcTemplate with the key/values from the Map.
          *