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 2026/07/24 08:33:55 UTC
(camel) branch main updated: CAMEL-24245: Add camel-clickhouse component
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 5028d03a876a CAMEL-24245: Add camel-clickhouse component
5028d03a876a is described below
commit 5028d03a876abd98645cc7e4f04131b296332345
Author: Omar Atie <at...@gmail.com>
AuthorDate: Fri Jul 24 01:33:48 2026 -0700
CAMEL-24245: Add camel-clickhouse component
New producer-only component using the official ClickHouse Java client
(client-v2). Supports insert (native format streaming with WrappedFile
and client-side batching), query and ping operations. Connection via
shared autowired Client bean or serverUrl/username/password config at
component or endpoint level. Includes test-infra module, 19 unit tests,
2 integration tests, documentation and upgrade guide entry.
Closes #25034
Co-authored-by: Cursor Agent <cu...@cursor.com>
Co-authored-by: Claude Opus 4.6 <no...@anthropic.com>
---
bom/camel-bom/pom.xml | 5 +
catalog/camel-allcomponents/pom.xml | 5 +
.../org/apache/camel/catalog/components.properties | 1 +
.../camel/catalog/components/clickhouse.json | 60 +++
.../org/apache/camel/catalog/docs.properties | 1 +
.../camel/catalog/docs/clickhouse-component.adoc | 123 +++++
.../apache/camel/catalog/test-infra/metadata.json | 11 +
components/camel-clickhouse/pom.xml | 89 ++++
.../clickhouse/ClickHouseComponentConfigurer.java | 83 ++++
.../clickhouse/ClickHouseEndpointConfigurer.java | 96 ++++
.../clickhouse/ClickHouseEndpointUriFactory.java | 91 ++++
.../camel/component/clickhouse/clickhouse.json | 60 +++
.../services/org/apache/camel/component.properties | 7 +
.../services/org/apache/camel/component/clickhouse | 2 +
.../apache/camel/configurer/clickhouse-component | 2 +
.../apache/camel/configurer/clickhouse-endpoint | 2 +
.../apache/camel/urifactory/clickhouse-endpoint | 2 +
.../src/main/docs/clickhouse-component.adoc | 123 +++++
.../component/clickhouse/ClickHouseComponent.java | 134 +++++
.../component/clickhouse/ClickHouseConstants.java | 41 ++
.../component/clickhouse/ClickHouseEndpoint.java | 256 ++++++++++
.../component/clickhouse/ClickHouseException.java | 35 ++
.../component/clickhouse/ClickHouseOperation.java | 35 ++
.../component/clickhouse/ClickHouseProducer.java | 206 ++++++++
.../clickhouse/ClickHouseComponentTest.java | 133 +++++
.../clickhouse/ClickHouseProducerTest.java | 252 ++++++++++
.../integration/ClickHouseProducerIT.java | 116 +++++
.../src/test/resources/log4j2.properties | 29 ++
components/pom.xml | 1 +
.../org/apache/camel/main/components.properties | 1 +
.../modules/ROOT/examples/json/clickhouse.json | 1 +
docs/components/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/clickhouse-component.adoc | 1 +
.../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc | 20 +
.../component/ComponentsBuilderFactory.java | 14 +
.../dsl/ClickhouseComponentBuilderFactory.java | 230 +++++++++
.../builder/endpoint/EndpointBuilderFactory.java | 1 +
.../camel/builder/endpoint/EndpointBuilders.java | 1 +
.../builder/endpoint/EndpointHeaderBuilders.java | 14 +
.../builder/endpoint/StaticEndpointBuilders.java | 44 ++
.../dsl/ClickHouseEndpointBuilderFactory.java | 546 +++++++++++++++++++++
.../camel-component-known-dependencies.properties | 1 +
parent/pom.xml | 6 +
test-infra/camel-test-infra-all/pom.xml | 11 +
.../src/generated/resources/META-INF/metadata.json | 11 +
test-infra/camel-test-infra-clickhouse/pom.xml | 46 ++
.../clickhouse/common/ClickHouseProperties.java | 30 ++
.../services/ClickHouseInfraService.java | 37 ++
.../ClickHouseLocalContainerInfraService.java | 109 ++++
.../services/ClickHouseLocalContainerService.java | 21 +
.../clickhouse/services/ClickHouseService.java | 23 +
.../services/ClickHouseServiceFactory.java | 53 ++
.../services/RemoteClickHouseInfraService.java | 63 +++
.../infra/clickhouse/services/container.properties | 17 +
test-infra/pom.xml | 1 +
55 files changed, 3304 insertions(+)
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index bc88a80d9c3f..b249836ed7ca 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -501,6 +501,11 @@
<artifactId>camel-cli-debug</artifactId>
<version>4.22.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-clickhouse</artifactId>
+ <version>4.22.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-clickup</artifactId>
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index 1a90dfd62cd2..aa14c371f6f5 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -457,6 +457,11 @@
<artifactId>camel-chunk</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-clickhouse</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-clickup</artifactId>
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
index 91be0f1a521e..95f6e7e9cacc 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components.properties
@@ -67,6 +67,7 @@ camunda
chatscript
chunk
class
+clickhouse
clickup
cm-sms
coap
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/clickhouse.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/clickhouse.json
new file mode 100644
index 000000000000..ad15eb9e991e
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/clickhouse.json
@@ -0,0 +1,60 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "clickhouse",
+ "title": "ClickHouse",
+ "description": "Interact with ClickHouse, the high-performance columnar OLAP database, for high-throughput ingestion and OLAP queries.",
+ "deprecated": false,
+ "firstVersion": "4.22.0",
+ "label": "database,bigdata",
+ "javaType": "org.apache.camel.component.clickhouse.ClickHouseComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-clickhouse",
+ "version": "4.22.0-SNAPSHOT",
+ "scheme": "clickhouse",
+ "extendsScheme": "",
+ "syntax": "clickhouse:database",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": true,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "client": { "index": 0, "kind": "property", "displayName": "Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "com.clickhouse.client.api.Client", "deprecated": false, "autowired": true, "secret": false, "description": "The shared ClickHouse client to use for all endpoints, of type com.clickhouse.client.api.Client. When set, the endpoint-level connection options (serverUrl, username, password, ssl) are ignored." },
+ "compression": { "index": 1, "kind": "property", "displayName": "Compression", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to compress the insert request payload sent to the server (LZ4)." },
+ "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+ "serverUrl": { "index": 3, "kind": "property", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The ClickHouse HTTP endpoint URL, e.g. http:\/\/localhost:8123. Can be overridden per endpoint. Required unless a shared Client bean is autowired or configured on the component." },
+ "autowiredEnabled": { "index": 4, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+ "password": { "index": 5, "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password used to authenticate to ClickHouse." },
+ "ssl": { "index": 6, "kind": "property", "displayName": "Ssl", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to connect to ClickHouse over a secure (HTTPS) connection." },
+ "username": { "index": 7, "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "default", "description": "The username used to authenticate to ClickHouse." }
+ },
+ "headers": {
+ "CamelClickHouseOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the operation configured on the endpoint (insert, query or ping).", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#OPERATION" },
+ "CamelClickHouseDatabase": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the target database configured on the endpoint.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#DATABASE" },
+ "CamelClickHouseTable": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the target table configured on the endpoint.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#TABLE" },
+ "CamelClickHouseFormat": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the data format configured on the endpoint.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#FORMAT" },
+ "CamelClickHouseWrittenRows": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of rows written by an insert operation.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#WRITTEN_ROWS" },
+ "CamelClickHouseReadRows": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of rows read by a query operation.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#READ_ROWS" },
+ "CamelClickHousePingOk": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The boolean result of a ping operation.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#PING_OK" }
+ },
+ "properties": {
+ "database": { "index": 0, "kind": "path", "displayName": "Database", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The ClickHouse database. A table may also be provided using the database.table syntax." },
+ "asyncInsert": { "index": 1, "kind": "parameter", "displayName": "Async Insert", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use ClickHouse server-side asynchronous inserts (async_insert=1)." },
+ "batchSize": { "index": 2, "kind": "parameter", "displayName": "Batch Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "The client-side batch size for insert operations when the message body is a List. When greater than 0, the list is split into batches of this size and each batch is sent as a separate insert. A value of 0 (default) inserts the [...]
+ "compression": { "index": 3, "kind": "parameter", "displayName": "Compression", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to compress the insert request payload sent to the server (LZ4)." },
+ "format": { "index": 4, "kind": "parameter", "displayName": "Format", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "JSONEachRow", "description": "The ClickHouse data format used for insert and query operations, e.g. JSONEachRow, RowBinary, CSV, TSV or Parquet." },
+ "operation": { "index": 5, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.clickhouse.ClickHouseOperation", "enum": [ "INSERT", "QUERY", "PING" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INSERT", "description": "The operation to perform: insert, query or ping." },
+ "serverUrl": { "index": 6, "kind": "parameter", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The ClickHouse HTTP endpoint URL, e.g. http:\/\/localhost:8123. Required unless a shared Client bean is autowired or configured on the component." },
+ "table": { "index": 7, "kind": "parameter", "displayName": "Table", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The target table for insert operations. Can also be given in the path as database.table or overridden per message with the CamelClickHouseTable header." },
+ "waitForAsyncInsert": { "index": 8, "kind": "parameter", "displayName": "Wait For Async Insert", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When asyncInsert is enabled, whether the server should wait for the async insert to be flushed before acknowledging (wait_for_async_insert)." },
+ "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
+ "password": { "index": 10, "kind": "parameter", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "The password used to authenticate to ClickHouse." },
+ "ssl": { "index": 11, "kind": "parameter", "displayName": "Ssl", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to connect to ClickHouse over a secure (HTTPS) connection." },
+ "username": { "index": 12, "kind": "parameter", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "default", "description": "The username used to authenticate to ClickHouse." }
+ }
+}
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties
index 86aa824fbf01..920c31585e25 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties
@@ -100,6 +100,7 @@ claimCheck-eip
class-component
cli-connector
cli-debug
+clickhouse-component
clickup-component
cloudevents
cm-sms-component
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/clickhouse-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/clickhouse-component.adoc
new file mode 100644
index 000000000000..2c2bb0e5a500
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/clickhouse-component.adoc
@@ -0,0 +1,123 @@
+= ClickHouse Component
+:doctitle: ClickHouse
+:shortname: clickhouse
+:artifactid: camel-clickhouse
+:description: Interact with ClickHouse, the high-performance columnar OLAP database, for high-throughput ingestion and OLAP queries.
+:since: 4.22
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+
+*Since Camel {since}*
+
+*{component-header}*
+
+This component allows you to interact with https://clickhouse.com/[ClickHouse], the high-performance columnar OLAP
+database, using the official ClickHouse Java client (client-v2).
+
+While ClickHouse can be reached through the generic xref:jdbc-component.adoc[JDBC] and xref:sql-component.adoc[SQL]
+components, this dedicated component exposes ClickHouse's native capabilities as first-class endpoint options:
+native format streaming inserts (RowBinary, JSONEachRow, CSV, TSV, Parquet), server-side asynchronous inserts,
+OLAP queries and health checks.
+
+Maven users will need to add the following dependency to their `pom.xml`
+for this component:
+
+[source,xml]
+------------------------------------------------------------
+<dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-clickhouse</artifactId>
+ <version>x.x.x</version>
+ <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+== URI format
+
+-------------------------------
+clickhouse://database[.table]?[options]
+-------------------------------
+
+The producer can either use a shared `com.clickhouse.client.api.Client` bean (autowired from the registry) or build
+its own client from the `serverUrl`, `username`, `password` and `ssl` options. Connection settings can also be
+configured once on the **component** (for example `camel.component.clickhouse.serverUrl`) and inherited by every
+endpoint, so they do not need to be repeated in each URI.
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+== Operations
+
+The component is producer-only and supports the following operations, selected with the `operation` option or the
+`CamelClickHouseOperation` header:
+
+[cols="1,3", options="header"]
+|===
+| Operation | Description
+| `insert` (default) | Streams the message body into the target table using the configured `format`. Accepted body
+types are `InputStream`, `byte[]`, `String`, `java.io.File` (matched to the `format`), or a `List` of objects
+whose class has been registered on the shared `Client`. When the body is a `List` and `batchSize` is greater
+than 0, the list is split into batches of that size, each sent as a separate insert. The number of written
+rows is set on the `CamelClickHouseWrittenRows` header.
+| `query` | Runs the SQL statement contained in the message body and returns the result set (in the configured
+`format`) as a `String` body. The number of read rows is set on the `CamelClickHouseReadRows` header.
+| `ping` | Pings the ClickHouse server and sets the boolean result on both the message body and the
+`CamelClickHousePingOk` header.
+|===
+
+== Examples
+
+=== High-throughput event ingestion
+
+Batch-insert aggregated events into ClickHouse using the native `RowBinary` format:
+
+[source,java]
+----
+from("kafka:events?groupId=analytics")
+ .aggregate(constant(true), new GroupedBodyAggregationStrategy())
+ .completionSize(5000).completionTimeout(2000)
+ .to("clickhouse://analytics.events?operation=insert&format=RowBinary")
+ .log("Inserted ${header.CamelClickHouseWrittenRows} rows");
+----
+
+=== Server-side asynchronous inserts
+
+Let ClickHouse buffer and flush inserts server-side, ideal for many concurrent producers sending small payloads:
+
+[source,java]
+----
+from("platform-http:/ingest")
+ .to("clickhouse://metrics.samples?operation=insert&asyncInsert=true&waitForAsyncInsert=false");
+----
+
+=== Scheduled OLAP query
+
+Run an aggregation query on a timer and route the result set downstream:
+
+[source,java]
+----
+from("timer:rollup?period=60000")
+ .setBody(constant("SELECT count() FROM analytics.events"))
+ .to("clickhouse://analytics?operation=query&format=JSONEachRow")
+ .to("kafka:rollup-metrics");
+----
+
+=== Health check
+
+Verify connectivity to the ClickHouse server:
+
+[source,java]
+----
+from("timer:health?period=30000")
+ .to("clickhouse://default?operation=ping")
+ .choice()
+ .when(header("CamelClickHousePingOk").isEqualTo(true))
+ .to("direct:markHealthy")
+ .otherwise()
+ .to("direct:alertOps")
+ .end();
+----
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
index d0efd2259650..a1b236ed29ce 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/test-infra/metadata.json
@@ -691,6 +691,17 @@
"version" : "4.22.0-SNAPSHOT",
"serviceVersion" : "1.2.1",
"uiSupported" : false
+}, {
+ "service" : "org.apache.camel.test.infra.clickhouse.services.ClickHouseInfraService",
+ "description" : "ClickHouse is a high-performance columnar OLAP database",
+ "implementation" : "org.apache.camel.test.infra.clickhouse.services.ClickHouseLocalContainerInfraService",
+ "alias" : [ "clickhouse" ],
+ "aliasImplementation" : [ ],
+ "groupId" : "org.apache.camel",
+ "artifactId" : "camel-test-infra-clickhouse",
+ "version" : "4.22.0-SNAPSHOT",
+ "serviceVersion" : "24.8",
+ "uiSupported" : false
}, {
"service" : "org.apache.camel.test.infra.ollama.services.OllamaInfraService",
"description" : "Ollama is a tool for running large language models locally",
diff --git a/components/camel-clickhouse/pom.xml b/components/camel-clickhouse/pom.xml
new file mode 100644
index 000000000000..59d7e326d0cc
--- /dev/null
+++ b/components/camel-clickhouse/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>components</artifactId>
+ <version>4.22.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-clickhouse</artifactId>
+ <packaging>jar</packaging>
+ <name>Camel :: ClickHouse</name>
+ <description>Camel ClickHouse component</description>
+
+ <properties>
+ <!-- ClickHouse server container image is not available on these platforms -->
+ <skipITs.ppc64le>true</skipITs.ppc64le>
+ <skipITs.s390x>true</skipITs.s390x>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-support</artifactId>
+ </dependency>
+
+ <!-- ClickHouse client (v2) -->
+ <dependency>
+ <groupId>com.clickhouse</groupId>
+ <artifactId>client-v2</artifactId>
+ <version>${clickhouse-client-version}</version>
+ </dependency>
+
+ <!-- testing -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit6</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-clickhouse</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito-version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j2-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseComponentConfigurer.java b/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseComponentConfigurer.java
new file mode 100644
index 000000000000..70703eda0169
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseComponentConfigurer.java
@@ -0,0 +1,83 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.clickhouse;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class ClickHouseComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ ClickHouseComponent target = (ClickHouseComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
+ case "client": target.setClient(property(camelContext, com.clickhouse.client.api.Client.class, value)); return true;
+ case "compression": target.setCompression(property(camelContext, boolean.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "password": target.setPassword(property(camelContext, java.lang.String.class, value)); return true;
+ case "serverurl":
+ case "serverUrl": target.setServerUrl(property(camelContext, java.lang.String.class, value)); return true;
+ case "ssl": target.setSsl(property(camelContext, boolean.class, value)); return true;
+ case "username": target.setUsername(property(camelContext, java.lang.String.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public String[] getAutowiredNames() {
+ return new String[]{"client"};
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "client": return com.clickhouse.client.api.Client.class;
+ case "compression": return boolean.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "password": return java.lang.String.class;
+ case "serverurl":
+ case "serverUrl": return java.lang.String.class;
+ case "ssl": return boolean.class;
+ case "username": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ ClickHouseComponent target = (ClickHouseComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "client": return target.getClient();
+ case "compression": return target.isCompression();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "password": return target.getPassword();
+ case "serverurl":
+ case "serverUrl": return target.getServerUrl();
+ case "ssl": return target.isSsl();
+ case "username": return target.getUsername();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseEndpointConfigurer.java b/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseEndpointConfigurer.java
new file mode 100644
index 000000000000..83e9fe11b183
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseEndpointConfigurer.java
@@ -0,0 +1,96 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.clickhouse;
+
+import javax.annotation.processing.Generated;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointSchemaGeneratorMojo")
+@SuppressWarnings("unchecked")
+public class ClickHouseEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ ClickHouseEndpoint target = (ClickHouseEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "asyncinsert":
+ case "asyncInsert": target.setAsyncInsert(property(camelContext, boolean.class, value)); return true;
+ case "batchsize":
+ case "batchSize": target.setBatchSize(property(camelContext, int.class, value)); return true;
+ case "compression": target.setCompression(property(camelContext, boolean.class, value)); return true;
+ case "format": target.setFormat(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "operation": target.setOperation(property(camelContext, org.apache.camel.component.clickhouse.ClickHouseOperation.class, value)); return true;
+ case "password": target.setPassword(property(camelContext, java.lang.String.class, value)); return true;
+ case "serverurl":
+ case "serverUrl": target.setServerUrl(property(camelContext, java.lang.String.class, value)); return true;
+ case "ssl": target.setSsl(property(camelContext, boolean.class, value)); return true;
+ case "table": target.setTable(property(camelContext, java.lang.String.class, value)); return true;
+ case "username": target.setUsername(property(camelContext, java.lang.String.class, value)); return true;
+ case "waitforasyncinsert":
+ case "waitForAsyncInsert": target.setWaitForAsyncInsert(property(camelContext, boolean.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class<?> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "asyncinsert":
+ case "asyncInsert": return boolean.class;
+ case "batchsize":
+ case "batchSize": return int.class;
+ case "compression": return boolean.class;
+ case "format": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "operation": return org.apache.camel.component.clickhouse.ClickHouseOperation.class;
+ case "password": return java.lang.String.class;
+ case "serverurl":
+ case "serverUrl": return java.lang.String.class;
+ case "ssl": return boolean.class;
+ case "table": return java.lang.String.class;
+ case "username": return java.lang.String.class;
+ case "waitforasyncinsert":
+ case "waitForAsyncInsert": return boolean.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ ClickHouseEndpoint target = (ClickHouseEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "asyncinsert":
+ case "asyncInsert": return target.isAsyncInsert();
+ case "batchsize":
+ case "batchSize": return target.getBatchSize();
+ case "compression": return target.isCompression();
+ case "format": return target.getFormat();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "operation": return target.getOperation();
+ case "password": return target.getPassword();
+ case "serverurl":
+ case "serverUrl": return target.getServerUrl();
+ case "ssl": return target.isSsl();
+ case "table": return target.getTable();
+ case "username": return target.getUsername();
+ case "waitforasyncinsert":
+ case "waitForAsyncInsert": return target.isWaitForAsyncInsert();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseEndpointUriFactory.java b/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseEndpointUriFactory.java
new file mode 100644
index 000000000000..91939bc52ee7
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/java/org/apache/camel/component/clickhouse/ClickHouseEndpointUriFactory.java
@@ -0,0 +1,91 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.clickhouse;
+
+import javax.annotation.processing.Generated;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.spi.EndpointUriFactory;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.GenerateEndpointUriFactoryMojo")
+public class ClickHouseEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory {
+
+ private static final String BASE = ":database";
+
+ private static final Set<String> PROPERTY_NAMES;
+ private static final Set<String> SECRET_PROPERTY_NAMES;
+ private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
+ private static final Map<String, String> MULTI_VALUE_PREFIXES;
+ static {
+ Set<String> props = new HashSet<>(13);
+ props.add("asyncInsert");
+ props.add("batchSize");
+ props.add("compression");
+ props.add("database");
+ props.add("format");
+ props.add("lazyStartProducer");
+ props.add("operation");
+ props.add("password");
+ props.add("serverUrl");
+ props.add("ssl");
+ props.add("table");
+ props.add("username");
+ props.add("waitForAsyncInsert");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ Set<String> secretProps = new HashSet<>(1);
+ secretProps.add("password");
+ SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
+ ENDPOINT_IDENTITY_PROPERTY_NAMES = Collections.emptySet();
+ MULTI_VALUE_PREFIXES = Collections.emptyMap();
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "clickhouse".equals(scheme);
+ }
+
+ @Override
+ public String buildUri(String scheme, Map<String, Object> properties, boolean encode) throws URISyntaxException {
+ String syntax = scheme + BASE;
+ String uri = syntax;
+
+ Map<String, Object> copy = new HashMap<>(properties);
+
+ uri = buildPathParameter(syntax, uri, "database", null, true, copy);
+ uri = buildQueryParameters(uri, copy, encode);
+ return uri;
+ }
+
+ @Override
+ public Set<String> propertyNames() {
+ return PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> secretPropertyNames() {
+ return SECRET_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set<String> endpointIdentityPropertyNames() {
+ return ENDPOINT_IDENTITY_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Map<String, String> multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
diff --git a/components/camel-clickhouse/src/generated/resources/META-INF/org/apache/camel/component/clickhouse/clickhouse.json b/components/camel-clickhouse/src/generated/resources/META-INF/org/apache/camel/component/clickhouse/clickhouse.json
new file mode 100644
index 000000000000..ad15eb9e991e
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/resources/META-INF/org/apache/camel/component/clickhouse/clickhouse.json
@@ -0,0 +1,60 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "clickhouse",
+ "title": "ClickHouse",
+ "description": "Interact with ClickHouse, the high-performance columnar OLAP database, for high-throughput ingestion and OLAP queries.",
+ "deprecated": false,
+ "firstVersion": "4.22.0",
+ "label": "database,bigdata",
+ "javaType": "org.apache.camel.component.clickhouse.ClickHouseComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-clickhouse",
+ "version": "4.22.0-SNAPSHOT",
+ "scheme": "clickhouse",
+ "extendsScheme": "",
+ "syntax": "clickhouse:database",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": true,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "client": { "index": 0, "kind": "property", "displayName": "Client", "group": "producer", "label": "", "required": false, "type": "object", "javaType": "com.clickhouse.client.api.Client", "deprecated": false, "autowired": true, "secret": false, "description": "The shared ClickHouse client to use for all endpoints, of type com.clickhouse.client.api.Client. When set, the endpoint-level connection options (serverUrl, username, password, ssl) are ignored." },
+ "compression": { "index": 1, "kind": "property", "displayName": "Compression", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to compress the insert request payload sent to the server (LZ4)." },
+ "lazyStartProducer": { "index": 2, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail [...]
+ "serverUrl": { "index": 3, "kind": "property", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The ClickHouse HTTP endpoint URL, e.g. http:\/\/localhost:8123. Can be overridden per endpoint. Required unless a shared Client bean is autowired or configured on the component." },
+ "autowiredEnabled": { "index": 4, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching t [...]
+ "password": { "index": 5, "kind": "property", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "description": "The password used to authenticate to ClickHouse." },
+ "ssl": { "index": 6, "kind": "property", "displayName": "Ssl", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to connect to ClickHouse over a secure (HTTPS) connection." },
+ "username": { "index": 7, "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "default", "description": "The username used to authenticate to ClickHouse." }
+ },
+ "headers": {
+ "CamelClickHouseOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the operation configured on the endpoint (insert, query or ping).", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#OPERATION" },
+ "CamelClickHouseDatabase": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the target database configured on the endpoint.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#DATABASE" },
+ "CamelClickHouseTable": { "index": 2, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the target table configured on the endpoint.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#TABLE" },
+ "CamelClickHouseFormat": { "index": 3, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Overrides the data format configured on the endpoint.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#FORMAT" },
+ "CamelClickHouseWrittenRows": { "index": 4, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of rows written by an insert operation.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#WRITTEN_ROWS" },
+ "CamelClickHouseReadRows": { "index": 5, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The number of rows read by a query operation.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#READ_ROWS" },
+ "CamelClickHousePingOk": { "index": 6, "kind": "header", "displayName": "", "group": "producer", "label": "", "required": false, "javaType": "boolean", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The boolean result of a ping operation.", "constantName": "org.apache.camel.component.clickhouse.ClickHouseConstants#PING_OK" }
+ },
+ "properties": {
+ "database": { "index": 0, "kind": "path", "displayName": "Database", "group": "producer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The ClickHouse database. A table may also be provided using the database.table syntax." },
+ "asyncInsert": { "index": 1, "kind": "parameter", "displayName": "Async Insert", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use ClickHouse server-side asynchronous inserts (async_insert=1)." },
+ "batchSize": { "index": 2, "kind": "parameter", "displayName": "Batch Size", "group": "producer", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "The client-side batch size for insert operations when the message body is a List. When greater than 0, the list is split into batches of this size and each batch is sent as a separate insert. A value of 0 (default) inserts the [...]
+ "compression": { "index": 3, "kind": "parameter", "displayName": "Compression", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to compress the insert request payload sent to the server (LZ4)." },
+ "format": { "index": 4, "kind": "parameter", "displayName": "Format", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "JSONEachRow", "description": "The ClickHouse data format used for insert and query operations, e.g. JSONEachRow, RowBinary, CSV, TSV or Parquet." },
+ "operation": { "index": 5, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "", "required": false, "type": "enum", "javaType": "org.apache.camel.component.clickhouse.ClickHouseOperation", "enum": [ "INSERT", "QUERY", "PING" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "INSERT", "description": "The operation to perform: insert, query or ping." },
+ "serverUrl": { "index": 6, "kind": "parameter", "displayName": "Server Url", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The ClickHouse HTTP endpoint URL, e.g. http:\/\/localhost:8123. Required unless a shared Client bean is autowired or configured on the component." },
+ "table": { "index": 7, "kind": "parameter", "displayName": "Table", "group": "producer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The target table for insert operations. Can also be given in the path as database.table or overridden per message with the CamelClickHouseTable header." },
+ "waitForAsyncInsert": { "index": 8, "kind": "parameter", "displayName": "Wait For Async Insert", "group": "producer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "When asyncInsert is enabled, whether the server should wait for the async insert to be flushed before acknowledging (wait_for_async_insert)." },
+ "lazyStartProducer": { "index": 9, "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a produc [...]
+ "password": { "index": 10, "kind": "parameter", "displayName": "Password", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "security": "secret", "description": "The password used to authenticate to ClickHouse." },
+ "ssl": { "index": 11, "kind": "parameter", "displayName": "Ssl", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to connect to ClickHouse over a secure (HTTPS) connection." },
+ "username": { "index": 12, "kind": "parameter", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "default", "description": "The username used to authenticate to ClickHouse." }
+ }
+}
diff --git a/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 000000000000..deaf99d05af2
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=clickhouse
+groupId=org.apache.camel
+artifactId=camel-clickhouse
+version=4.22.0-SNAPSHOT
+projectName=Camel :: ClickHouse
+projectDescription=Camel ClickHouse component
diff --git a/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/component/clickhouse b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/component/clickhouse
new file mode 100644
index 000000000000..414a9667aca0
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/component/clickhouse
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.clickhouse.ClickHouseComponent
diff --git a/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/configurer/clickhouse-component b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/configurer/clickhouse-component
new file mode 100644
index 000000000000..8a0436243abc
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/configurer/clickhouse-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.clickhouse.ClickHouseComponentConfigurer
diff --git a/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/configurer/clickhouse-endpoint b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/configurer/clickhouse-endpoint
new file mode 100644
index 000000000000..457270e57f2f
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/configurer/clickhouse-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.clickhouse.ClickHouseEndpointConfigurer
diff --git a/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/urifactory/clickhouse-endpoint b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/urifactory/clickhouse-endpoint
new file mode 100644
index 000000000000..b71c4f491fd2
--- /dev/null
+++ b/components/camel-clickhouse/src/generated/resources/META-INF/services/org/apache/camel/urifactory/clickhouse-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.clickhouse.ClickHouseEndpointUriFactory
diff --git a/components/camel-clickhouse/src/main/docs/clickhouse-component.adoc b/components/camel-clickhouse/src/main/docs/clickhouse-component.adoc
new file mode 100644
index 000000000000..2c2bb0e5a500
--- /dev/null
+++ b/components/camel-clickhouse/src/main/docs/clickhouse-component.adoc
@@ -0,0 +1,123 @@
+= ClickHouse Component
+:doctitle: ClickHouse
+:shortname: clickhouse
+:artifactid: camel-clickhouse
+:description: Interact with ClickHouse, the high-performance columnar OLAP database, for high-throughput ingestion and OLAP queries.
+:since: 4.22
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Only producer is supported
+
+*Since Camel {since}*
+
+*{component-header}*
+
+This component allows you to interact with https://clickhouse.com/[ClickHouse], the high-performance columnar OLAP
+database, using the official ClickHouse Java client (client-v2).
+
+While ClickHouse can be reached through the generic xref:jdbc-component.adoc[JDBC] and xref:sql-component.adoc[SQL]
+components, this dedicated component exposes ClickHouse's native capabilities as first-class endpoint options:
+native format streaming inserts (RowBinary, JSONEachRow, CSV, TSV, Parquet), server-side asynchronous inserts,
+OLAP queries and health checks.
+
+Maven users will need to add the following dependency to their `pom.xml`
+for this component:
+
+[source,xml]
+------------------------------------------------------------
+<dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-clickhouse</artifactId>
+ <version>x.x.x</version>
+ <!-- use the same version as your Camel core version -->
+</dependency>
+------------------------------------------------------------
+
+== URI format
+
+-------------------------------
+clickhouse://database[.table]?[options]
+-------------------------------
+
+The producer can either use a shared `com.clickhouse.client.api.Client` bean (autowired from the registry) or build
+its own client from the `serverUrl`, `username`, `password` and `ssl` options. Connection settings can also be
+configured once on the **component** (for example `camel.component.clickhouse.serverUrl`) and inherited by every
+endpoint, so they do not need to be repeated in each URI.
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+include::partial$component-endpoint-headers.adoc[]
+// component options: END
+
+== Operations
+
+The component is producer-only and supports the following operations, selected with the `operation` option or the
+`CamelClickHouseOperation` header:
+
+[cols="1,3", options="header"]
+|===
+| Operation | Description
+| `insert` (default) | Streams the message body into the target table using the configured `format`. Accepted body
+types are `InputStream`, `byte[]`, `String`, `java.io.File` (matched to the `format`), or a `List` of objects
+whose class has been registered on the shared `Client`. When the body is a `List` and `batchSize` is greater
+than 0, the list is split into batches of that size, each sent as a separate insert. The number of written
+rows is set on the `CamelClickHouseWrittenRows` header.
+| `query` | Runs the SQL statement contained in the message body and returns the result set (in the configured
+`format`) as a `String` body. The number of read rows is set on the `CamelClickHouseReadRows` header.
+| `ping` | Pings the ClickHouse server and sets the boolean result on both the message body and the
+`CamelClickHousePingOk` header.
+|===
+
+== Examples
+
+=== High-throughput event ingestion
+
+Batch-insert aggregated events into ClickHouse using the native `RowBinary` format:
+
+[source,java]
+----
+from("kafka:events?groupId=analytics")
+ .aggregate(constant(true), new GroupedBodyAggregationStrategy())
+ .completionSize(5000).completionTimeout(2000)
+ .to("clickhouse://analytics.events?operation=insert&format=RowBinary")
+ .log("Inserted ${header.CamelClickHouseWrittenRows} rows");
+----
+
+=== Server-side asynchronous inserts
+
+Let ClickHouse buffer and flush inserts server-side, ideal for many concurrent producers sending small payloads:
+
+[source,java]
+----
+from("platform-http:/ingest")
+ .to("clickhouse://metrics.samples?operation=insert&asyncInsert=true&waitForAsyncInsert=false");
+----
+
+=== Scheduled OLAP query
+
+Run an aggregation query on a timer and route the result set downstream:
+
+[source,java]
+----
+from("timer:rollup?period=60000")
+ .setBody(constant("SELECT count() FROM analytics.events"))
+ .to("clickhouse://analytics?operation=query&format=JSONEachRow")
+ .to("kafka:rollup-metrics");
+----
+
+=== Health check
+
+Verify connectivity to the ClickHouse server:
+
+[source,java]
+----
+from("timer:health?period=30000")
+ .to("clickhouse://default?operation=ping")
+ .choice()
+ .when(header("CamelClickHousePingOk").isEqualTo(true))
+ .to("direct:markHealthy")
+ .otherwise()
+ .to("direct:alertOps")
+ .end();
+----
diff --git a/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseComponent.java b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseComponent.java
new file mode 100644
index 000000000000..9577e453b6f4
--- /dev/null
+++ b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseComponent.java
@@ -0,0 +1,134 @@
+/*
+ * 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.clickhouse;
+
+import java.util.Map;
+
+import com.clickhouse.client.api.Client;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+import org.apache.camel.util.ObjectHelper;
+
+@Component("clickhouse")
+public class ClickHouseComponent extends DefaultComponent {
+
+ @Metadata(autowired = true)
+ private Client client;
+ @Metadata(description = "The ClickHouse HTTP endpoint URL, e.g. http://localhost:8123. Can be overridden per endpoint."
+ + " Required unless a shared Client bean is autowired or configured on the component.")
+ private String serverUrl;
+ @Metadata(label = "security", defaultValue = "default", description = "The username used to authenticate to ClickHouse.")
+ private String username = "default";
+ @Metadata(label = "security", secret = true, description = "The password used to authenticate to ClickHouse.")
+ private String password;
+ @Metadata(label = "security", defaultValue = "false",
+ description = "Whether to connect to ClickHouse over a secure (HTTPS) connection.")
+ private boolean ssl;
+ @Metadata(defaultValue = "false",
+ description = "Whether to compress the insert request payload sent to the server (LZ4).")
+ private boolean compression;
+
+ public ClickHouseComponent() {
+ }
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+ if (ObjectHelper.isEmpty(remaining)) {
+ throw new IllegalArgumentException(
+ "A database (and optionally a table) must be configured on the URI path, e.g. clickhouse://database.table");
+ }
+
+ ClickHouseEndpoint endpoint = new ClickHouseEndpoint(uri, this);
+ endpoint.setClient(client);
+ if (ObjectHelper.isNotEmpty(serverUrl)) {
+ endpoint.setServerUrl(serverUrl);
+ }
+ endpoint.setUsername(username);
+ endpoint.setPassword(password);
+ endpoint.setSsl(ssl);
+ endpoint.setCompression(compression);
+
+ String database = remaining;
+ String table = null;
+ int dot = remaining.indexOf('.');
+ if (dot > 0) {
+ database = remaining.substring(0, dot);
+ table = remaining.substring(dot + 1);
+ }
+ endpoint.setDatabase(database);
+ if (ObjectHelper.isNotEmpty(table)) {
+ endpoint.setTable(table);
+ }
+
+ setProperties(endpoint, parameters);
+ return endpoint;
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ /**
+ * The shared ClickHouse client to use for all endpoints, of type {@code com.clickhouse.client.api.Client}. When
+ * set, the endpoint-level connection options (serverUrl, username, password, ssl) are ignored.
+ */
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ public void setServerUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isSsl() {
+ return ssl;
+ }
+
+ public void setSsl(boolean ssl) {
+ this.ssl = ssl;
+ }
+
+ public boolean isCompression() {
+ return compression;
+ }
+
+ public void setCompression(boolean compression) {
+ this.compression = compression;
+ }
+}
diff --git a/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseConstants.java b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseConstants.java
new file mode 100644
index 000000000000..1bc03b65844c
--- /dev/null
+++ b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseConstants.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.clickhouse;
+
+import org.apache.camel.spi.Metadata;
+
+public final class ClickHouseConstants {
+
+ @Metadata(description = "Overrides the operation configured on the endpoint (insert, query or ping).",
+ javaType = "String")
+ public static final String OPERATION = "CamelClickHouseOperation";
+ @Metadata(description = "Overrides the target database configured on the endpoint.", javaType = "String")
+ public static final String DATABASE = "CamelClickHouseDatabase";
+ @Metadata(description = "Overrides the target table configured on the endpoint.", javaType = "String")
+ public static final String TABLE = "CamelClickHouseTable";
+ @Metadata(description = "Overrides the data format configured on the endpoint.", javaType = "String")
+ public static final String FORMAT = "CamelClickHouseFormat";
+ @Metadata(description = "The number of rows written by an insert operation.", javaType = "long")
+ public static final String WRITTEN_ROWS = "CamelClickHouseWrittenRows";
+ @Metadata(description = "The number of rows read by a query operation.", javaType = "long")
+ public static final String READ_ROWS = "CamelClickHouseReadRows";
+ @Metadata(description = "The boolean result of a ping operation.", javaType = "boolean")
+ public static final String PING_OK = "CamelClickHousePingOk";
+
+ private ClickHouseConstants() {
+ }
+}
diff --git a/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseEndpoint.java b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseEndpoint.java
new file mode 100644
index 000000000000..e9dcbac2b810
--- /dev/null
+++ b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseEndpoint.java
@@ -0,0 +1,256 @@
+/*
+ * 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.clickhouse;
+
+import com.clickhouse.client.api.Client;
+import org.apache.camel.Category;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.DefaultEndpoint;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * Interact with <a href="https://clickhouse.com/">ClickHouse</a>, the high-performance columnar OLAP database, for
+ * high-throughput ingestion and OLAP queries.
+ */
+@UriEndpoint(firstVersion = "4.22.0", scheme = "clickhouse", title = "ClickHouse",
+ syntax = "clickhouse:database", category = { Category.DATABASE, Category.BIGDATA },
+ producerOnly = true, headersClass = ClickHouseConstants.class)
+public class ClickHouseEndpoint extends DefaultEndpoint {
+
+ private Client client;
+ private boolean clientCreated;
+
+ @UriPath
+ @Metadata(required = true,
+ description = "The ClickHouse database. A table may also be provided using the database.table syntax.")
+ private String database;
+ @UriParam(description = "The target table for insert operations. Can also be given in the path as database.table"
+ + " or overridden per message with the CamelClickHouseTable header.")
+ private String table;
+ @UriParam(description = "The ClickHouse HTTP endpoint URL, e.g. http://localhost:8123. Required unless a shared"
+ + " Client bean is autowired or configured on the component.")
+ private String serverUrl;
+ @UriParam(label = "security", defaultValue = "default", description = "The username used to authenticate to ClickHouse.")
+ private String username = "default";
+ @UriParam(label = "security", secret = true, description = "The password used to authenticate to ClickHouse.")
+ private String password;
+ @UriParam(label = "security", defaultValue = "false",
+ description = "Whether to connect to ClickHouse over a secure (HTTPS) connection.")
+ private boolean ssl;
+ @UriParam(defaultValue = "INSERT", description = "The operation to perform: insert, query or ping.")
+ private ClickHouseOperation operation = ClickHouseOperation.INSERT;
+ @UriParam(defaultValue = "JSONEachRow",
+ description = "The ClickHouse data format used for insert and query operations, e.g. JSONEachRow,"
+ + " RowBinary, CSV, TSV or Parquet.")
+ private String format = "JSONEachRow";
+ @UriParam(defaultValue = "0",
+ description = "The client-side batch size for insert operations when the message body is a List. When"
+ + " greater than 0, the list is split into batches of this size and each batch is sent as a"
+ + " separate insert. A value of 0 (default) inserts the whole list in a single call.")
+ private int batchSize;
+ @UriParam(defaultValue = "false",
+ description = "Whether to use ClickHouse server-side asynchronous inserts (async_insert=1).")
+ private boolean asyncInsert;
+ @UriParam(defaultValue = "true",
+ description = "When asyncInsert is enabled, whether the server should wait for the async insert to be"
+ + " flushed before acknowledging (wait_for_async_insert).")
+ private boolean waitForAsyncInsert = true;
+ @UriParam(defaultValue = "false",
+ description = "Whether to compress the insert request payload sent to the server (LZ4).")
+ private boolean compression;
+
+ public ClickHouseEndpoint() {
+ }
+
+ public ClickHouseEndpoint(String uri, ClickHouseComponent component) {
+ super(uri, component);
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ return new ClickHouseProducer(this);
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ throw new UnsupportedOperationException("You cannot receive messages from this endpoint");
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ if (client != null) {
+ return;
+ }
+ if (ObjectHelper.isEmpty(serverUrl)) {
+ throw new IllegalArgumentException(
+ "Either a shared Client must be autowired or the serverUrl option must be configured");
+ }
+ client = createClient();
+ clientCreated = true;
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ if (clientCreated && client != null) {
+ client.close();
+ client = null;
+ clientCreated = false;
+ }
+ super.doStop();
+ }
+
+ public Client getClient() {
+ return client;
+ }
+
+ private Client createClient() {
+ Client.Builder builder = new Client.Builder()
+ .addEndpoint(resolveEndpointUrl())
+ .setUsername(username)
+ .setPassword(password != null ? password : "");
+ if (ObjectHelper.isNotEmpty(database)) {
+ builder.setDefaultDatabase(database);
+ }
+ if (compression) {
+ builder.compressClientRequest(true);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Resolves the endpoint URL, upgrading the scheme to HTTPS when the {@code ssl} option is enabled. The ClickHouse
+ * client-v2 derives the transport security from the endpoint URL scheme.
+ */
+ String resolveEndpointUrl() {
+ if (ssl) {
+ if (serverUrl.startsWith("http://")) {
+ return "https://" + serverUrl.substring("http://".length());
+ }
+ if (!serverUrl.startsWith("https://")) {
+ return "https://" + serverUrl;
+ }
+ }
+ return serverUrl;
+ }
+
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ public String getDatabase() {
+ return database;
+ }
+
+ public void setDatabase(String database) {
+ this.database = database;
+ }
+
+ public String getTable() {
+ return table;
+ }
+
+ public void setTable(String table) {
+ this.table = table;
+ }
+
+ public String getServerUrl() {
+ return serverUrl;
+ }
+
+ public void setServerUrl(String serverUrl) {
+ this.serverUrl = serverUrl;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isSsl() {
+ return ssl;
+ }
+
+ public void setSsl(boolean ssl) {
+ this.ssl = ssl;
+ }
+
+ public ClickHouseOperation getOperation() {
+ return operation;
+ }
+
+ public void setOperation(ClickHouseOperation operation) {
+ this.operation = operation;
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ public void setFormat(String format) {
+ this.format = format;
+ }
+
+ public int getBatchSize() {
+ return batchSize;
+ }
+
+ public void setBatchSize(int batchSize) {
+ this.batchSize = batchSize;
+ }
+
+ public boolean isAsyncInsert() {
+ return asyncInsert;
+ }
+
+ public void setAsyncInsert(boolean asyncInsert) {
+ this.asyncInsert = asyncInsert;
+ }
+
+ public boolean isWaitForAsyncInsert() {
+ return waitForAsyncInsert;
+ }
+
+ public void setWaitForAsyncInsert(boolean waitForAsyncInsert) {
+ this.waitForAsyncInsert = waitForAsyncInsert;
+ }
+
+ public boolean isCompression() {
+ return compression;
+ }
+
+ public void setCompression(boolean compression) {
+ this.compression = compression;
+ }
+}
diff --git a/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseException.java b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseException.java
new file mode 100644
index 000000000000..bae36ca361a5
--- /dev/null
+++ b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.clickhouse;
+
+/**
+ * Exception thrown when a ClickHouse operation fails.
+ */
+public class ClickHouseException extends RuntimeException {
+
+ public ClickHouseException(String message) {
+ super(message);
+ }
+
+ public ClickHouseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ClickHouseException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseOperation.java b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseOperation.java
new file mode 100644
index 000000000000..ca1172c15ebe
--- /dev/null
+++ b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseOperation.java
@@ -0,0 +1,35 @@
+/*
+ * 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.clickhouse;
+
+/**
+ * The operations the ClickHouse producer can perform.
+ */
+public enum ClickHouseOperation {
+ /**
+ * Insert (stream) data into a table.
+ */
+ INSERT,
+ /**
+ * Run a SQL query and return the result set.
+ */
+ QUERY,
+ /**
+ * Ping the ClickHouse server to verify connectivity.
+ */
+ PING
+}
diff --git a/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseProducer.java b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseProducer.java
new file mode 100644
index 000000000000..823f6a5f7740
--- /dev/null
+++ b/components/camel-clickhouse/src/main/java/org/apache/camel/component/clickhouse/ClickHouseProducer.java
@@ -0,0 +1,206 @@
+/*
+ * 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.clickhouse;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import com.clickhouse.client.api.Client;
+import com.clickhouse.client.api.insert.InsertResponse;
+import com.clickhouse.client.api.insert.InsertSettings;
+import com.clickhouse.client.api.query.QueryResponse;
+import com.clickhouse.client.api.query.QuerySettings;
+import com.clickhouse.data.ClickHouseFormat;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.WrappedFile;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClickHouseProducer extends DefaultProducer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ClickHouseProducer.class);
+
+ private final ClickHouseEndpoint endpoint;
+
+ public ClickHouseProducer(ClickHouseEndpoint endpoint) {
+ super(endpoint);
+ this.endpoint = endpoint;
+ }
+
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ ClickHouseOperation operation = resolveOperation(exchange);
+ switch (operation) {
+ case INSERT -> doInsert(exchange);
+ case QUERY -> doQuery(exchange);
+ case PING -> doPing(exchange);
+ default -> throw new ClickHouseException("Unsupported operation: " + operation);
+ }
+ }
+
+ private void doInsert(Exchange exchange) throws Exception {
+ Client client = endpoint.getClient();
+ String target = resolveTable(exchange);
+ if (ObjectHelper.isEmpty(target)) {
+ throw new ClickHouseException(
+ "A table is required for insert operations. Provide it via the URI path (database.table),"
+ + " the table option, or the " + ClickHouseConstants.TABLE + " header.");
+ }
+
+ InsertSettings settings = new InsertSettings();
+ String database = resolveDatabase(exchange);
+ if (ObjectHelper.isNotEmpty(database)) {
+ settings.setDatabase(database);
+ }
+ if (endpoint.isAsyncInsert()) {
+ settings.serverSetting("async_insert", "1");
+ settings.serverSetting("wait_for_async_insert", endpoint.isWaitForAsyncInsert() ? "1" : "0");
+ }
+
+ Object body = exchange.getIn().getBody();
+ if (body instanceof WrappedFile<?> wrappedFile) {
+ body = wrappedFile.getBody();
+ }
+ long writtenRows;
+ if (body instanceof List) {
+ List<?> data = exchange.getIn().getBody(List.class);
+ writtenRows = insertList(client, target, data, settings);
+ } else {
+ InputStream stream = null;
+ boolean createdStream = false;
+ try {
+ if (body instanceof InputStream is) {
+ stream = is;
+ } else if (body instanceof byte[] bytes) {
+ stream = new ByteArrayInputStream(bytes);
+ createdStream = true;
+ } else if (body instanceof File file) {
+ stream = new FileInputStream(file);
+ createdStream = true;
+ } else if (body instanceof String str) {
+ stream = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));
+ createdStream = true;
+ } else {
+ stream = exchange.getIn().getMandatoryBody(InputStream.class);
+ }
+
+ ClickHouseFormat format = resolveFormat(exchange);
+ try (InsertResponse response = client.insert(target, stream, format, settings).get()) {
+ writtenRows = response.getWrittenRows();
+ }
+ } finally {
+ if (createdStream) {
+ IOHelper.close(stream);
+ }
+ }
+ }
+
+ LOG.debug("Inserted {} rows into {}", writtenRows, target);
+ exchange.getMessage().setHeader(ClickHouseConstants.WRITTEN_ROWS, writtenRows);
+ }
+
+ private long insertList(Client client, String target, List<?> data, InsertSettings settings) throws Exception {
+ int batchSize = endpoint.getBatchSize();
+ if (batchSize <= 0 || data.size() <= batchSize) {
+ try (InsertResponse response = client.insert(target, data, settings).get()) {
+ return response.getWrittenRows();
+ }
+ }
+
+ // split the list into batches of batchSize, inserting each batch separately
+ long writtenRows = 0;
+ for (int start = 0; start < data.size(); start += batchSize) {
+ List<?> batch = data.subList(start, Math.min(start + batchSize, data.size()));
+ try (InsertResponse response = client.insert(target, batch, settings).get()) {
+ writtenRows += response.getWrittenRows();
+ }
+ }
+ return writtenRows;
+ }
+
+ private void doQuery(Exchange exchange) throws Exception {
+ Client client = endpoint.getClient();
+ String sql = exchange.getIn().getBody(String.class);
+ if (ObjectHelper.isEmpty(sql)) {
+ throw new ClickHouseException("The SQL query must be provided in the message body for the query operation");
+ }
+
+ QuerySettings settings = new QuerySettings();
+ settings.setFormat(resolveFormat(exchange));
+ String database = resolveDatabase(exchange);
+ if (ObjectHelper.isNotEmpty(database)) {
+ settings.setDatabase(database);
+ }
+
+ try (QueryResponse response = client.query(sql, settings).get()) {
+ String result;
+ try (InputStream is = response.getInputStream()) {
+ result = new String(is.readAllBytes(), StandardCharsets.UTF_8);
+ }
+ Message message = exchange.getMessage();
+ message.setHeader(ClickHouseConstants.READ_ROWS, response.getReadRows());
+ message.setBody(result);
+ }
+ }
+
+ private void doPing(Exchange exchange) {
+ boolean ok = endpoint.getClient().ping();
+ Message message = exchange.getMessage();
+ message.setHeader(ClickHouseConstants.PING_OK, ok);
+ message.setBody(ok);
+ }
+
+ private ClickHouseOperation resolveOperation(Exchange exchange) {
+ String header = exchange.getIn().getHeader(ClickHouseConstants.OPERATION, String.class);
+ if (ObjectHelper.isNotEmpty(header)) {
+ return ClickHouseOperation.valueOf(header.trim().toUpperCase());
+ }
+ return endpoint.getOperation();
+ }
+
+ private ClickHouseFormat resolveFormat(Exchange exchange) {
+ String format = exchange.getIn().getHeader(ClickHouseConstants.FORMAT, String.class);
+ if (ObjectHelper.isEmpty(format)) {
+ format = endpoint.getFormat();
+ }
+ return ClickHouseFormat.valueOf(format);
+ }
+
+ private String resolveDatabase(Exchange exchange) {
+ String database = exchange.getIn().getHeader(ClickHouseConstants.DATABASE, String.class);
+ if (ObjectHelper.isNotEmpty(database)) {
+ return database;
+ }
+ return endpoint.getDatabase();
+ }
+
+ private String resolveTable(Exchange exchange) {
+ String table = exchange.getIn().getHeader(ClickHouseConstants.TABLE, String.class);
+ if (ObjectHelper.isNotEmpty(table)) {
+ return table;
+ }
+ return endpoint.getTable();
+ }
+}
diff --git a/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/ClickHouseComponentTest.java b/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/ClickHouseComponentTest.java
new file mode 100644
index 000000000000..d111d08542f4
--- /dev/null
+++ b/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/ClickHouseComponentTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.clickhouse;
+
+import org.apache.camel.ResolveEndpointFailedException;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+class ClickHouseComponentTest extends CamelTestSupport {
+
+ private static final String URL = "serverUrl=http://localhost:8123";
+
+ @Test
+ void createEndpointParsesDatabaseAndTableFromPath() {
+ ClickHouseEndpoint endpoint = context.getEndpoint(
+ "clickhouse://analytics.events?" + URL, ClickHouseEndpoint.class);
+
+ assertThat(endpoint.getDatabase()).isEqualTo("analytics");
+ assertThat(endpoint.getTable()).isEqualTo("events");
+ assertThat(endpoint.getServerUrl()).isEqualTo("http://localhost:8123");
+ }
+
+ @Test
+ void createEndpointParsesDatabaseOnlyPath() {
+ ClickHouseEndpoint endpoint = context.getEndpoint(
+ "clickhouse://analytics?operation=query&" + URL, ClickHouseEndpoint.class);
+
+ assertThat(endpoint.getDatabase()).isEqualTo("analytics");
+ assertThat(endpoint.getTable()).isNull();
+ assertThat(endpoint.getOperation()).isEqualTo(ClickHouseOperation.QUERY);
+ }
+
+ @Test
+ void createEndpointAppliesDefaults() {
+ ClickHouseEndpoint endpoint = context.getEndpoint("clickhouse://db?" + URL, ClickHouseEndpoint.class);
+
+ assertThat(endpoint.getOperation()).isEqualTo(ClickHouseOperation.INSERT);
+ assertThat(endpoint.getFormat()).isEqualTo("JSONEachRow");
+ assertThat(endpoint.getUsername()).isEqualTo("default");
+ assertThat(endpoint.isAsyncInsert()).isFalse();
+ assertThat(endpoint.isWaitForAsyncInsert()).isTrue();
+ assertThat(endpoint.isCompression()).isFalse();
+ }
+
+ @Test
+ void createEndpointBindsAllOptions() {
+ ClickHouseEndpoint endpoint = context.getEndpoint(
+ "clickhouse://metrics.samples?operation=insert&format=RowBinary&asyncInsert=true"
+ + "&waitForAsyncInsert=false&compression=true&batchSize=5000"
+ + "&username=admin&password=secret&ssl=true&" + URL,
+ ClickHouseEndpoint.class);
+
+ assertThat(endpoint.getDatabase()).isEqualTo("metrics");
+ assertThat(endpoint.getTable()).isEqualTo("samples");
+ assertThat(endpoint.getFormat()).isEqualTo("RowBinary");
+ assertThat(endpoint.isAsyncInsert()).isTrue();
+ assertThat(endpoint.isWaitForAsyncInsert()).isFalse();
+ assertThat(endpoint.isCompression()).isTrue();
+ assertThat(endpoint.getBatchSize()).isEqualTo(5000);
+ assertThat(endpoint.getUsername()).isEqualTo("admin");
+ assertThat(endpoint.getPassword()).isEqualTo("secret");
+ assertThat(endpoint.isSsl()).isTrue();
+ }
+
+ @Test
+ void createConsumerIsNotSupported() {
+ ClickHouseEndpoint endpoint = context.getEndpoint("clickhouse://db?" + URL, ClickHouseEndpoint.class);
+
+ assertThatThrownBy(() -> endpoint.createConsumer(exchange -> {
+ })).isInstanceOf(UnsupportedOperationException.class);
+ }
+
+ @Test
+ void startWithoutClientOrServerUrlFails() {
+ assertThatThrownBy(() -> context.getEndpoint("clickhouse://db?operation=ping", ClickHouseEndpoint.class))
+ .hasMessageContaining("serverUrl");
+ }
+
+ @Test
+ void componentLevelConnectionOptionsAreInherited() {
+ ClickHouseComponent component = context.getComponent("clickhouse", ClickHouseComponent.class);
+ component.setServerUrl("http://clickhouse:8123");
+ component.setUsername("admin");
+ component.setPassword("secret");
+ component.setSsl(true);
+ component.setCompression(true);
+
+ ClickHouseEndpoint endpoint = context.getEndpoint("clickhouse://db", ClickHouseEndpoint.class);
+
+ assertThat(endpoint.getServerUrl()).isEqualTo("http://clickhouse:8123");
+ assertThat(endpoint.getUsername()).isEqualTo("admin");
+ assertThat(endpoint.getPassword()).isEqualTo("secret");
+ assertThat(endpoint.isSsl()).isTrue();
+ assertThat(endpoint.isCompression()).isTrue();
+ }
+
+ @Test
+ void endpointOptionsOverrideComponentDefaults() {
+ ClickHouseComponent component = context.getComponent("clickhouse", ClickHouseComponent.class);
+ component.setServerUrl("http://clickhouse:8123");
+ component.setUsername("admin");
+
+ ClickHouseEndpoint endpoint = context.getEndpoint(
+ "clickhouse://db?username=override&serverUrl=http://other:8123", ClickHouseEndpoint.class);
+
+ assertThat(endpoint.getServerUrl()).isEqualTo("http://other:8123");
+ assertThat(endpoint.getUsername()).isEqualTo("override");
+ }
+
+ @Test
+ void emptyPathIsRejected() {
+ assertThatThrownBy(() -> context.getEndpoint("clickhouse:?" + URL, ClickHouseEndpoint.class))
+ .isInstanceOf(ResolveEndpointFailedException.class)
+ .hasMessageContaining("database");
+ }
+}
diff --git a/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/ClickHouseProducerTest.java b/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/ClickHouseProducerTest.java
new file mode 100644
index 000000000000..2b9e08b1e57c
--- /dev/null
+++ b/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/ClickHouseProducerTest.java
@@ -0,0 +1,252 @@
+/*
+ * 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.clickhouse;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import com.clickhouse.client.api.Client;
+import com.clickhouse.client.api.insert.InsertResponse;
+import com.clickhouse.client.api.insert.InsertSettings;
+import com.clickhouse.client.api.query.QueryResponse;
+import com.clickhouse.client.api.query.QuerySettings;
+import com.clickhouse.data.ClickHouseFormat;
+import org.apache.camel.CamelContext;
+import org.apache.camel.WrappedFile;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class ClickHouseProducerTest extends CamelTestSupport {
+
+ private final Client client = mock(Client.class);
+ private final InsertResponse insertResponse = mock(InsertResponse.class);
+ private final QueryResponse queryResponse = mock(QueryResponse.class);
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ ClickHouseComponent component = new ClickHouseComponent();
+ component.setClient(client);
+ context.addComponent("clickhouse", component);
+ return context;
+ }
+
+ @BeforeEach
+ void setupMocks() {
+ when(insertResponse.getWrittenRows()).thenReturn(3L);
+ when(client.insert(anyString(), any(InputStream.class), any(ClickHouseFormat.class), any(InsertSettings.class)))
+ .thenReturn(CompletableFuture.completedFuture(insertResponse));
+ when(client.insert(anyString(), anyList(), any(InsertSettings.class)))
+ .thenReturn(CompletableFuture.completedFuture(insertResponse));
+
+ when(queryResponse.getReadRows()).thenReturn(5L);
+ when(queryResponse.getInputStream())
+ .thenReturn(new ByteArrayInputStream("id,name\n1,alice\n".getBytes(StandardCharsets.UTF_8)));
+ when(client.query(anyString(), any(QuerySettings.class)))
+ .thenReturn(CompletableFuture.completedFuture(queryResponse));
+
+ when(client.ping()).thenReturn(true);
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:insert")
+ .to("clickhouse://analytics.events?operation=insert&format=JSONEachRow")
+ .to("mock:result");
+ from("direct:insertRowBinary")
+ .to("clickhouse://analytics.events?operation=insert&format=RowBinary")
+ .to("mock:result");
+ from("direct:insertBatched")
+ .to("clickhouse://analytics.events?operation=insert&format=JSONEachRow&batchSize=2")
+ .to("mock:result");
+ from("direct:query")
+ .to("clickhouse://analytics?operation=query&format=CSV")
+ .to("mock:result");
+ from("direct:ping")
+ .to("clickhouse://analytics?operation=ping")
+ .to("mock:result");
+ from("direct:default")
+ .to("clickhouse://analytics.events")
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ void insertStreamsStringBodyWithConfiguredFormat() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(1);
+
+ template.sendBody("direct:insert", "{\"id\":1,\"name\":\"alice\"}");
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ ArgumentCaptor<String> tableCaptor = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<ClickHouseFormat> formatCaptor = ArgumentCaptor.forClass(ClickHouseFormat.class);
+ verify(client).insert(tableCaptor.capture(), any(InputStream.class), formatCaptor.capture(),
+ any(InsertSettings.class));
+
+ assertThat(tableCaptor.getValue()).isEqualTo("events");
+ assertThat(formatCaptor.getValue()).isEqualTo(ClickHouseFormat.JSONEachRow);
+ assertThat(mock.getExchanges().get(0).getMessage().getHeader(ClickHouseConstants.WRITTEN_ROWS))
+ .isEqualTo(3L);
+ }
+
+ @Test
+ void insertStreamsByteArrayBody() throws Exception {
+ template.sendBody("direct:insertRowBinary", "row-binary-bytes".getBytes(StandardCharsets.UTF_8));
+
+ ArgumentCaptor<ClickHouseFormat> formatCaptor = ArgumentCaptor.forClass(ClickHouseFormat.class);
+ verify(client).insert(anyString(), any(InputStream.class), formatCaptor.capture(), any(InsertSettings.class));
+ assertThat(formatCaptor.getValue()).isEqualTo(ClickHouseFormat.RowBinary);
+ }
+
+ @Test
+ void insertUsesNativeListApiForListBodies() throws Exception {
+ List<Map<String, Object>> rows = List.of(Map.of("id", 1, "name", "alice"), Map.of("id", 2, "name", "bob"));
+
+ template.sendBody("direct:insert", rows);
+
+ verify(client).insert(anyString(), anyList(), any(InsertSettings.class));
+ }
+
+ @Test
+ void insertSplitsListIntoBatchesWhenBatchSizeSet() throws Exception {
+ // batchSize=2 with 5 rows -> 3 insert calls (2 + 2 + 1)
+ List<Map<String, Object>> rows = List.of(
+ Map.of("id", 1), Map.of("id", 2), Map.of("id", 3), Map.of("id", 4), Map.of("id", 5));
+
+ template.sendBody("direct:insertBatched", rows);
+
+ ArgumentCaptor<List> batchCaptor = ArgumentCaptor.forClass(List.class);
+ verify(client, times(3)).insert(anyString(), batchCaptor.capture(), any(InsertSettings.class));
+
+ List<List> batches = batchCaptor.getAllValues();
+ assertThat(batches).hasSize(3);
+ assertThat(batches.get(0)).hasSize(2);
+ assertThat(batches.get(1)).hasSize(2);
+ assertThat(batches.get(2)).hasSize(1);
+ }
+
+ @Test
+ void insertStreamsWrappedFileBody() throws Exception {
+ File file = File.createTempFile("clickhouse-", ".json");
+ file.deleteOnExit();
+ java.nio.file.Files.writeString(file.toPath(), "{\"id\":1,\"name\":\"alice\"}");
+
+ WrappedFile<File> wrappedFile = new WrappedFile<>() {
+ @Override
+ public File getFile() {
+ return file;
+ }
+
+ @Override
+ public Object getBody() {
+ return file;
+ }
+
+ @Override
+ public long getFileLength() {
+ return file.length();
+ }
+ };
+
+ template.sendBody("direct:insert", wrappedFile);
+
+ verify(client).insert(anyString(), any(InputStream.class), any(ClickHouseFormat.class), any(InsertSettings.class));
+ }
+
+ @Test
+ void queryReturnsResultBodyAndReadRowsHeader() throws Exception {
+ Object result = template.requestBody("direct:query", "SELECT * FROM analytics.events");
+
+ assertThat(result).isInstanceOf(String.class);
+ assertThat((String) result).contains("alice");
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ assertThat(mock.getExchanges().get(0).getMessage().getHeader(ClickHouseConstants.READ_ROWS)).isEqualTo(5L);
+
+ ArgumentCaptor<String> sqlCaptor = ArgumentCaptor.forClass(String.class);
+ verify(client).query(sqlCaptor.capture(), any(QuerySettings.class));
+ assertThat(sqlCaptor.getValue()).isEqualTo("SELECT * FROM analytics.events");
+ }
+
+ @Test
+ void pingReturnsBooleanBodyAndHeader() throws Exception {
+ Object result = template.requestBody("direct:ping", (Object) null);
+
+ assertThat(result).isEqualTo(true);
+ verify(client).ping();
+
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ assertThat(mock.getExchanges().get(0).getMessage().getHeader(ClickHouseConstants.PING_OK)).isEqualTo(true);
+ }
+
+ @Test
+ void operationHeaderOverridesEndpointOperation() throws Exception {
+ // endpoint is configured for insert, but the header forces a ping
+ Object result = template.requestBodyAndHeader("direct:default", null,
+ ClickHouseConstants.OPERATION, "ping");
+
+ assertThat(result).isEqualTo(true);
+ verify(client).ping();
+ }
+
+ @Test
+ void tableAndFormatHeadersOverrideEndpoint() throws Exception {
+ template.sendBodyAndHeaders("direct:insert", "{\"id\":1}", Map.of(
+ ClickHouseConstants.TABLE, "overridden",
+ ClickHouseConstants.FORMAT, "TSV"));
+
+ ArgumentCaptor<String> tableCaptor = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<ClickHouseFormat> formatCaptor = ArgumentCaptor.forClass(ClickHouseFormat.class);
+ verify(client).insert(tableCaptor.capture(), any(InputStream.class), formatCaptor.capture(),
+ any(InsertSettings.class));
+
+ assertThat(tableCaptor.getValue()).isEqualTo("overridden");
+ assertThat(formatCaptor.getValue()).isEqualTo(ClickHouseFormat.TSV);
+ }
+
+ @Test
+ void queryWithoutSqlBodyFails() {
+ assertThat(template.request("direct:query", exchange -> exchange.getIn().setBody(null))
+ .getException())
+ .isInstanceOf(ClickHouseException.class)
+ .hasMessageContaining("SQL query");
+ }
+}
diff --git a/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/integration/ClickHouseProducerIT.java b/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/integration/ClickHouseProducerIT.java
new file mode 100644
index 000000000000..7b6038466b8a
--- /dev/null
+++ b/components/camel-clickhouse/src/test/java/org/apache/camel/component/clickhouse/integration/ClickHouseProducerIT.java
@@ -0,0 +1,116 @@
+/*
+ * 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.clickhouse.integration;
+
+import com.clickhouse.client.api.Client;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.clickhouse.ClickHouseComponent;
+import org.apache.camel.component.clickhouse.ClickHouseConstants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.infra.clickhouse.services.ClickHouseService;
+import org.apache.camel.test.infra.clickhouse.services.ClickHouseServiceFactory;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ClickHouseProducerIT extends CamelTestSupport {
+
+ @RegisterExtension
+ static ClickHouseService service = ClickHouseServiceFactory.createService();
+
+ private static Client client;
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+
+ client = new Client.Builder()
+ .addEndpoint(service.getHttpUrl())
+ .setUsername(service.getUsername())
+ .setPassword(service.getPassword())
+ .setDefaultDatabase(service.getDatabaseName())
+ .build();
+
+ ClickHouseComponent component = new ClickHouseComponent();
+ component.setClient(client);
+ context.addComponent("clickhouse", component);
+ return context;
+ }
+
+ @AfterAll
+ static void closeClient() {
+ if (client != null) {
+ client.close();
+ }
+ }
+
+ @BeforeEach
+ void createTable() throws Exception {
+ client.query("CREATE TABLE IF NOT EXISTS " + service.getDatabaseName()
+ + ".camel_events (id UInt32, name String) ENGINE = Memory")
+ .get();
+ client.query("TRUNCATE TABLE " + service.getDatabaseName() + ".camel_events").get();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:insert")
+ .to("clickhouse://" + service.getDatabaseName()
+ + ".camel_events?operation=insert&format=JSONEachRow")
+ .to("mock:result");
+ from("direct:query")
+ .to("clickhouse://" + service.getDatabaseName() + "?operation=query&format=CSV")
+ .to("mock:result");
+ from("direct:ping")
+ .to("clickhouse://" + service.getDatabaseName() + "?operation=ping")
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ void insertAndQueryRoundTrip() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(1);
+
+ String body = "{\"id\":1,\"name\":\"alice\"}\n{\"id\":2,\"name\":\"bob\"}\n";
+ template.sendBody("direct:insert", body);
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Object written = mock.getExchanges().get(0).getMessage().getHeader(ClickHouseConstants.WRITTEN_ROWS);
+ assertThat(written).isEqualTo(2L);
+
+ String result = template.requestBody("direct:query",
+ "SELECT count() FROM " + service.getDatabaseName() + ".camel_events", String.class);
+ assertThat(result.trim()).isEqualTo("2");
+ }
+
+ @Test
+ void pingReturnsTrue() {
+ Boolean result = template.requestBody("direct:ping", null, Boolean.class);
+ assertThat(result).isTrue();
+ }
+}
diff --git a/components/camel-clickhouse/src/test/resources/log4j2.properties b/components/camel-clickhouse/src/test/resources/log4j2.properties
new file mode 100644
index 000000000000..e8d543e1f7c1
--- /dev/null
+++ b/components/camel-clickhouse/src/test/resources/log4j2.properties
@@ -0,0 +1,29 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-clickhouse-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/pom.xml b/components/pom.xml
index 6e31921eb995..00cdcb7520fd 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -104,6 +104,7 @@
<module>camel-cassandraql</module>
<module>camel-cbor</module>
<module>camel-chunk</module>
+ <module>camel-clickhouse</module>
<module>camel-clickup</module>
<module>camel-cloudevents</module>
<module>camel-cm-sms</module>
diff --git a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
index 91be0f1a521e..95f6e7e9cacc 100644
--- a/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
+++ b/core/camel-main/src/generated/resources/org/apache/camel/main/components.properties
@@ -67,6 +67,7 @@ camunda
chatscript
chunk
class
+clickhouse
clickup
cm-sms
coap
diff --git a/docs/components/modules/ROOT/examples/json/clickhouse.json b/docs/components/modules/ROOT/examples/json/clickhouse.json
new file mode 120000
index 000000000000..8d65dae90005
--- /dev/null
+++ b/docs/components/modules/ROOT/examples/json/clickhouse.json
@@ -0,0 +1 @@
+../../../../../../components/camel-clickhouse/src/generated/resources/META-INF/org/apache/camel/component/clickhouse/clickhouse.json
\ No newline at end of file
diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc
index 8eb41333f82d..916b92cbf1c7 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -100,6 +100,7 @@
** xref:cql-component.adoc[Cassandra CQL]
** xref:chunk-component.adoc[Chunk]
** xref:class-component.adoc[Class]
+** xref:clickhouse-component.adoc[ClickHouse]
** xref:clickup-component.adoc[ClickUp]
** xref:cm-sms-component.adoc[CM SMS Gateway]
** xref:coap-component.adoc[CoAP]
diff --git a/docs/components/modules/ROOT/pages/clickhouse-component.adoc b/docs/components/modules/ROOT/pages/clickhouse-component.adoc
new file mode 120000
index 000000000000..319c6731c165
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/clickhouse-component.adoc
@@ -0,0 +1 @@
+../../../../../components/camel-clickhouse/src/main/docs/clickhouse-component.adoc
\ No newline at end of file
diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
index db480bb442a8..e7e07f50b38e 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
@@ -1047,6 +1047,25 @@ The `io.vavr:vavr` and `io.vavr:vavr-match` runtime dependencies have been remov
`camel-resilience4j`. The single internal usage of Vavr's `Try` monad has been replaced with a
plain try-catch. This eliminates two transitive runtime JARs. No user-facing behavior change.
+=== camel-clickhouse (new component)
+
+A new `camel-clickhouse` producer component has been added. It integrates with
+https://clickhouse.com/[ClickHouse], the high-performance columnar OLAP database, using the official
+ClickHouse Java client (client-v2). It exposes ClickHouse's native capabilities as first-class endpoint
+options: native format streaming inserts (`RowBinary`, `JSONEachRow`, `CSV`, `TSV`, `Parquet`),
+server-side asynchronous inserts, OLAP queries and health checks.
+
+[source,java]
+----
+from("direct:events")
+ .to("clickhouse://analytics.events?operation=insert&format=JSONEachRow");
+----
+
+The component supports the `insert` (default), `query` and `ping` operations, and can either use a shared
+autowired `com.clickhouse.client.api.Client` bean or build its own client from the `serverUrl`, `username`,
+`password` and `ssl` endpoint options. See the xref:next@components::clickhouse-component.adoc[ClickHouse component]
+documentation for details.
+
=== camel-minio - Upgraded to minio 9.0.3 - Breaking Changes
The underlying `io.minio:minio` library has been upgraded from 8.x to 9.0.3.
@@ -1149,3 +1168,4 @@ Update any catch blocks or method `throws` declarations accordingly.
// After:
} catch (MinioException e) { ... }
----
+
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
index a1d0779fed81..00bb253b89b2 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
@@ -954,6 +954,20 @@ public interface ComponentsBuilderFactory {
static ClasComponentBuilderFactory.ClasComponentBuilder clas() {
return ClasComponentBuilderFactory.clas();
}
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP database,
+ * for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * @return the dsl builder
+ */
+ static ClickhouseComponentBuilderFactory.ClickhouseComponentBuilder clickhouse() {
+ return ClickhouseComponentBuilderFactory.clickhouse();
+ }
/**
* ClickUp (camel-clickup)
* Receives events from ClickUp
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ClickhouseComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ClickhouseComponentBuilderFactory.java
new file mode 100644
index 000000000000..3c912c00a55c
--- /dev/null
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/ClickhouseComponentBuilderFactory.java
@@ -0,0 +1,230 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * 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.builder.component.dsl;
+
+import javax.annotation.processing.Generated;
+import org.apache.camel.Component;
+import org.apache.camel.builder.component.AbstractComponentBuilder;
+import org.apache.camel.builder.component.ComponentBuilder;
+import org.apache.camel.component.clickhouse.ClickHouseComponent;
+
+/**
+ * Interact with ClickHouse, the high-performance columnar OLAP database, for
+ * high-throughput ingestion and OLAP queries.
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.ComponentDslMojo")
+public interface ClickhouseComponentBuilderFactory {
+
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP database,
+ * for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * @return the dsl builder
+ */
+ static ClickhouseComponentBuilder clickhouse() {
+ return new ClickhouseComponentBuilderImpl();
+ }
+
+ /**
+ * Builder for the ClickHouse component.
+ */
+ interface ClickhouseComponentBuilder extends ComponentBuilder<ClickHouseComponent> {
+
+ /**
+ * The shared ClickHouse client to use for all endpoints, of type
+ * com.clickhouse.client.api.Client. When set, the endpoint-level
+ * connection options (serverUrl, username, password, ssl) are ignored.
+ *
+ * The option is a:
+ * <code>com.clickhouse.client.api.Client</code> type.
+ *
+ * Group: producer
+ *
+ * @param client the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder client(com.clickhouse.client.api.Client client) {
+ doSetProperty("client", client);
+ return this;
+ }
+
+
+ /**
+ * Whether to compress the insert request payload sent to the server
+ * (LZ4).
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param compression the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder compression(boolean compression) {
+ doSetProperty("compression", compression);
+ return this;
+ }
+
+
+ /**
+ * Whether the producer should be started lazy (on the first message).
+ * By starting lazy you can use this to allow CamelContext and routes to
+ * startup in situations where a producer may otherwise fail during
+ * starting and cause the route to fail being started. By deferring this
+ * startup to be lazy then the startup failure can be handled during
+ * routing messages via Camel's routing error handlers. Beware that when
+ * the first message is processed then creating and starting the
+ * producer may take a little time and prolong the total processing time
+ * of the processing.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param lazyStartProducer the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder lazyStartProducer(boolean lazyStartProducer) {
+ doSetProperty("lazyStartProducer", lazyStartProducer);
+ return this;
+ }
+
+ /**
+ * The ClickHouse HTTP endpoint URL, e.g. http://localhost:8123. Can be
+ * overridden per endpoint. Required unless a shared Client bean is
+ * autowired or configured on the component.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param serverUrl the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder serverUrl(java.lang.String serverUrl) {
+ doSetProperty("serverUrl", serverUrl);
+ return this;
+ }
+
+
+ /**
+ * Whether autowiring is enabled. This is used for automatic autowiring
+ * options (the option must be marked as autowired) by looking up in the
+ * registry to find if there is a single instance of matching type,
+ * which then gets configured on the component. This can be used for
+ * automatic configuring JDBC data sources, JMS connection factories,
+ * AWS Clients, etc.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: advanced
+ *
+ * @param autowiredEnabled the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder autowiredEnabled(boolean autowiredEnabled) {
+ doSetProperty("autowiredEnabled", autowiredEnabled);
+ return this;
+ }
+
+ /**
+ * The password used to authenticate to ClickHouse.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: security
+ *
+ * @param password the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder password(java.lang.String password) {
+ doSetProperty("password", password);
+ return this;
+ }
+
+
+ /**
+ * Whether to connect to ClickHouse over a secure (HTTPS) connection.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: security
+ *
+ * @param ssl the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder ssl(boolean ssl) {
+ doSetProperty("ssl", ssl);
+ return this;
+ }
+
+
+ /**
+ * The username used to authenticate to ClickHouse.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: default
+ * Group: security
+ *
+ * @param username the value to set
+ * @return the dsl builder
+ */
+ default ClickhouseComponentBuilder username(java.lang.String username) {
+ doSetProperty("username", username);
+ return this;
+ }
+ }
+
+ class ClickhouseComponentBuilderImpl
+ extends AbstractComponentBuilder<ClickHouseComponent>
+ implements ClickhouseComponentBuilder {
+ @Override
+ protected ClickHouseComponent buildConcreteComponent() {
+ return new ClickHouseComponent();
+ }
+ @Override
+ protected boolean setPropertyOnComponent(
+ Component component,
+ String name,
+ Object value) {
+ switch (name) {
+ case "client": ((ClickHouseComponent) component).setClient((com.clickhouse.client.api.Client) value); return true;
+ case "compression": ((ClickHouseComponent) component).setCompression((boolean) value); return true;
+ case "lazyStartProducer": ((ClickHouseComponent) component).setLazyStartProducer((boolean) value); return true;
+ case "serverUrl": ((ClickHouseComponent) component).setServerUrl((java.lang.String) value); return true;
+ case "autowiredEnabled": ((ClickHouseComponent) component).setAutowiredEnabled((boolean) value); return true;
+ case "password": ((ClickHouseComponent) component).setPassword((java.lang.String) value); return true;
+ case "ssl": ((ClickHouseComponent) component).setSsl((boolean) value); return true;
+ case "username": ((ClickHouseComponent) component).setUsername((java.lang.String) value); return true;
+ default: return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
index 05ae1039f3b0..21fab8e26536 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilderFactory.java
@@ -64,6 +64,7 @@ public interface EndpointBuilderFactory
org.apache.camel.builder.endpoint.dsl.ChunkEndpointBuilderFactory.ChunkBuilders,
org.apache.camel.builder.endpoint.dsl.CinderEndpointBuilderFactory.CinderBuilders,
org.apache.camel.builder.endpoint.dsl.ClassEndpointBuilderFactory.ClassBuilders,
+ org.apache.camel.builder.endpoint.dsl.ClickHouseEndpointBuilderFactory.ClickHouseBuilders,
org.apache.camel.builder.endpoint.dsl.ClickUpEndpointBuilderFactory.ClickUpBuilders,
org.apache.camel.builder.endpoint.dsl.ClientEndpointBuilderFactory.ClientBuilders,
org.apache.camel.builder.endpoint.dsl.CloudtrailEndpointBuilderFactory.CloudtrailBuilders,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
index ac8eb7ace0de..f8350dafc64a 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointBuilders.java
@@ -61,6 +61,7 @@ public interface EndpointBuilders
org.apache.camel.builder.endpoint.dsl.ChunkEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.CinderEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.ClassEndpointBuilderFactory,
+ org.apache.camel.builder.endpoint.dsl.ClickHouseEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.ClickUpEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.ClientEndpointBuilderFactory,
org.apache.camel.builder.endpoint.dsl.CloudtrailEndpointBuilderFactory,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
index c6cae70e0880..0502a62071de 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/EndpointHeaderBuilders.java
@@ -788,6 +788,20 @@ public class EndpointHeaderBuilders {
public static ChunkEndpointBuilderFactory.ChunkHeaderNameBuilder chunk() {
return ChunkEndpointBuilderFactory.ChunkHeaderNameBuilder.INSTANCE;
}
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP database,
+ * for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * @return the dsl builder for the headers' name.
+ */
+ public static ClickHouseEndpointBuilderFactory.ClickHouseHeaderNameBuilder clickhouse() {
+ return ClickHouseEndpointBuilderFactory.ClickHouseHeaderNameBuilder.INSTANCE;
+ }
/**
* CoAP (camel-coap)
* Send and receive messages to/from CoAP (Constrained Application Protocol)
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index fd3ce42e2ea5..b9339e96ba8f 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -3028,6 +3028,50 @@ public class StaticEndpointBuilders {
public static ClassEndpointBuilderFactory.ClassEndpointBuilder clas(String componentName, String path) {
return ClassEndpointBuilderFactory.endpointBuilder(componentName, path);
}
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP database,
+ * for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * Syntax: <code>clickhouse:database</code>
+ *
+ * Path parameter: database (required)
+ * The ClickHouse database. A table may also be provided using the
+ * database.table syntax.
+ *
+ * @param path database
+ * @return the dsl builder
+ */
+ public static ClickHouseEndpointBuilderFactory.ClickHouseEndpointBuilder clickhouse(String path) {
+ return clickhouse("clickhouse", path);
+ }
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP database,
+ * for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * Syntax: <code>clickhouse:database</code>
+ *
+ * Path parameter: database (required)
+ * The ClickHouse database. A table may also be provided using the
+ * database.table syntax.
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path database
+ * @return the dsl builder
+ */
+ public static ClickHouseEndpointBuilderFactory.ClickHouseEndpointBuilder clickhouse(String componentName, String path) {
+ return ClickHouseEndpointBuilderFactory.endpointBuilder(componentName, path);
+ }
/**
* ClickUp (camel-clickup)
* Receives events from ClickUp
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ClickHouseEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ClickHouseEndpointBuilderFactory.java
new file mode 100644
index 000000000000..43d70e9e4b28
--- /dev/null
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/ClickHouseEndpointBuilderFactory.java
@@ -0,0 +1,546 @@
+/* Generated by camel build tools - do NOT edit this file! */
+/*
+ * 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.builder.endpoint.dsl;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.function.*;
+import java.util.stream.*;
+import javax.annotation.processing.Generated;
+import org.apache.camel.builder.EndpointConsumerBuilder;
+import org.apache.camel.builder.EndpointProducerBuilder;
+import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
+
+/**
+ * Interact with ClickHouse, the high-performance columnar OLAP database, for
+ * high-throughput ingestion and OLAP queries.
+ *
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
+public interface ClickHouseEndpointBuilderFactory {
+
+ /**
+ * Builder for endpoint for the ClickHouse component.
+ */
+ public interface ClickHouseEndpointBuilder
+ extends
+ EndpointProducerBuilder {
+ default AdvancedClickHouseEndpointBuilder advanced() {
+ return (AdvancedClickHouseEndpointBuilder) this;
+ }
+
+ /**
+ * Whether to use ClickHouse server-side asynchronous inserts
+ * (async_insert=1).
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param asyncInsert the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder asyncInsert(boolean asyncInsert) {
+ doSetProperty("asyncInsert", asyncInsert);
+ return this;
+ }
+ /**
+ * Whether to use ClickHouse server-side asynchronous inserts
+ * (async_insert=1).
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param asyncInsert the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder asyncInsert(String asyncInsert) {
+ doSetProperty("asyncInsert", asyncInsert);
+ return this;
+ }
+ /**
+ * The client-side batch size for insert operations when the message
+ * body is a List. When greater than 0, the list is split into batches
+ * of this size and each batch is sent as a separate insert. A value of
+ * 0 (default) inserts the whole list in a single call.
+ *
+ * The option is a: <code>int</code> type.
+ *
+ * Default: 0
+ * Group: producer
+ *
+ * @param batchSize the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder batchSize(int batchSize) {
+ doSetProperty("batchSize", batchSize);
+ return this;
+ }
+ /**
+ * The client-side batch size for insert operations when the message
+ * body is a List. When greater than 0, the list is split into batches
+ * of this size and each batch is sent as a separate insert. A value of
+ * 0 (default) inserts the whole list in a single call.
+ *
+ * The option will be converted to a <code>int</code> type.
+ *
+ * Default: 0
+ * Group: producer
+ *
+ * @param batchSize the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder batchSize(String batchSize) {
+ doSetProperty("batchSize", batchSize);
+ return this;
+ }
+ /**
+ * Whether to compress the insert request payload sent to the server
+ * (LZ4).
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param compression the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder compression(boolean compression) {
+ doSetProperty("compression", compression);
+ return this;
+ }
+ /**
+ * Whether to compress the insert request payload sent to the server
+ * (LZ4).
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param compression the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder compression(String compression) {
+ doSetProperty("compression", compression);
+ return this;
+ }
+ /**
+ * The ClickHouse data format used for insert and query operations, e.g.
+ * JSONEachRow, RowBinary, CSV, TSV or Parquet.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: JSONEachRow
+ * Group: producer
+ *
+ * @param format the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder format(String format) {
+ doSetProperty("format", format);
+ return this;
+ }
+ /**
+ * The operation to perform: insert, query or ping.
+ *
+ * The option is a:
+ * <code>org.apache.camel.component.clickhouse.ClickHouseOperation</code> type.
+ *
+ * Default: INSERT
+ * Group: producer
+ *
+ * @param operation the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder operation(org.apache.camel.component.clickhouse.ClickHouseOperation operation) {
+ doSetProperty("operation", operation);
+ return this;
+ }
+ /**
+ * The operation to perform: insert, query or ping.
+ *
+ * The option will be converted to a
+ * <code>org.apache.camel.component.clickhouse.ClickHouseOperation</code> type.
+ *
+ * Default: INSERT
+ * Group: producer
+ *
+ * @param operation the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder operation(String operation) {
+ doSetProperty("operation", operation);
+ return this;
+ }
+ /**
+ * The ClickHouse HTTP endpoint URL, e.g. http://localhost:8123.
+ * Required unless a shared Client bean is autowired or configured on
+ * the component.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param serverUrl the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder serverUrl(String serverUrl) {
+ doSetProperty("serverUrl", serverUrl);
+ return this;
+ }
+ /**
+ * The target table for insert operations. Can also be given in the path
+ * as database.table or overridden per message with the
+ * CamelClickHouseTable header.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param table the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder table(String table) {
+ doSetProperty("table", table);
+ return this;
+ }
+ /**
+ * When asyncInsert is enabled, whether the server should wait for the
+ * async insert to be flushed before acknowledging
+ * (wait_for_async_insert).
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: producer
+ *
+ * @param waitForAsyncInsert the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder waitForAsyncInsert(boolean waitForAsyncInsert) {
+ doSetProperty("waitForAsyncInsert", waitForAsyncInsert);
+ return this;
+ }
+ /**
+ * When asyncInsert is enabled, whether the server should wait for the
+ * async insert to be flushed before acknowledging
+ * (wait_for_async_insert).
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: true
+ * Group: producer
+ *
+ * @param waitForAsyncInsert the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder waitForAsyncInsert(String waitForAsyncInsert) {
+ doSetProperty("waitForAsyncInsert", waitForAsyncInsert);
+ return this;
+ }
+ /**
+ * The password used to authenticate to ClickHouse.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: security
+ *
+ * @param password the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder password(String password) {
+ doSetProperty("password", password);
+ return this;
+ }
+ /**
+ * Whether to connect to ClickHouse over a secure (HTTPS) connection.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: security
+ *
+ * @param ssl the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder ssl(boolean ssl) {
+ doSetProperty("ssl", ssl);
+ return this;
+ }
+ /**
+ * Whether to connect to ClickHouse over a secure (HTTPS) connection.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: security
+ *
+ * @param ssl the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder ssl(String ssl) {
+ doSetProperty("ssl", ssl);
+ return this;
+ }
+ /**
+ * The username used to authenticate to ClickHouse.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: default
+ * Group: security
+ *
+ * @param username the value to set
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder username(String username) {
+ doSetProperty("username", username);
+ return this;
+ }
+ }
+
+ /**
+ * Advanced builder for endpoint for the ClickHouse component.
+ */
+ public interface AdvancedClickHouseEndpointBuilder
+ extends
+ EndpointProducerBuilder {
+ default ClickHouseEndpointBuilder basic() {
+ return (ClickHouseEndpointBuilder) this;
+ }
+
+ /**
+ * Whether the producer should be started lazy (on the first message).
+ * By starting lazy you can use this to allow CamelContext and routes to
+ * startup in situations where a producer may otherwise fail during
+ * starting and cause the route to fail being started. By deferring this
+ * startup to be lazy then the startup failure can be handled during
+ * routing messages via Camel's routing error handlers. Beware that when
+ * the first message is processed then creating and starting the
+ * producer may take a little time and prolong the total processing time
+ * of the processing.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer (advanced)
+ *
+ * @param lazyStartProducer the value to set
+ * @return the dsl builder
+ */
+ default AdvancedClickHouseEndpointBuilder lazyStartProducer(boolean lazyStartProducer) {
+ doSetProperty("lazyStartProducer", lazyStartProducer);
+ return this;
+ }
+ /**
+ * Whether the producer should be started lazy (on the first message).
+ * By starting lazy you can use this to allow CamelContext and routes to
+ * startup in situations where a producer may otherwise fail during
+ * starting and cause the route to fail being started. By deferring this
+ * startup to be lazy then the startup failure can be handled during
+ * routing messages via Camel's routing error handlers. Beware that when
+ * the first message is processed then creating and starting the
+ * producer may take a little time and prolong the total processing time
+ * of the processing.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer (advanced)
+ *
+ * @param lazyStartProducer the value to set
+ * @return the dsl builder
+ */
+ default AdvancedClickHouseEndpointBuilder lazyStartProducer(String lazyStartProducer) {
+ doSetProperty("lazyStartProducer", lazyStartProducer);
+ return this;
+ }
+ }
+
+ public interface ClickHouseBuilders {
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP
+ * database, for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * @return the dsl builder for the headers' name.
+ */
+ default ClickHouseHeaderNameBuilder clickhouse() {
+ return ClickHouseHeaderNameBuilder.INSTANCE;
+ }
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP
+ * database, for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * Syntax: <code>clickhouse:database</code>
+ *
+ * Path parameter: database (required)
+ * The ClickHouse database. A table may also be provided using the
+ * database.table syntax.
+ *
+ * @param path database
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder clickhouse(String path) {
+ return ClickHouseEndpointBuilderFactory.endpointBuilder("clickhouse", path);
+ }
+ /**
+ * ClickHouse (camel-clickhouse)
+ * Interact with ClickHouse, the high-performance columnar OLAP
+ * database, for high-throughput ingestion and OLAP queries.
+ *
+ * Category: database,bigdata
+ * Since: 4.22
+ * Maven coordinates: org.apache.camel:camel-clickhouse
+ *
+ * Syntax: <code>clickhouse:database</code>
+ *
+ * Path parameter: database (required)
+ * The ClickHouse database. A table may also be provided using the
+ * database.table syntax.
+ *
+ * @param componentName to use a custom component name for the endpoint
+ * instead of the default name
+ * @param path database
+ * @return the dsl builder
+ */
+ default ClickHouseEndpointBuilder clickhouse(String componentName, String path) {
+ return ClickHouseEndpointBuilderFactory.endpointBuilder(componentName, path);
+ }
+
+ }
+ /**
+ * The builder of headers' name for the ClickHouse component.
+ */
+ public static class ClickHouseHeaderNameBuilder {
+ /**
+ * The internal instance of the builder used to access to all the
+ * methods representing the name of headers.
+ */
+ public static final ClickHouseHeaderNameBuilder INSTANCE = new ClickHouseHeaderNameBuilder();
+
+ /**
+ * Overrides the operation configured on the endpoint (insert, query or
+ * ping).
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHouseOperation}.
+ */
+ public String clickHouseOperation() {
+ return "CamelClickHouseOperation";
+ }
+ /**
+ * Overrides the target database configured on the endpoint.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHouseDatabase}.
+ */
+ public String clickHouseDatabase() {
+ return "CamelClickHouseDatabase";
+ }
+ /**
+ * Overrides the target table configured on the endpoint.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHouseTable}.
+ */
+ public String clickHouseTable() {
+ return "CamelClickHouseTable";
+ }
+ /**
+ * Overrides the data format configured on the endpoint.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHouseFormat}.
+ */
+ public String clickHouseFormat() {
+ return "CamelClickHouseFormat";
+ }
+ /**
+ * The number of rows written by an insert operation.
+ *
+ * The option is a: {@code long} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHouseWrittenRows}.
+ */
+ public String clickHouseWrittenRows() {
+ return "CamelClickHouseWrittenRows";
+ }
+ /**
+ * The number of rows read by a query operation.
+ *
+ * The option is a: {@code long} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHouseReadRows}.
+ */
+ public String clickHouseReadRows() {
+ return "CamelClickHouseReadRows";
+ }
+ /**
+ * The boolean result of a ping operation.
+ *
+ * The option is a: {@code boolean} type.
+ *
+ * Group: producer
+ *
+ * @return the name of the header {@code ClickHousePingOk}.
+ */
+ public String clickHousePingOk() {
+ return "CamelClickHousePingOk";
+ }
+ }
+ static ClickHouseEndpointBuilder endpointBuilder(String componentName, String path) {
+ class ClickHouseEndpointBuilderImpl extends AbstractEndpointBuilder implements ClickHouseEndpointBuilder, AdvancedClickHouseEndpointBuilder {
+ public ClickHouseEndpointBuilderImpl(String path) {
+ super(componentName, path);
+ }
+ }
+ return new ClickHouseEndpointBuilderImpl(path);
+ }
+}
\ No newline at end of file
diff --git a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
index 1e819aadf38e..dbc6a7cc7a0c 100644
--- a/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
+++ b/dsl/camel-kamelet-main/src/generated/resources/camel-component-known-dependencies.properties
@@ -87,6 +87,7 @@ org.apache.camel.component.camunda.CamundaComponent=camel:camunda
org.apache.camel.component.cassandra.CassandraComponent=camel:cassandraql
org.apache.camel.component.chatscript.ChatScriptComponent=camel:chatscript
org.apache.camel.component.chunk.ChunkComponent=camel:chunk
+org.apache.camel.component.clickhouse.ClickHouseComponent=camel:clickhouse
org.apache.camel.component.clickup.ClickUpComponent=camel:clickup
org.apache.camel.component.cm.CMComponent=camel:cm-sms
org.apache.camel.component.cometd.CometdComponent=camel:cometd
diff --git a/parent/pom.xml b/parent/pom.xml
index c37deb587dd5..2f064be1ef9a 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -99,6 +99,7 @@
<camunda-version>7.24.0</camunda-version>
<camunda-client-java-version>8.9.13</camunda-client-java-version>
<cassandra-driver-version>4.19.3</cassandra-driver-version>
+ <clickhouse-client-version>0.9.8</clickhouse-client-version>
<jta-api-1.2-version>1.2</jta-api-1.2-version>
<chunk-templates-version>3.6.2</chunk-templates-version>
<citrus-version>5.0.0-M2</citrus-version>
@@ -1102,6 +1103,11 @@
<artifactId>camel-chunk</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-clickhouse</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-clickup</artifactId>
diff --git a/test-infra/camel-test-infra-all/pom.xml b/test-infra/camel-test-infra-all/pom.xml
index a9674528b4b6..e79e00a3a525 100644
--- a/test-infra/camel-test-infra-all/pom.xml
+++ b/test-infra/camel-test-infra-all/pom.xml
@@ -46,6 +46,11 @@
<artifactId>camel-test-infra-cassandra</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-clickhouse</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-infra-elasticsearch</artifactId>
@@ -342,6 +347,12 @@
<artifactId>camel-test-infra-cassandra</artifactId>
</dependency>
</fileSet>
+ <fileSet>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-clickhouse</artifactId>
+ </dependency>
+ </fileSet>
<fileSet>
<dependency>
<groupId>org.apache.camel</groupId>
diff --git a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
index d0efd2259650..a1b236ed29ce 100644
--- a/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
+++ b/test-infra/camel-test-infra-all/src/generated/resources/META-INF/metadata.json
@@ -691,6 +691,17 @@
"version" : "4.22.0-SNAPSHOT",
"serviceVersion" : "1.2.1",
"uiSupported" : false
+}, {
+ "service" : "org.apache.camel.test.infra.clickhouse.services.ClickHouseInfraService",
+ "description" : "ClickHouse is a high-performance columnar OLAP database",
+ "implementation" : "org.apache.camel.test.infra.clickhouse.services.ClickHouseLocalContainerInfraService",
+ "alias" : [ "clickhouse" ],
+ "aliasImplementation" : [ ],
+ "groupId" : "org.apache.camel",
+ "artifactId" : "camel-test-infra-clickhouse",
+ "version" : "4.22.0-SNAPSHOT",
+ "serviceVersion" : "24.8",
+ "uiSupported" : false
}, {
"service" : "org.apache.camel.test.infra.ollama.services.OllamaInfraService",
"description" : "Ollama is a tool for running large language models locally",
diff --git a/test-infra/camel-test-infra-clickhouse/pom.xml b/test-infra/camel-test-infra-clickhouse/pom.xml
new file mode 100644
index 000000000000..080bd3ba9fe3
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>camel-test-infra-parent</artifactId>
+ <groupId>org.apache.camel</groupId>
+ <relativePath>../camel-test-infra-parent/pom.xml</relativePath>
+ <version>4.22.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-test-infra-clickhouse</artifactId>
+ <name>Camel :: Test Infra :: ClickHouse</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-infra-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.testcontainers</groupId>
+ <artifactId>testcontainers-clickhouse</artifactId>
+ <version>${testcontainers-version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/common/ClickHouseProperties.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/common/ClickHouseProperties.java
new file mode 100644
index 000000000000..a883b556f338
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/common/ClickHouseProperties.java
@@ -0,0 +1,30 @@
+/*
+ * 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.test.infra.clickhouse.common;
+
+public final class ClickHouseProperties {
+ public static final String CLICKHOUSE_CONTAINER = "clickhouse.container";
+ public static final String CLICKHOUSE_HTTP_URL = "clickhouse.http.url";
+ public static final String CLICKHOUSE_USERNAME = "clickhouse.username";
+ public static final String CLICKHOUSE_PASSWORD = "clickhouse.password";
+ public static final String CLICKHOUSE_DATABASE = "clickhouse.database";
+
+ private ClickHouseProperties() {
+
+ }
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseInfraService.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseInfraService.java
new file mode 100644
index 000000000000..b70e4a7c36d8
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseInfraService.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.test.infra.clickhouse.services;
+
+import org.apache.camel.test.infra.common.services.InfrastructureService;
+
+/**
+ * Represents an endpoint to a ClickHouse instance
+ */
+public interface ClickHouseInfraService extends InfrastructureService {
+
+ /**
+ * The ClickHouse HTTP endpoint URL, e.g. http://localhost:8123.
+ */
+ String getHttpUrl();
+
+ String getUsername();
+
+ String getPassword();
+
+ String getDatabaseName();
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseLocalContainerInfraService.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseLocalContainerInfraService.java
new file mode 100644
index 000000000000..afaf940e26a5
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseLocalContainerInfraService.java
@@ -0,0 +1,109 @@
+/*
+ * 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.test.infra.clickhouse.services;
+
+import org.apache.camel.spi.annotations.InfraService;
+import org.apache.camel.test.infra.clickhouse.common.ClickHouseProperties;
+import org.apache.camel.test.infra.common.LocalPropertyResolver;
+import org.apache.camel.test.infra.common.services.ContainerEnvironmentUtil;
+import org.apache.camel.test.infra.common.services.ContainerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.clickhouse.ClickHouseContainer;
+import org.testcontainers.utility.DockerImageName;
+
+/**
+ * A service for a local instance of ClickHouse running with TestContainers
+ */
+@InfraService(service = ClickHouseInfraService.class,
+ description = "ClickHouse is a high-performance columnar OLAP database",
+ serviceAlias = { "clickhouse" })
+public class ClickHouseLocalContainerInfraService implements ClickHouseInfraService, ContainerService<ClickHouseContainer> {
+ private static final Logger LOG = LoggerFactory.getLogger(ClickHouseLocalContainerInfraService.class);
+
+ private final ClickHouseContainer container;
+
+ public ClickHouseLocalContainerInfraService() {
+ this(LocalPropertyResolver.getProperty(
+ ClickHouseLocalContainerInfraService.class,
+ ClickHouseProperties.CLICKHOUSE_CONTAINER));
+ }
+
+ public ClickHouseLocalContainerInfraService(String imageName) {
+ container = initContainer(imageName);
+ String name = ContainerEnvironmentUtil.containerName(ClickHouseLocalContainerInfraService.this.getClass());
+ if (name != null) {
+ container.withCreateContainerCmdModifier(cmd -> cmd.withName(name));
+ }
+ }
+
+ public ClickHouseLocalContainerInfraService(ClickHouseContainer container) {
+ this.container = container;
+ }
+
+ protected ClickHouseContainer initContainer(String imageName) {
+ return new ClickHouseContainer(
+ DockerImageName.parse(imageName).asCompatibleSubstituteFor("clickhouse/clickhouse-server"));
+ }
+
+ @Override
+ public String getHttpUrl() {
+ return container.getHttpUrl();
+ }
+
+ @Override
+ public String getUsername() {
+ return container.getUsername();
+ }
+
+ @Override
+ public String getPassword() {
+ return container.getPassword();
+ }
+
+ @Override
+ public String getDatabaseName() {
+ return container.getDatabaseName();
+ }
+
+ @Override
+ public void registerProperties() {
+ System.setProperty(ClickHouseProperties.CLICKHOUSE_HTTP_URL, getHttpUrl());
+ System.setProperty(ClickHouseProperties.CLICKHOUSE_USERNAME, getUsername());
+ System.setProperty(ClickHouseProperties.CLICKHOUSE_PASSWORD, getPassword());
+ System.setProperty(ClickHouseProperties.CLICKHOUSE_DATABASE, getDatabaseName());
+ }
+
+ @Override
+ public void initialize() {
+ container.start();
+
+ registerProperties();
+ LOG.info("ClickHouse server running at address {}", getHttpUrl());
+ }
+
+ @Override
+ public void shutdown() {
+ LOG.info("Stopping the ClickHouse container");
+ container.stop();
+ }
+
+ @Override
+ public ClickHouseContainer getContainer() {
+ return container;
+ }
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseLocalContainerService.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseLocalContainerService.java
new file mode 100644
index 000000000000..41586cfb2ae4
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseLocalContainerService.java
@@ -0,0 +1,21 @@
+/*
+ * 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.test.infra.clickhouse.services;
+
+public class ClickHouseLocalContainerService extends ClickHouseLocalContainerInfraService
+ implements ClickHouseService {
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseService.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseService.java
new file mode 100644
index 000000000000..7d70b7e74632
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseService.java
@@ -0,0 +1,23 @@
+/*
+ * 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.test.infra.clickhouse.services;
+
+import org.apache.camel.test.infra.common.services.ContainerTestService;
+import org.apache.camel.test.infra.common.services.TestService;
+
+public interface ClickHouseService extends TestService, ClickHouseInfraService, ContainerTestService {
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseServiceFactory.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseServiceFactory.java
new file mode 100644
index 000000000000..75bc2284eec0
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/ClickHouseServiceFactory.java
@@ -0,0 +1,53 @@
+/*
+ * 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.test.infra.clickhouse.services;
+
+import org.apache.camel.test.infra.common.services.SimpleTestServiceBuilder;
+
+public final class ClickHouseServiceFactory {
+ private ClickHouseServiceFactory() {
+
+ }
+
+ public static SimpleTestServiceBuilder<ClickHouseService> builder() {
+ return new SimpleTestServiceBuilder<>("clickhouse");
+ }
+
+ public static ClickHouseService createService() {
+ return builder()
+ .addLocalMapping(ClickHouseLocalContainerService::new)
+ .addRemoteMapping(RemoteClickHouseService::new)
+ .build();
+ }
+
+ public static ClickHouseService createSingletonService() {
+ return SingletonServiceHolder.INSTANCE;
+ }
+
+ public static class RemoteClickHouseService extends RemoteClickHouseInfraService implements ClickHouseService {
+ }
+
+ private static class SingletonServiceHolder {
+ static final ClickHouseService INSTANCE;
+ static {
+ SimpleTestServiceBuilder<ClickHouseService> instance = builder();
+ instance.addLocalMapping(ClickHouseLocalContainerService::new)
+ .addRemoteMapping(RemoteClickHouseService::new);
+ INSTANCE = instance.build();
+ }
+ }
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/RemoteClickHouseInfraService.java b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/RemoteClickHouseInfraService.java
new file mode 100644
index 000000000000..58c63f490367
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/java/org/apache/camel/test/infra/clickhouse/services/RemoteClickHouseInfraService.java
@@ -0,0 +1,63 @@
+/*
+ * 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.test.infra.clickhouse.services;
+
+import org.apache.camel.test.infra.clickhouse.common.ClickHouseProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A remote instance of ClickHouse
+ */
+public class RemoteClickHouseInfraService implements ClickHouseInfraService {
+ private static final Logger LOG = LoggerFactory.getLogger(RemoteClickHouseInfraService.class);
+
+ @Override
+ public String getHttpUrl() {
+ return System.getProperty(ClickHouseProperties.CLICKHOUSE_HTTP_URL);
+ }
+
+ @Override
+ public String getUsername() {
+ return System.getProperty(ClickHouseProperties.CLICKHOUSE_USERNAME, "default");
+ }
+
+ @Override
+ public String getPassword() {
+ return System.getProperty(ClickHouseProperties.CLICKHOUSE_PASSWORD, "");
+ }
+
+ @Override
+ public String getDatabaseName() {
+ return System.getProperty(ClickHouseProperties.CLICKHOUSE_DATABASE, "default");
+ }
+
+ @Override
+ public void registerProperties() {
+ // NO-OP
+ }
+
+ @Override
+ public void initialize() {
+ registerProperties();
+ }
+
+ @Override
+ public void shutdown() {
+ // NO-OP
+ }
+}
diff --git a/test-infra/camel-test-infra-clickhouse/src/main/resources/org/apache/camel/test/infra/clickhouse/services/container.properties b/test-infra/camel-test-infra-clickhouse/src/main/resources/org/apache/camel/test/infra/clickhouse/services/container.properties
new file mode 100644
index 000000000000..909d24760511
--- /dev/null
+++ b/test-infra/camel-test-infra-clickhouse/src/main/resources/org/apache/camel/test/infra/clickhouse/services/container.properties
@@ -0,0 +1,17 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+clickhouse.container=mirror.gcr.io/clickhouse/clickhouse-server:24.8
diff --git a/test-infra/pom.xml b/test-infra/pom.xml
index 77052dee985e..9d71d087c2a1 100644
--- a/test-infra/pom.xml
+++ b/test-infra/pom.xml
@@ -45,6 +45,7 @@
<module>camel-test-infra-aws-common</module>
<module>camel-test-infra-aws-v2</module>
<module>camel-test-infra-cassandra</module>
+ <module>camel-test-infra-clickhouse</module>
<module>camel-test-infra-elasticsearch</module>
<module>camel-test-infra-couchbase</module>
<module>camel-test-infra-mongodb</module>