diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index bae2e243ad389..e3eb1bc280737 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -1027,6 +1027,11 @@
camel-iec60870
4.14.0-SNAPSHOT
+
+ org.apache.camel
+ camel-iggy
+ 4.14.0-SNAPSHOT
+
org.apache.camel
camel-ignite
diff --git a/catalog/camel-allcomponents/pom.xml b/catalog/camel-allcomponents/pom.xml
index 32890b8166f37..d3687dd24a835 100644
--- a/catalog/camel-allcomponents/pom.xml
+++ b/catalog/camel-allcomponents/pom.xml
@@ -891,6 +891,11 @@
camel-iec60870
${project.version}
+
+ org.apache.camel
+ camel-iggy
+ ${project.version}
+
org.apache.camel
camel-ignite
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 bf628cfc0c8c6..832bc9647a9e2 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
@@ -155,6 +155,7 @@ hwcloud-smn
ibm-secrets-manager
iec60870-client
iec60870-server
+iggy
ignite-cache
ignite-compute
ignite-events
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json
new file mode 100644
index 0000000000000..a309f8e339dd4
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/iggy.json
@@ -0,0 +1,85 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "iggy",
+ "title": "Iggy",
+ "description": "Camel Iggy component",
+ "deprecated": false,
+ "firstVersion": "4.14.0",
+ "label": "messaging",
+ "javaType": "org.apache.camel.component.iggy.IggyComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-iggy",
+ "version": "4.14.0-SNAPSHOT",
+ "scheme": "iggy",
+ "extendsScheme": "",
+ "syntax": "iggy:topicName",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": false,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "autoCreateStream": { "index": 0, "kind": "property", "displayName": "Auto Create Stream", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create stream if it does not exist" },
+ "autoCreateTopic": { "index": 1, "kind": "property", "displayName": "Auto Create Topic", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create topic if it does not exist" },
+ "clientTransport": { "index": 2, "kind": "property", "displayName": "Client Transport", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "TCP", "HTTP" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TCP", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "compressionAlgorithm": { "index": 3, "kind": "property", "displayName": "Compression Algorithm", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.iggy.topic.CompressionAlgorithm", "enum": [ "None", "Gzip" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "None", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Compression algorithm for message payload" },
+ "configuration": { "index": 4, "kind": "property", "displayName": "Configuration", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.iggy.IggyConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to pre-configure the Iggy component with common options that the endpoints will reuse." },
+ "host": { "index": 5, "kind": "property", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server hostname or IP address" },
+ "maxTopicSize": { "index": 6, "kind": "property", "displayName": "Max Topic Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Maximum topic size in bytes (0 means unlimited)" },
+ "messageExpiry": { "index": 7, "kind": "property", "displayName": "Message Expiry", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Message expiry time in seconds (0 means no expiry)" },
+ "partitionsCount": { "index": 8, "kind": "property", "displayName": "Partitions Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Number of partitions for the topic" },
+ "password": { "index": 9, "kind": "property", "displayName": "Password", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy password" },
+ "port": { "index": 10, "kind": "property", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 8090, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server port number" },
+ "replicationFactor": { "index": 11, "kind": "property", "displayName": "Replication Factor", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Short", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Replication factor for the topic" },
+ "streamId": { "index": 12, "kind": "property", "displayName": "Stream Id", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream identifier" },
+ "streamName": { "index": 13, "kind": "property", "displayName": "Stream Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream name" },
+ "autoCommit": { "index": 14, "kind": "property", "displayName": "Auto Commit", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Controls message acknowledgment behavior. When true, messages are automatically marked as processed after consumption. When false, enables manual offset management and allows setting a custom starting offset position" },
+ "bridgeErrorHandler": { "index": 15, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
+ "consumerGroupName": { "index": 16, "kind": "property", "displayName": "Consumer Group Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The name of the consumer group" },
+ "consumersCount": { "index": 17, "kind": "property", "displayName": "Consumers Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy consumers count" },
+ "partitionId": { "index": 18, "kind": "property", "displayName": "Partition Id", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer partition id" },
+ "pollBatchSize": { "index": 19, "kind": "property", "displayName": "Poll Batch Size", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "10", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer poll batch size" },
+ "pollingStrategy": { "index": 20, "kind": "property", "displayName": "Polling Strategy", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "next", "first", "last" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "next", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "shutdownTimeout": { "index": 21, "kind": "property", "displayName": "Shutdown Timeout", "group": "consumer", "label": "common,consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy shutdown timeout" },
+ "startingOffset": { "index": 22, "kind": "property", "displayName": "Starting Offset", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Defines the initial message offset position when autoCommit is disabled. Use 0 to start from the beginning of the stream, or specify a custom offset to resume from a particular point" },
+ "lazyStartProducer": { "index": 23, "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 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." },
+ "partitioning": { "index": 24, "kind": "property", "displayName": "Partitioning", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.iggy.message.Partitioning", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "balanced", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Partitioning strategy for message distribution" },
+ "autowiredEnabled": { "index": 25, "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 type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." },
+ "username": { "index": 26, "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy username" }
+ },
+ "properties": {
+ "topicName": { "index": 0, "kind": "path", "displayName": "Topic Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the topic" },
+ "autoCreateStream": { "index": 1, "kind": "parameter", "displayName": "Auto Create Stream", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create stream if it does not exist" },
+ "autoCreateTopic": { "index": 2, "kind": "parameter", "displayName": "Auto Create Topic", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create topic if it does not exist" },
+ "clientTransport": { "index": 3, "kind": "parameter", "displayName": "Client Transport", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "TCP", "HTTP" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TCP", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "compressionAlgorithm": { "index": 4, "kind": "parameter", "displayName": "Compression Algorithm", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.iggy.topic.CompressionAlgorithm", "enum": [ "None", "Gzip" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "None", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Compression algorithm for message payload" },
+ "host": { "index": 5, "kind": "parameter", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server hostname or IP address" },
+ "maxTopicSize": { "index": 6, "kind": "parameter", "displayName": "Max Topic Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Maximum topic size in bytes (0 means unlimited)" },
+ "messageExpiry": { "index": 7, "kind": "parameter", "displayName": "Message Expiry", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Message expiry time in seconds (0 means no expiry)" },
+ "partitionsCount": { "index": 8, "kind": "parameter", "displayName": "Partitions Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Number of partitions for the topic" },
+ "password": { "index": 9, "kind": "parameter", "displayName": "Password", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy password" },
+ "port": { "index": 10, "kind": "parameter", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 8090, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server port number" },
+ "replicationFactor": { "index": 11, "kind": "parameter", "displayName": "Replication Factor", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Short", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Replication factor for the topic" },
+ "streamId": { "index": 12, "kind": "parameter", "displayName": "Stream Id", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream identifier" },
+ "streamName": { "index": 13, "kind": "parameter", "displayName": "Stream Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream name" },
+ "autoCommit": { "index": 14, "kind": "parameter", "displayName": "Auto Commit", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Controls message acknowledgment behavior. When true, messages are automatically marked as processed after consumption. When false, enables manual offset management and allows setting a custom starting offset position" },
+ "consumerGroupName": { "index": 15, "kind": "parameter", "displayName": "Consumer Group Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The name of the consumer group" },
+ "consumersCount": { "index": 16, "kind": "parameter", "displayName": "Consumers Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy consumers count" },
+ "partitionId": { "index": 17, "kind": "parameter", "displayName": "Partition Id", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer partition id" },
+ "pollBatchSize": { "index": 18, "kind": "parameter", "displayName": "Poll Batch Size", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "10", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer poll batch size" },
+ "pollingStrategy": { "index": 19, "kind": "parameter", "displayName": "Polling Strategy", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "next", "first", "last" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "next", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "shutdownTimeout": { "index": 20, "kind": "parameter", "displayName": "Shutdown Timeout", "group": "consumer", "label": "common,consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy shutdown timeout" },
+ "startingOffset": { "index": 21, "kind": "parameter", "displayName": "Starting Offset", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Defines the initial message offset position when autoCommit is disabled. Use 0 to start from the beginning of the stream, or specify a custom offset to resume from a particular point" },
+ "bridgeErrorHandler": { "index": 22, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
+ "exceptionHandler": { "index": 23, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
+ "exchangePattern": { "index": 24, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+ "partitioning": { "index": 25, "kind": "parameter", "displayName": "Partitioning", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.iggy.message.Partitioning", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "balanced", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Partitioning strategy for message distribution" },
+ "lazyStartProducer": { "index": 26, "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 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." },
+ "username": { "index": 27, "kind": "parameter", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy username" }
+ }
+}
diff --git a/components/camel-iggy/pom.xml b/components/camel-iggy/pom.xml
new file mode 100644
index 0000000000000..45bbd76aeedfa
--- /dev/null
+++ b/components/camel-iggy/pom.xml
@@ -0,0 +1,86 @@
+
+
+
+ 4.0.0
+
+
+ org.apache.camel
+ components
+ 4.14.0-SNAPSHOT
+
+
+ camel-iggy
+ jar
+ Camel :: Iggy
+ Camel Iggy component
+
+
+
+ org.apache.camel
+ camel-support
+
+
+ org.apache.iggy
+ iggy-java-sdk
+ ${iggy-version}
+
+
+ org.apache.commons
+ commons-pool2
+ ${commons-pool2-version}
+
+
+
+
+ org.apache.camel
+ camel-test-junit5
+ test
+
+
+ org.apache.camel
+ camel-test-infra-core
+ ${project.version}
+ test
+ test-jar
+
+
+ org.apache.camel
+ camel-test-infra-iggy
+ ${project.version}
+ test
+ test-jar
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ org.assertj
+ assertj-core
+
+
+
+
\ No newline at end of file
diff --git a/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyComponentConfigurer.java b/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyComponentConfigurer.java
new file mode 100644
index 0000000000000..30dc2a9d6ca4c
--- /dev/null
+++ b/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyComponentConfigurer.java
@@ -0,0 +1,196 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.iggy;
+
+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 IggyComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ private org.apache.camel.component.iggy.IggyConfiguration getOrCreateConfiguration(IggyComponent target) {
+ if (target.getConfiguration() == null) {
+ target.setConfiguration(new org.apache.camel.component.iggy.IggyConfiguration());
+ }
+ return target.getConfiguration();
+ }
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ IggyComponent target = (IggyComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autocommit":
+ case "autoCommit": getOrCreateConfiguration(target).setAutoCommit(property(camelContext, boolean.class, value)); return true;
+ case "autocreatestream":
+ case "autoCreateStream": getOrCreateConfiguration(target).setAutoCreateStream(property(camelContext, boolean.class, value)); return true;
+ case "autocreatetopic":
+ case "autoCreateTopic": getOrCreateConfiguration(target).setAutoCreateTopic(property(camelContext, boolean.class, value)); return true;
+ case "autowiredenabled":
+ case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
+ case "clienttransport":
+ case "clientTransport": getOrCreateConfiguration(target).setClientTransport(property(camelContext, java.lang.String.class, value)); return true;
+ case "compressionalgorithm":
+ case "compressionAlgorithm": getOrCreateConfiguration(target).setCompressionAlgorithm(property(camelContext, org.apache.iggy.topic.CompressionAlgorithm.class, value)); return true;
+ case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.iggy.IggyConfiguration.class, value)); return true;
+ case "consumergroupname":
+ case "consumerGroupName": getOrCreateConfiguration(target).setConsumerGroupName(property(camelContext, java.lang.String.class, value)); return true;
+ case "consumerscount":
+ case "consumersCount": getOrCreateConfiguration(target).setConsumersCount(property(camelContext, int.class, value)); return true;
+ case "host": getOrCreateConfiguration(target).setHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "maxtopicsize":
+ case "maxTopicSize": getOrCreateConfiguration(target).setMaxTopicSize(property(camelContext, java.lang.Long.class, value)); return true;
+ case "messageexpiry":
+ case "messageExpiry": getOrCreateConfiguration(target).setMessageExpiry(property(camelContext, java.lang.Long.class, value)); return true;
+ case "partitionid":
+ case "partitionId": getOrCreateConfiguration(target).setPartitionId(property(camelContext, java.lang.Long.class, value)); return true;
+ case "partitioning": getOrCreateConfiguration(target).setPartitioning(property(camelContext, org.apache.iggy.message.Partitioning.class, value)); return true;
+ case "partitionscount":
+ case "partitionsCount": getOrCreateConfiguration(target).setPartitionsCount(property(camelContext, java.lang.Long.class, value)); return true;
+ case "password": getOrCreateConfiguration(target).setPassword(property(camelContext, java.lang.String.class, value)); return true;
+ case "pollbatchsize":
+ case "pollBatchSize": getOrCreateConfiguration(target).setPollBatchSize(property(camelContext, java.lang.Long.class, value)); return true;
+ case "pollingstrategy":
+ case "pollingStrategy": getOrCreateConfiguration(target).setPollingStrategy(property(camelContext, java.lang.String.class, value)); return true;
+ case "port": getOrCreateConfiguration(target).setPort(property(camelContext, int.class, value)); return true;
+ case "replicationfactor":
+ case "replicationFactor": getOrCreateConfiguration(target).setReplicationFactor(property(camelContext, java.lang.Short.class, value)); return true;
+ case "shutdowntimeout":
+ case "shutdownTimeout": getOrCreateConfiguration(target).setShutdownTimeout(property(camelContext, int.class, value)); return true;
+ case "startingoffset":
+ case "startingOffset": getOrCreateConfiguration(target).setStartingOffset(property(camelContext, java.lang.Long.class, value)); return true;
+ case "streamid":
+ case "streamId": getOrCreateConfiguration(target).setStreamId(property(camelContext, java.lang.Long.class, value)); return true;
+ case "streamname":
+ case "streamName": getOrCreateConfiguration(target).setStreamName(property(camelContext, java.lang.String.class, value)); return true;
+ case "username": getOrCreateConfiguration(target).setUsername(property(camelContext, java.lang.String.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autocommit":
+ case "autoCommit": return boolean.class;
+ case "autocreatestream":
+ case "autoCreateStream": return boolean.class;
+ case "autocreatetopic":
+ case "autoCreateTopic": return boolean.class;
+ case "autowiredenabled":
+ case "autowiredEnabled": return boolean.class;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return boolean.class;
+ case "clienttransport":
+ case "clientTransport": return java.lang.String.class;
+ case "compressionalgorithm":
+ case "compressionAlgorithm": return org.apache.iggy.topic.CompressionAlgorithm.class;
+ case "configuration": return org.apache.camel.component.iggy.IggyConfiguration.class;
+ case "consumergroupname":
+ case "consumerGroupName": return java.lang.String.class;
+ case "consumerscount":
+ case "consumersCount": return int.class;
+ case "host": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "maxtopicsize":
+ case "maxTopicSize": return java.lang.Long.class;
+ case "messageexpiry":
+ case "messageExpiry": return java.lang.Long.class;
+ case "partitionid":
+ case "partitionId": return java.lang.Long.class;
+ case "partitioning": return org.apache.iggy.message.Partitioning.class;
+ case "partitionscount":
+ case "partitionsCount": return java.lang.Long.class;
+ case "password": return java.lang.String.class;
+ case "pollbatchsize":
+ case "pollBatchSize": return java.lang.Long.class;
+ case "pollingstrategy":
+ case "pollingStrategy": return java.lang.String.class;
+ case "port": return int.class;
+ case "replicationfactor":
+ case "replicationFactor": return java.lang.Short.class;
+ case "shutdowntimeout":
+ case "shutdownTimeout": return int.class;
+ case "startingoffset":
+ case "startingOffset": return java.lang.Long.class;
+ case "streamid":
+ case "streamId": return java.lang.Long.class;
+ case "streamname":
+ case "streamName": return java.lang.String.class;
+ case "username": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ IggyComponent target = (IggyComponent) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autocommit":
+ case "autoCommit": return getOrCreateConfiguration(target).isAutoCommit();
+ case "autocreatestream":
+ case "autoCreateStream": return getOrCreateConfiguration(target).isAutoCreateStream();
+ case "autocreatetopic":
+ case "autoCreateTopic": return getOrCreateConfiguration(target).isAutoCreateTopic();
+ case "autowiredenabled":
+ case "autowiredEnabled": return target.isAutowiredEnabled();
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "clienttransport":
+ case "clientTransport": return getOrCreateConfiguration(target).getClientTransport();
+ case "compressionalgorithm":
+ case "compressionAlgorithm": return getOrCreateConfiguration(target).getCompressionAlgorithm();
+ case "configuration": return target.getConfiguration();
+ case "consumergroupname":
+ case "consumerGroupName": return getOrCreateConfiguration(target).getConsumerGroupName();
+ case "consumerscount":
+ case "consumersCount": return getOrCreateConfiguration(target).getConsumersCount();
+ case "host": return getOrCreateConfiguration(target).getHost();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "maxtopicsize":
+ case "maxTopicSize": return getOrCreateConfiguration(target).getMaxTopicSize();
+ case "messageexpiry":
+ case "messageExpiry": return getOrCreateConfiguration(target).getMessageExpiry();
+ case "partitionid":
+ case "partitionId": return getOrCreateConfiguration(target).getPartitionId();
+ case "partitioning": return getOrCreateConfiguration(target).getPartitioning();
+ case "partitionscount":
+ case "partitionsCount": return getOrCreateConfiguration(target).getPartitionsCount();
+ case "password": return getOrCreateConfiguration(target).getPassword();
+ case "pollbatchsize":
+ case "pollBatchSize": return getOrCreateConfiguration(target).getPollBatchSize();
+ case "pollingstrategy":
+ case "pollingStrategy": return getOrCreateConfiguration(target).getPollingStrategy();
+ case "port": return getOrCreateConfiguration(target).getPort();
+ case "replicationfactor":
+ case "replicationFactor": return getOrCreateConfiguration(target).getReplicationFactor();
+ case "shutdowntimeout":
+ case "shutdownTimeout": return getOrCreateConfiguration(target).getShutdownTimeout();
+ case "startingoffset":
+ case "startingOffset": return getOrCreateConfiguration(target).getStartingOffset();
+ case "streamid":
+ case "streamId": return getOrCreateConfiguration(target).getStreamId();
+ case "streamname":
+ case "streamName": return getOrCreateConfiguration(target).getStreamName();
+ case "username": return getOrCreateConfiguration(target).getUsername();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyEndpointConfigurer.java b/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyEndpointConfigurer.java
new file mode 100644
index 0000000000000..63cc1c3be4e25
--- /dev/null
+++ b/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyEndpointConfigurer.java
@@ -0,0 +1,192 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.iggy;
+
+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 IggyEndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+ @Override
+ public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+ IggyEndpoint target = (IggyEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autocommit":
+ case "autoCommit": target.getConfiguration().setAutoCommit(property(camelContext, boolean.class, value)); return true;
+ case "autocreatestream":
+ case "autoCreateStream": target.getConfiguration().setAutoCreateStream(property(camelContext, boolean.class, value)); return true;
+ case "autocreatetopic":
+ case "autoCreateTopic": target.getConfiguration().setAutoCreateTopic(property(camelContext, boolean.class, value)); return true;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
+ case "clienttransport":
+ case "clientTransport": target.getConfiguration().setClientTransport(property(camelContext, java.lang.String.class, value)); return true;
+ case "compressionalgorithm":
+ case "compressionAlgorithm": target.getConfiguration().setCompressionAlgorithm(property(camelContext, org.apache.iggy.topic.CompressionAlgorithm.class, value)); return true;
+ case "consumergroupname":
+ case "consumerGroupName": target.getConfiguration().setConsumerGroupName(property(camelContext, java.lang.String.class, value)); return true;
+ case "consumerscount":
+ case "consumersCount": target.getConfiguration().setConsumersCount(property(camelContext, int.class, value)); return true;
+ case "exceptionhandler":
+ case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true;
+ case "exchangepattern":
+ case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true;
+ case "host": target.getConfiguration().setHost(property(camelContext, java.lang.String.class, value)); return true;
+ case "lazystartproducer":
+ case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+ case "maxtopicsize":
+ case "maxTopicSize": target.getConfiguration().setMaxTopicSize(property(camelContext, java.lang.Long.class, value)); return true;
+ case "messageexpiry":
+ case "messageExpiry": target.getConfiguration().setMessageExpiry(property(camelContext, java.lang.Long.class, value)); return true;
+ case "partitionid":
+ case "partitionId": target.getConfiguration().setPartitionId(property(camelContext, java.lang.Long.class, value)); return true;
+ case "partitioning": target.getConfiguration().setPartitioning(property(camelContext, org.apache.iggy.message.Partitioning.class, value)); return true;
+ case "partitionscount":
+ case "partitionsCount": target.getConfiguration().setPartitionsCount(property(camelContext, java.lang.Long.class, value)); return true;
+ case "password": target.getConfiguration().setPassword(property(camelContext, java.lang.String.class, value)); return true;
+ case "pollbatchsize":
+ case "pollBatchSize": target.getConfiguration().setPollBatchSize(property(camelContext, java.lang.Long.class, value)); return true;
+ case "pollingstrategy":
+ case "pollingStrategy": target.getConfiguration().setPollingStrategy(property(camelContext, java.lang.String.class, value)); return true;
+ case "port": target.getConfiguration().setPort(property(camelContext, int.class, value)); return true;
+ case "replicationfactor":
+ case "replicationFactor": target.getConfiguration().setReplicationFactor(property(camelContext, java.lang.Short.class, value)); return true;
+ case "shutdowntimeout":
+ case "shutdownTimeout": target.getConfiguration().setShutdownTimeout(property(camelContext, int.class, value)); return true;
+ case "startingoffset":
+ case "startingOffset": target.getConfiguration().setStartingOffset(property(camelContext, java.lang.Long.class, value)); return true;
+ case "streamid":
+ case "streamId": target.getConfiguration().setStreamId(property(camelContext, java.lang.Long.class, value)); return true;
+ case "streamname":
+ case "streamName": target.getConfiguration().setStreamName(property(camelContext, java.lang.String.class, value)); return true;
+ case "username": target.getConfiguration().setUsername(property(camelContext, java.lang.String.class, value)); return true;
+ default: return false;
+ }
+ }
+
+ @Override
+ public Class> getOptionType(String name, boolean ignoreCase) {
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autocommit":
+ case "autoCommit": return boolean.class;
+ case "autocreatestream":
+ case "autoCreateStream": return boolean.class;
+ case "autocreatetopic":
+ case "autoCreateTopic": return boolean.class;
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return boolean.class;
+ case "clienttransport":
+ case "clientTransport": return java.lang.String.class;
+ case "compressionalgorithm":
+ case "compressionAlgorithm": return org.apache.iggy.topic.CompressionAlgorithm.class;
+ case "consumergroupname":
+ case "consumerGroupName": return java.lang.String.class;
+ case "consumerscount":
+ case "consumersCount": return int.class;
+ case "exceptionhandler":
+ case "exceptionHandler": return org.apache.camel.spi.ExceptionHandler.class;
+ case "exchangepattern":
+ case "exchangePattern": return org.apache.camel.ExchangePattern.class;
+ case "host": return java.lang.String.class;
+ case "lazystartproducer":
+ case "lazyStartProducer": return boolean.class;
+ case "maxtopicsize":
+ case "maxTopicSize": return java.lang.Long.class;
+ case "messageexpiry":
+ case "messageExpiry": return java.lang.Long.class;
+ case "partitionid":
+ case "partitionId": return java.lang.Long.class;
+ case "partitioning": return org.apache.iggy.message.Partitioning.class;
+ case "partitionscount":
+ case "partitionsCount": return java.lang.Long.class;
+ case "password": return java.lang.String.class;
+ case "pollbatchsize":
+ case "pollBatchSize": return java.lang.Long.class;
+ case "pollingstrategy":
+ case "pollingStrategy": return java.lang.String.class;
+ case "port": return int.class;
+ case "replicationfactor":
+ case "replicationFactor": return java.lang.Short.class;
+ case "shutdowntimeout":
+ case "shutdownTimeout": return int.class;
+ case "startingoffset":
+ case "startingOffset": return java.lang.Long.class;
+ case "streamid":
+ case "streamId": return java.lang.Long.class;
+ case "streamname":
+ case "streamName": return java.lang.String.class;
+ case "username": return java.lang.String.class;
+ default: return null;
+ }
+ }
+
+ @Override
+ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+ IggyEndpoint target = (IggyEndpoint) obj;
+ switch (ignoreCase ? name.toLowerCase() : name) {
+ case "autocommit":
+ case "autoCommit": return target.getConfiguration().isAutoCommit();
+ case "autocreatestream":
+ case "autoCreateStream": return target.getConfiguration().isAutoCreateStream();
+ case "autocreatetopic":
+ case "autoCreateTopic": return target.getConfiguration().isAutoCreateTopic();
+ case "bridgeerrorhandler":
+ case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "clienttransport":
+ case "clientTransport": return target.getConfiguration().getClientTransport();
+ case "compressionalgorithm":
+ case "compressionAlgorithm": return target.getConfiguration().getCompressionAlgorithm();
+ case "consumergroupname":
+ case "consumerGroupName": return target.getConfiguration().getConsumerGroupName();
+ case "consumerscount":
+ case "consumersCount": return target.getConfiguration().getConsumersCount();
+ case "exceptionhandler":
+ case "exceptionHandler": return target.getExceptionHandler();
+ case "exchangepattern":
+ case "exchangePattern": return target.getExchangePattern();
+ case "host": return target.getConfiguration().getHost();
+ case "lazystartproducer":
+ case "lazyStartProducer": return target.isLazyStartProducer();
+ case "maxtopicsize":
+ case "maxTopicSize": return target.getConfiguration().getMaxTopicSize();
+ case "messageexpiry":
+ case "messageExpiry": return target.getConfiguration().getMessageExpiry();
+ case "partitionid":
+ case "partitionId": return target.getConfiguration().getPartitionId();
+ case "partitioning": return target.getConfiguration().getPartitioning();
+ case "partitionscount":
+ case "partitionsCount": return target.getConfiguration().getPartitionsCount();
+ case "password": return target.getConfiguration().getPassword();
+ case "pollbatchsize":
+ case "pollBatchSize": return target.getConfiguration().getPollBatchSize();
+ case "pollingstrategy":
+ case "pollingStrategy": return target.getConfiguration().getPollingStrategy();
+ case "port": return target.getConfiguration().getPort();
+ case "replicationfactor":
+ case "replicationFactor": return target.getConfiguration().getReplicationFactor();
+ case "shutdowntimeout":
+ case "shutdownTimeout": return target.getConfiguration().getShutdownTimeout();
+ case "startingoffset":
+ case "startingOffset": return target.getConfiguration().getStartingOffset();
+ case "streamid":
+ case "streamId": return target.getConfiguration().getStreamId();
+ case "streamname":
+ case "streamName": return target.getConfiguration().getStreamName();
+ case "username": return target.getConfiguration().getUsername();
+ default: return null;
+ }
+ }
+}
+
diff --git a/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyEndpointUriFactory.java b/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyEndpointUriFactory.java
new file mode 100644
index 0000000000000..a072c7b8fb104
--- /dev/null
+++ b/components/camel-iggy/src/generated/java/org/apache/camel/component/iggy/IggyEndpointUriFactory.java
@@ -0,0 +1,100 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.iggy;
+
+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 IggyEndpointUriFactory extends org.apache.camel.support.component.EndpointUriFactorySupport implements EndpointUriFactory {
+
+ private static final String BASE = ":topicName";
+
+ private static final Set PROPERTY_NAMES;
+ private static final Set SECRET_PROPERTY_NAMES;
+ private static final Set MULTI_VALUE_PREFIXES;
+ static {
+ Set props = new HashSet<>(28);
+ props.add("autoCommit");
+ props.add("autoCreateStream");
+ props.add("autoCreateTopic");
+ props.add("bridgeErrorHandler");
+ props.add("clientTransport");
+ props.add("compressionAlgorithm");
+ props.add("consumerGroupName");
+ props.add("consumersCount");
+ props.add("exceptionHandler");
+ props.add("exchangePattern");
+ props.add("host");
+ props.add("lazyStartProducer");
+ props.add("maxTopicSize");
+ props.add("messageExpiry");
+ props.add("partitionId");
+ props.add("partitioning");
+ props.add("partitionsCount");
+ props.add("password");
+ props.add("pollBatchSize");
+ props.add("pollingStrategy");
+ props.add("port");
+ props.add("replicationFactor");
+ props.add("shutdownTimeout");
+ props.add("startingOffset");
+ props.add("streamId");
+ props.add("streamName");
+ props.add("topicName");
+ props.add("username");
+ PROPERTY_NAMES = Collections.unmodifiableSet(props);
+ Set secretProps = new HashSet<>(2);
+ secretProps.add("password");
+ secretProps.add("username");
+ SECRET_PROPERTY_NAMES = Collections.unmodifiableSet(secretProps);
+ MULTI_VALUE_PREFIXES = Collections.emptySet();
+ }
+
+ @Override
+ public boolean isEnabled(String scheme) {
+ return "iggy".equals(scheme);
+ }
+
+ @Override
+ public String buildUri(String scheme, Map properties, boolean encode) throws URISyntaxException {
+ String syntax = scheme + BASE;
+ String uri = syntax;
+
+ Map copy = new HashMap<>(properties);
+
+ uri = buildPathParameter(syntax, uri, "topicName", null, true, copy);
+ uri = buildQueryParameters(uri, copy, encode);
+ return uri;
+ }
+
+ @Override
+ public Set propertyNames() {
+ return PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set secretPropertyNames() {
+ return SECRET_PROPERTY_NAMES;
+ }
+
+ @Override
+ public Set multiValuePrefixes() {
+ return MULTI_VALUE_PREFIXES;
+ }
+
+ @Override
+ public boolean isLenientProperties() {
+ return false;
+ }
+}
+
diff --git a/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json b/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json
new file mode 100644
index 0000000000000..a309f8e339dd4
--- /dev/null
+++ b/components/camel-iggy/src/generated/resources/META-INF/org/apache/camel/component/iggy/iggy.json
@@ -0,0 +1,85 @@
+{
+ "component": {
+ "kind": "component",
+ "name": "iggy",
+ "title": "Iggy",
+ "description": "Camel Iggy component",
+ "deprecated": false,
+ "firstVersion": "4.14.0",
+ "label": "messaging",
+ "javaType": "org.apache.camel.component.iggy.IggyComponent",
+ "supportLevel": "Preview",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-iggy",
+ "version": "4.14.0-SNAPSHOT",
+ "scheme": "iggy",
+ "extendsScheme": "",
+ "syntax": "iggy:topicName",
+ "async": false,
+ "api": false,
+ "consumerOnly": false,
+ "producerOnly": false,
+ "lenientProperties": false,
+ "browsable": false,
+ "remote": true
+ },
+ "componentProperties": {
+ "autoCreateStream": { "index": 0, "kind": "property", "displayName": "Auto Create Stream", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create stream if it does not exist" },
+ "autoCreateTopic": { "index": 1, "kind": "property", "displayName": "Auto Create Topic", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create topic if it does not exist" },
+ "clientTransport": { "index": 2, "kind": "property", "displayName": "Client Transport", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "TCP", "HTTP" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TCP", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "compressionAlgorithm": { "index": 3, "kind": "property", "displayName": "Compression Algorithm", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.iggy.topic.CompressionAlgorithm", "enum": [ "None", "Gzip" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "None", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Compression algorithm for message payload" },
+ "configuration": { "index": 4, "kind": "property", "displayName": "Configuration", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.iggy.IggyConfiguration", "deprecated": false, "autowired": false, "secret": false, "description": "Allows to pre-configure the Iggy component with common options that the endpoints will reuse." },
+ "host": { "index": 5, "kind": "property", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server hostname or IP address" },
+ "maxTopicSize": { "index": 6, "kind": "property", "displayName": "Max Topic Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Maximum topic size in bytes (0 means unlimited)" },
+ "messageExpiry": { "index": 7, "kind": "property", "displayName": "Message Expiry", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Message expiry time in seconds (0 means no expiry)" },
+ "partitionsCount": { "index": 8, "kind": "property", "displayName": "Partitions Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Number of partitions for the topic" },
+ "password": { "index": 9, "kind": "property", "displayName": "Password", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy password" },
+ "port": { "index": 10, "kind": "property", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 8090, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server port number" },
+ "replicationFactor": { "index": 11, "kind": "property", "displayName": "Replication Factor", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Short", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Replication factor for the topic" },
+ "streamId": { "index": 12, "kind": "property", "displayName": "Stream Id", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream identifier" },
+ "streamName": { "index": 13, "kind": "property", "displayName": "Stream Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream name" },
+ "autoCommit": { "index": 14, "kind": "property", "displayName": "Auto Commit", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Controls message acknowledgment behavior. When true, messages are automatically marked as processed after consumption. When false, enables manual offset management and allows setting a custom starting offset position" },
+ "bridgeErrorHandler": { "index": 15, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
+ "consumerGroupName": { "index": 16, "kind": "property", "displayName": "Consumer Group Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The name of the consumer group" },
+ "consumersCount": { "index": 17, "kind": "property", "displayName": "Consumers Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy consumers count" },
+ "partitionId": { "index": 18, "kind": "property", "displayName": "Partition Id", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer partition id" },
+ "pollBatchSize": { "index": 19, "kind": "property", "displayName": "Poll Batch Size", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "10", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer poll batch size" },
+ "pollingStrategy": { "index": 20, "kind": "property", "displayName": "Polling Strategy", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "next", "first", "last" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "next", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "shutdownTimeout": { "index": 21, "kind": "property", "displayName": "Shutdown Timeout", "group": "consumer", "label": "common,consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy shutdown timeout" },
+ "startingOffset": { "index": 22, "kind": "property", "displayName": "Starting Offset", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Defines the initial message offset position when autoCommit is disabled. Use 0 to start from the beginning of the stream, or specify a custom offset to resume from a particular point" },
+ "lazyStartProducer": { "index": 23, "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 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." },
+ "partitioning": { "index": 24, "kind": "property", "displayName": "Partitioning", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.iggy.message.Partitioning", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "balanced", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Partitioning strategy for message distribution" },
+ "autowiredEnabled": { "index": 25, "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 type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." },
+ "username": { "index": 26, "kind": "property", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy username" }
+ },
+ "properties": {
+ "topicName": { "index": 0, "kind": "path", "displayName": "Topic Name", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Name of the topic" },
+ "autoCreateStream": { "index": 1, "kind": "parameter", "displayName": "Auto Create Stream", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create stream if it does not exist" },
+ "autoCreateTopic": { "index": 2, "kind": "parameter", "displayName": "Auto Create Topic", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Whether to automatically create topic if it does not exist" },
+ "clientTransport": { "index": 3, "kind": "parameter", "displayName": "Client Transport", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "TCP", "HTTP" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TCP", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "compressionAlgorithm": { "index": 4, "kind": "parameter", "displayName": "Compression Algorithm", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.iggy.topic.CompressionAlgorithm", "enum": [ "None", "Gzip" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "None", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Compression algorithm for message payload" },
+ "host": { "index": 5, "kind": "parameter", "displayName": "Host", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "localhost", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server hostname or IP address" },
+ "maxTopicSize": { "index": 6, "kind": "parameter", "displayName": "Max Topic Size", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Maximum topic size in bytes (0 means unlimited)" },
+ "messageExpiry": { "index": 7, "kind": "parameter", "displayName": "Message Expiry", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Message expiry time in seconds (0 means no expiry)" },
+ "partitionsCount": { "index": 8, "kind": "parameter", "displayName": "Partitions Count", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Number of partitions for the topic" },
+ "password": { "index": 9, "kind": "parameter", "displayName": "Password", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy password" },
+ "port": { "index": 10, "kind": "parameter", "displayName": "Port", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 8090, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy server port number" },
+ "replicationFactor": { "index": 11, "kind": "parameter", "displayName": "Replication Factor", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Short", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Replication factor for the topic" },
+ "streamId": { "index": 12, "kind": "parameter", "displayName": "Stream Id", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream identifier" },
+ "streamName": { "index": 13, "kind": "parameter", "displayName": "Stream Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Stream name" },
+ "autoCommit": { "index": 14, "kind": "parameter", "displayName": "Auto Commit", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Controls message acknowledgment behavior. When true, messages are automatically marked as processed after consumption. When false, enables manual offset management and allows setting a custom starting offset position" },
+ "consumerGroupName": { "index": 15, "kind": "parameter", "displayName": "Consumer Group Name", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The name of the consumer group" },
+ "consumersCount": { "index": 16, "kind": "parameter", "displayName": "Consumers Count", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy consumers count" },
+ "partitionId": { "index": 17, "kind": "parameter", "displayName": "Partition Id", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer partition id" },
+ "pollBatchSize": { "index": 18, "kind": "parameter", "displayName": "Poll Batch Size", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "10", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "The consumer poll batch size" },
+ "pollingStrategy": { "index": 19, "kind": "parameter", "displayName": "Polling Strategy", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "next", "first", "last" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "next", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Polling strategy" },
+ "shutdownTimeout": { "index": 20, "kind": "parameter", "displayName": "Shutdown Timeout", "group": "consumer", "label": "common,consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 30000, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Camel Iggy shutdown timeout" },
+ "startingOffset": { "index": 21, "kind": "parameter", "displayName": "Starting Offset", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "0", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Defines the initial message offset position when autoCommit is disabled. Use 0 to start from the beginning of the stream, or specify a custom offset to resume from a particular point" },
+ "bridgeErrorHandler": { "index": 22, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
+ "exceptionHandler": { "index": 23, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." },
+ "exchangePattern": { "index": 24, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+ "partitioning": { "index": 25, "kind": "parameter", "displayName": "Partitioning", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.iggy.message.Partitioning", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "balanced", "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Partitioning strategy for message distribution" },
+ "lazyStartProducer": { "index": 26, "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 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." },
+ "username": { "index": 27, "kind": "parameter", "displayName": "Username", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.iggy.IggyConfiguration", "configurationField": "configuration", "description": "Iggy username" }
+ }
+}
diff --git a/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 0000000000000..cc137ae61499b
--- /dev/null
+++ b/components/camel-iggy/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=iggy
+groupId=org.apache.camel
+artifactId=camel-iggy
+version=4.14.0-SNAPSHOT
+projectName=Camel :: Iggy
+projectDescription=Camel Iggy component
diff --git a/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/component/iggy b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/component/iggy
new file mode 100644
index 0000000000000..c531eea74f1b9
--- /dev/null
+++ b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/component/iggy
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.iggy.IggyComponent
diff --git a/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/configurer/iggy-component b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/configurer/iggy-component
new file mode 100644
index 0000000000000..9473c04a1de10
--- /dev/null
+++ b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/configurer/iggy-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.iggy.IggyComponentConfigurer
diff --git a/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/configurer/iggy-endpoint b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/configurer/iggy-endpoint
new file mode 100644
index 0000000000000..8055f6b07b9fc
--- /dev/null
+++ b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/configurer/iggy-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.iggy.IggyEndpointConfigurer
diff --git a/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/urifactory/iggy-endpoint b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/urifactory/iggy-endpoint
new file mode 100644
index 0000000000000..717043fdec1b1
--- /dev/null
+++ b/components/camel-iggy/src/generated/resources/META-INF/services/org/apache/camel/urifactory/iggy-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.iggy.IggyEndpointUriFactory
diff --git a/components/camel-iggy/src/main/docs/iggy-component.adoc b/components/camel-iggy/src/main/docs/iggy-component.adoc
new file mode 100644
index 0000000000000..cd2d5c52aba58
--- /dev/null
+++ b/components/camel-iggy/src/main/docs/iggy-component.adoc
@@ -0,0 +1,98 @@
+= Iggy Component
+:doctitle: Iggy
+:shortname: iggy
+:artifactid: camel-iggy
+:description: Camel Iggy component
+:since: 4.14
+:supportlevel: Preview
+:tabs-sync-option:
+:component-header: Both producer and consumer are supported
+//Manually maintained attributes
+:camel-spring-boot-name: iggy
+
+*Since Camel {since}*
+
+*{component-header}*
+
+The Iggy component is used for communicating with
+https://iggy.incubator.apache.org/[Iggy] message broker.
+
+Maven users will need to add the following dependency to their `pom.xml`
+for this component.
+
+[source,xml]
+------------------------------------------------------------
+
+ org.apache.camel
+ camel-iggy
+ x.x.x
+
+
+------------------------------------------------------------
+
+== URI format
+
+---------------------------
+iggy:topic[?options]
+---------------------------
+
+
+// component-configure options: START
+
+// component-configure options: END
+
+// component options: START
+include::partial$component-configure-options.adoc[]
+include::partial$component-endpoint-options.adoc[]
+// component options: END
+
+// endpoint options: START
+
+// endpoint options: END
+
+// component headers: START
+include::partial$component-endpoint-headers.adoc[]
+// component headers: END
+
+== Iggy Headers
+
+The following headers are set on the exchange when consuming messages from Iggy:
+
+[width="100%",cols="2m,2m,5",options="header"]
+|===
+| Header | Type | Description
+| `CamelIggyMessageId` | `String` | The unique identifier of the message.
+| `CamelIggyMessageOffset` | `long` | The offset of the message in the partition.
+| `CamelIggyMessageTimestamp` | `long` | The timestamp of the message.
+| `CamelIggyMessageOriginTimestamp` | `long` | The original timestamp of the message.
+| `CamelIggyMessageChecksum` | `long` | The checksum of the message.
+| `CamelIggyMessageLength` | `int` | The length of the message.
+| `CamelIggyMessageSize` | `int` | The size of the message.
+|===
+
+== Examples
+
+=== Consuming messages from Iggy
+
+Here is a minimal route to read messages from an Iggy topic:
+
+[source,java]
+----
+from("iggy:my_topic?streamName=my_stream&consumerGroupName=my_consumer_group&host=localhost&port=8090")
+ .log("Message received from Iggy : ${body}")
+ .log(" with id ${headers[CamelIggyMessageId]}")
+ .log(" and offset ${headers[CamelIggyMessageOffset]}");
+----
+
+=== Producing messages to Iggy
+
+Here is a minimal route to produce messages to an Iggy topic:
+
+[source,java]
+----
+from("direct:start")
+ .setBody(constant("Message from Camel"))
+ .to("iggy:my_topic?streamName=my_stream&host=localhost&port=8090");
+----
+
+include::spring-boot:partial$starter.adoc[]
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyComponent.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyComponent.java
new file mode 100644
index 0000000000000..0381ddf7101b0
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyComponent.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.component.iggy;
+
+import java.util.Map;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+
+@Component("iggy")
+public class IggyComponent extends DefaultComponent {
+
+ @Metadata
+ private IggyConfiguration configuration = new IggyConfiguration();
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception {
+ IggyConfiguration config = configuration.copy();
+
+ IggyEndpoint endpoint = new IggyEndpoint(uri, this, config);
+ endpoint.setTopicName(remaining);
+ setProperties(endpoint, parameters);
+
+ return endpoint;
+ }
+
+ public IggyConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ /**
+ * Allows to pre-configure the Iggy component with common options that the endpoints will reuse.
+ */
+ public void setConfiguration(IggyConfiguration configuration) {
+ this.configuration = configuration;
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConfiguration.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConfiguration.java
new file mode 100644
index 0000000000000..32cca9cfd33b7
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConfiguration.java
@@ -0,0 +1,280 @@
+/*
+ * 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.iggy;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+import org.apache.iggy.message.Partitioning;
+import org.apache.iggy.topic.CompressionAlgorithm;
+
+@UriParams
+public class IggyConfiguration implements Cloneable {
+
+ @UriParam(defaultValue = "localhost", description = "Iggy server hostname or IP address")
+ private String host = "localhost";
+ @UriParam(defaultValue = "8090", description = "Iggy server port number")
+ private int port = 8090;
+ @UriParam(secret = true, label = "security", description = "Iggy username")
+ private String username;
+ @UriParam(secret = true, description = "Iggy password")
+ private String password;
+ @UriParam(defaultValue = "true",
+ description = "Whether to automatically create stream if it does not exist")
+ private boolean autoCreateStream = true;
+ @UriParam(defaultValue = "true",
+ description = "Whether to automatically create topic if it does not exist")
+ private boolean autoCreateTopic = true;
+ @UriParam(description = "Stream identifier")
+ private Long streamId;
+ @UriParam(description = "Stream name")
+ private String streamName;
+ @UriParam(defaultValue = "1", description = "Number of partitions for the topic")
+ private Long partitionsCount = 1L;
+ @UriParam(defaultValue = "None", enums = "None,Gzip",
+ description = "Compression algorithm for message payload")
+ private CompressionAlgorithm compressionAlgorithm = CompressionAlgorithm.None;
+ @UriParam(defaultValue = "0", description = "Message expiry time in seconds (0 means no expiry)")
+ private Long messageExpiry = 0L;
+ @UriParam(defaultValue = "0", description = "Maximum topic size in bytes (0 means unlimited)")
+ private Long maxTopicSize = 0L;
+ @UriParam(description = "Replication factor for the topic")
+ private Short replicationFactor;
+ @UriParam(label = "producer", defaultValue = "balanced", description = "Partitioning strategy for message distribution")
+ private Partitioning partitioning = Partitioning.balanced();
+ @UriParam(label = "consumer", description = "The name of the consumer group")
+ private String consumerGroupName;
+ @UriParam(label = "consumer", description = "The consumer poll batch size", defaultValue = "10")
+ private Long pollBatchSize = 10L;
+ @UriParam(label = "consumer", description = "The consumer partition id")
+ private Long partitionId;
+ @UriParam(label = "consumer", defaultValue = "1", description = "Camel Iggy consumers count")
+ private int consumersCount = 1;
+ @UriParam(label = "common,consumer", defaultValue = "30000", description = "Camel Iggy shutdown timeout")
+ private int shutdownTimeout = 30000;
+ @UriParam(label = "consumer", defaultValue = "next", description = "Polling strategy", enums = "next,first,last")
+ private String pollingStrategy = "next";
+ @UriParam(defaultValue = "TCP", description = "Polling strategy", enums = "TCP,HTTP")
+ private String clientTransport = "TCP"; // There may be QUIC in the future
+ @UriParam(label = "consumer", defaultValue = "true",
+ description = "Controls message acknowledgment behavior. " +
+ "When true, messages are automatically marked as processed after consumption. " +
+ "When false, enables manual offset management and allows setting a custom starting offset position")
+ private boolean autoCommit = true;
+ @UriParam(label = "consumer", defaultValue = "0",
+ description = "Defines the initial message offset position when autoCommit is disabled. " +
+ "Use 0 to start from the beginning of the stream, or specify a custom offset to resume from a particular point")
+ private Long startingOffset;
+
+ public IggyConfiguration copy() {
+ try {
+ return (IggyConfiguration) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new RuntimeCamelException(e);
+ }
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * The hostname of the Iggy server.
+ */
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * The port of the Iggy server.
+ */
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ 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 isAutoCreateStream() {
+ return autoCreateStream;
+ }
+
+ public void setAutoCreateStream(boolean autoCreateStream) {
+ this.autoCreateStream = autoCreateStream;
+ }
+
+ public boolean isAutoCreateTopic() {
+ return autoCreateTopic;
+ }
+
+ public void setAutoCreateTopic(boolean autoCreateTopic) {
+ this.autoCreateTopic = autoCreateTopic;
+ }
+
+ public Long getStreamId() {
+ return streamId;
+ }
+
+ public void setStreamId(Long streamId) {
+ this.streamId = streamId;
+ }
+
+ public String getStreamName() {
+ return streamName;
+ }
+
+ public void setStreamName(String streamName) {
+ this.streamName = streamName;
+ }
+
+ public Long getPartitionsCount() {
+ return partitionsCount;
+ }
+
+ public void setPartitionsCount(Long partitionsCount) {
+ this.partitionsCount = partitionsCount;
+ }
+
+ public CompressionAlgorithm getCompressionAlgorithm() {
+ return compressionAlgorithm;
+ }
+
+ public void setCompressionAlgorithm(CompressionAlgorithm compressionAlgorithm) {
+ this.compressionAlgorithm = compressionAlgorithm;
+ }
+
+ public Long getMessageExpiry() {
+ return messageExpiry;
+ }
+
+ public void setMessageExpiry(Long messageExpiry) {
+ this.messageExpiry = messageExpiry;
+ }
+
+ public Long getMaxTopicSize() {
+ return maxTopicSize;
+ }
+
+ public void setMaxTopicSize(Long maxTopicSize) {
+ this.maxTopicSize = maxTopicSize;
+ }
+
+ public Short getReplicationFactor() {
+ return replicationFactor;
+ }
+
+ public void setReplicationFactor(Short replicationFactor) {
+ this.replicationFactor = replicationFactor;
+ }
+
+ public Partitioning getPartitioning() {
+ return partitioning;
+ }
+
+ public void setPartitioning(Partitioning partitioning) {
+ this.partitioning = partitioning;
+ }
+
+ public String getConsumerGroupName() {
+ return consumerGroupName;
+ }
+
+ public void setConsumerGroupName(String consumerGroupName) {
+ this.consumerGroupName = consumerGroupName;
+ }
+
+ public Long getPollBatchSize() {
+ return pollBatchSize;
+ }
+
+ public void setPollBatchSize(Long pollBatchSize) {
+ this.pollBatchSize = pollBatchSize;
+ }
+
+ public Long getPartitionId() {
+ return partitionId;
+ }
+
+ public void setPartitionId(Long partitionId) {
+ this.partitionId = partitionId;
+ }
+
+ public int getConsumersCount() {
+ return consumersCount;
+ }
+
+ public void setConsumersCount(int consumersCount) {
+ this.consumersCount = consumersCount;
+ }
+
+ public int getShutdownTimeout() {
+ return shutdownTimeout;
+ }
+
+ public void setShutdownTimeout(int shutdownTimeout) {
+ this.shutdownTimeout = shutdownTimeout;
+ }
+
+ public String getPollingStrategy() {
+ return pollingStrategy;
+ }
+
+ public void setPollingStrategy(String pollingStrategy) {
+ this.pollingStrategy = pollingStrategy;
+ }
+
+ public String getClientTransport() {
+ return clientTransport;
+ }
+
+ public void setClientTransport(String clientTransport) {
+ this.clientTransport = clientTransport;
+ }
+
+ public boolean isAutoCommit() {
+ return autoCommit;
+ }
+
+ public void setAutoCommit(boolean autoCommit) {
+ this.autoCommit = autoCommit;
+ }
+
+ public Long getStartingOffset() {
+ return startingOffset;
+ }
+
+ public void setStartingOffset(Long startingOffset) {
+ this.startingOffset = startingOffset;
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java
new file mode 100644
index 0000000000000..421c28913c694
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConstants.java
@@ -0,0 +1,34 @@
+/*
+ * 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.iggy;
+
+public final class IggyConstants {
+
+ public static final String MESSAGE_ID = "CamelIggyMessageId";
+ public static final String MESSAGE_OFFSET = "CamelIggyMessageOffset";
+ public static final String MESSAGE_TIMESTAMP = "CamelIggyMessageTimestamp";
+ public static final String MESSAGE_ORIGIN_TIMESTAMP = "CamelIggyMessageOriginTimestamp";
+ public static final String MESSAGE_CHECKSUM = "CamelIggyMessageChecksum";
+ public static final String MESSAGE_LENGTH = "CamelIggyMessageLength";
+ public static final String MESSAGE_SIZE = "CamelIggyMessageSize";
+ public static final String TOPIC_OVERRIDE = "CamelIggyTopicOverride";
+ public static final String STREAM_OVERRIDE = "CamelIggyStreamOverride";
+
+ private IggyConstants() {
+ // Constants class
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConsumer.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConsumer.java
new file mode 100644
index 0000000000000..f58883ab2e3a1
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyConsumer.java
@@ -0,0 +1,113 @@
+/*
+ * 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.iggy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.Processor;
+import org.apache.camel.component.iggy.client.IggyClientConnectionPool;
+import org.apache.camel.support.BridgeExceptionHandlerToErrorHandler;
+import org.apache.camel.support.DefaultConsumer;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IggyConsumer extends DefaultConsumer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IggyConsumer.class);
+ private final IggyEndpoint endpoint;
+ private IggyClientConnectionPool iggyClientConnectionPool;
+ private ExecutorService executor;
+ private final List tasks = new ArrayList<>();
+
+ public IggyConsumer(IggyEndpoint endpoint, Processor processor) {
+ super(endpoint, processor);
+ this.endpoint = endpoint;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ LOG.info("Starting Iggy consumer for stream {} and topic {}", endpoint.getConfiguration().getStreamId(),
+ endpoint.getTopicName());
+
+ iggyClientConnectionPool = new IggyClientConnectionPool(
+ endpoint.getConfiguration().getHost(),
+ endpoint.getConfiguration().getPort(),
+ endpoint.getConfiguration().getUsername(),
+ endpoint.getConfiguration().getPassword(),
+ endpoint.getConfiguration().getClientTransport());
+
+ IggyBaseClient client = iggyClientConnectionPool.borrowObject();
+ endpoint.initializeTopic(client);
+ endpoint.initializeConsumerGroup(client);
+ iggyClientConnectionPool.returnClient(client);
+
+ executor = endpoint.createExecutor();
+ BridgeExceptionHandlerToErrorHandler bridge = new BridgeExceptionHandlerToErrorHandler(this);
+
+ // For now, we'll just have one consumer task. This can be extended later if Iggy supports partitioned consumption.
+ // TODO Handle streams, once tehy will be implemented in the java client
+ IggyFetchRecords task = new IggyFetchRecords(
+ this,
+ endpoint,
+ endpoint.getConfiguration(),
+ iggyClientConnectionPool,
+ bridge);
+ executor.submit(task);
+ tasks.add(task);
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ LOG.info("Stopping Iggy consumer for stream {} and topic {}", endpoint.getConfiguration().getStreamId(),
+ endpoint.getTopicName());
+
+ if (executor != null) {
+ if (getEndpoint() != null && getEndpoint().getCamelContext() != null) {
+ for (IggyFetchRecords task : tasks) {
+ task.stop();
+ }
+
+ int timeout = endpoint.getConfiguration().getShutdownTimeout();
+ LOG.debug("Shutting down Iggy consumer worker threads with timeout {} millis", timeout);
+ getEndpoint().getCamelContext().getExecutorServiceManager().shutdownGraceful(executor, timeout);
+ } else {
+ executor.shutdown();
+
+ int timeout = endpoint.getConfiguration().getShutdownTimeout();
+ LOG.debug("Shutting down Iggy consumer worker threads with timeout {} millis", timeout);
+ if (!executor.awaitTermination(timeout, TimeUnit.MILLISECONDS)) {
+ LOG.warn("Shutting down Iggy {} consumer worker threads did not finish within {} millis",
+ tasks.size(), timeout);
+ }
+ }
+
+ if (!executor.isTerminated()) {
+ tasks.forEach(IggyFetchRecords::stop);
+ executor.shutdownNow();
+ }
+ }
+ tasks.clear();
+ executor = null;
+
+ super.doStop();
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java
new file mode 100644
index 0000000000000..ae32ac569ee08
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyEndpoint.java
@@ -0,0 +1,181 @@
+/*
+ * 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.iggy;
+
+import java.math.BigInteger;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+
+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.iggy.client.blocking.IggyBaseClient;
+import org.apache.iggy.consumergroup.ConsumerGroupDetails;
+import org.apache.iggy.identifier.ConsumerId;
+import org.apache.iggy.identifier.StreamId;
+import org.apache.iggy.identifier.TopicId;
+import org.apache.iggy.stream.StreamDetails;
+import org.apache.iggy.topic.TopicDetails;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static java.util.Optional.empty;
+
+@UriEndpoint(firstVersion = "4.14.0", scheme = "iggy", title = "Iggy", syntax = "iggy:topicName",
+ category = { Category.MESSAGING }, headersClass = IggyConstants.class)
+public class IggyEndpoint extends DefaultEndpoint {
+ private static final Logger LOG = LoggerFactory.getLogger(IggyEndpoint.class);
+
+ @UriParam
+ private IggyConfiguration configuration;
+ @UriPath(description = "Name of the topic")
+ @Metadata(required = true)
+ private String topicName;
+
+ public IggyEndpoint(String endpointUri, IggyComponent component, IggyConfiguration configuration) {
+ super(endpointUri, component);
+ this.configuration = configuration;
+ }
+
+ @Override
+ public Producer createProducer() throws Exception {
+ return new IggyProducer(this);
+ }
+
+ @Override
+ public Consumer createConsumer(Processor processor) throws Exception {
+ IggyConsumer consumer = new IggyConsumer(this, processor);
+ configureConsumer(consumer);
+ return consumer;
+ }
+
+ public void initializeTopic(IggyBaseClient client, String topicName, String streamName) throws Exception {
+ IggyConfiguration iggyConfiguration = getConfiguration();
+ Objects.requireNonNull(iggyConfiguration.getStreamName(), "The stream name is required");
+ String topic = topicName != null ? topicName : getTopicName();
+ String stream = streamName != null ? streamName : iggyConfiguration.getStreamName();
+
+ if (iggyConfiguration.isAutoCreateStream()) {
+ if (iggyConfiguration.getStreamId() != null) {
+ client.streams().getStream(StreamId.of(iggyConfiguration.getStreamId())).orElseGet(() -> {
+ LOG.debug("Creating stream with id {} and name {}", iggyConfiguration.getStreamId(),
+ iggyConfiguration.getStreamName());
+ StreamDetails streamDetails = client.streams().createStream(Optional.of(iggyConfiguration.getStreamId()),
+ iggyConfiguration.getStreamName());
+
+ LOG.debug("Stream created with details: {}", streamDetails.toString());
+
+ return streamDetails;
+ });
+ } else {
+ client.streams().getStream(StreamId.of(stream)).orElseGet(() -> {
+ LOG.debug("Creating stream with name {}", stream);
+ StreamDetails streamDetails = client.streams().createStream(empty(), stream);
+ LOG.debug("Stream created with details: {}", streamDetails.toString());
+
+ return streamDetails;
+ });
+ }
+
+ }
+
+ if (iggyConfiguration.isAutoCreateTopic()) {
+ client.topics()
+ .getTopic(StreamId.of(stream), TopicId.of(topic))
+ .orElseGet(() -> {
+ LOG.debug("Creating topic with name {}", topic);
+ TopicDetails topicDetails = client.topics().createTopic(StreamId.of(stream),
+ empty(),
+ iggyConfiguration.getPartitionsCount(),
+ iggyConfiguration.getCompressionAlgorithm(),
+ BigInteger.valueOf(iggyConfiguration.getMessageExpiry()),
+ BigInteger.valueOf(iggyConfiguration.getMaxTopicSize()),
+ Optional.ofNullable(iggyConfiguration.getReplicationFactor()),
+ topic);
+
+ LOG.debug("Topic created or retrieved with details: {}", topicDetails.toString());
+
+ return topicDetails;
+ });
+ }
+ }
+
+ public void initializeTopic(IggyBaseClient client) throws Exception {
+ initializeTopic(client, null, null);
+ }
+
+ public void initializeConsumerGroup(IggyBaseClient client) {
+ Objects.requireNonNull(getConfiguration().getConsumerGroupName(), "Consumer group name is required");
+
+ client.consumerGroups()
+ .getConsumerGroup(
+ StreamId.of(getConfiguration().getStreamName()),
+ TopicId.of(getTopicName()),
+ ConsumerId.of(getConfiguration().getConsumerGroupName()))
+ .orElseGet(() -> {
+ LOG.debug("Creating consumer group with name {}", configuration.getConsumerGroupName());
+
+ ConsumerGroupDetails consumerGroupDetails = client.consumerGroups().createConsumerGroup(
+ StreamId.of(getConfiguration().getStreamName()),
+ TopicId.of(getTopicName()),
+ empty(),
+ getConfiguration().getConsumerGroupName());
+
+ LOG.debug("Created consumer group {}", consumerGroupDetails);
+
+ return consumerGroupDetails;
+ });
+
+ client.consumerGroups().joinConsumerGroup(
+ StreamId.of(getConfiguration().getStreamName()),
+ TopicId.of(getTopicName()),
+ ConsumerId.of(getConfiguration().getConsumerGroupName()));
+
+ LOG.debug("The client joined the consumer group on the stream {}, topic {} and consumer {}",
+ getConfiguration().getStreamName(),
+ getTopicName(),
+ getConfiguration().getConsumerGroupName());
+ }
+
+ public ExecutorService createExecutor() {
+ return getCamelContext().getExecutorServiceManager().newFixedThreadPool(this,
+ "IggyConsumer[" + getTopicName() + "]", configuration.getConsumersCount());
+ }
+
+ public IggyConfiguration getConfiguration() {
+ return configuration;
+ }
+
+ public void setConfiguration(IggyConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+ public String getTopicName() {
+ return topicName;
+ }
+
+ public void setTopicName(String topicName) {
+ this.topicName = topicName;
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java
new file mode 100644
index 0000000000000..f9a97a7b27d59
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyFetchRecords.java
@@ -0,0 +1,178 @@
+/*
+ * 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.iggy;
+
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.iggy.client.IggyClientConnectionPool;
+import org.apache.camel.support.BridgeExceptionHandlerToErrorHandler;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+import org.apache.iggy.consumergroup.Consumer;
+import org.apache.iggy.identifier.ConsumerId;
+import org.apache.iggy.identifier.StreamId;
+import org.apache.iggy.identifier.TopicId;
+import org.apache.iggy.message.PolledMessages;
+import org.apache.iggy.message.PollingStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IggyFetchRecords implements Runnable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IggyFetchRecords.class);
+
+ private final IggyConsumer iggyConsumer;
+ private final IggyEndpoint endpoint;
+ private final IggyConfiguration configuration;
+ private final IggyClientConnectionPool iggyClientConnectionPool;
+ private final BridgeExceptionHandlerToErrorHandler bridgeExceptionHandlerToErrorHandler;
+
+ private volatile boolean running;
+ private final AtomicBoolean polling = new AtomicBoolean(false);
+ private BigInteger offset;
+
+ public IggyFetchRecords(IggyConsumer iggyConsumer, IggyEndpoint endpoint, IggyConfiguration configuration,
+ IggyClientConnectionPool iggyClientConnectionPool,
+ BridgeExceptionHandlerToErrorHandler bridgeExceptionHandlerToErrorHandler) {
+ this.iggyConsumer = iggyConsumer;
+ this.endpoint = endpoint;
+ this.configuration = configuration;
+ this.iggyClientConnectionPool = iggyClientConnectionPool;
+ this.bridgeExceptionHandlerToErrorHandler = bridgeExceptionHandlerToErrorHandler;
+ this.offset = configuration.getStartingOffset() == null ? null : BigInteger.valueOf(configuration.getStartingOffset());
+ }
+
+ @Override
+ public void run() {
+ running = true;
+ while (running) {
+ if (iggyConsumer.isSuspending() || iggyConsumer.isSuspended()) {
+ LOG.trace("Consumer is suspended. Skipping message polling.");
+ try {
+ Thread.sleep(1000); // Sleep for a bit to avoid busy-waiting
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ continue;
+ }
+
+ if (polling.compareAndSet(false, true)) {
+ try {
+ pollMessages();
+ } catch (Exception e) {
+ bridgeExceptionHandlerToErrorHandler.handleException(e);
+ } finally {
+ polling.set(false);
+ }
+ }
+ }
+ }
+
+ private void pollMessages() {
+ try {
+ StreamId streamId = StreamId.of(configuration.getStreamName());
+ TopicId topicId = TopicId.of(endpoint.getTopicName());
+ ConsumerId consumerId = ConsumerId.of(configuration.getConsumerGroupName());
+
+ PolledMessages polledMessages;
+ IggyBaseClient client = iggyClientConnectionPool.borrowObject();
+ if (configuration.isAutoCommit()) {
+ polledMessages = client.messages()
+ .pollMessages(streamId,
+ topicId,
+ Optional.ofNullable(configuration.getPartitionId()),
+ Consumer.group(consumerId),
+ resolvePollingStrategy(),
+ configuration.getPollBatchSize(),
+ configuration.isAutoCommit());
+ } else {
+ polledMessages = client.messages()
+ .pollMessages(streamId,
+ topicId,
+ Optional.ofNullable(configuration.getPartitionId()),
+ Consumer.group(consumerId),
+ PollingStrategy.offset(offset),
+ configuration.getPollBatchSize(),
+ false);
+
+ // Update offset
+ offset = offset.add(BigInteger.valueOf(polledMessages.count()));
+ }
+
+ iggyClientConnectionPool.returnClient(client);
+
+ LOG.debug("Fetched {} messages from partition {}, current offset {}",
+ polledMessages.count(),
+ polledMessages.partitionId(),
+ configuration.isAutoCommit() ? polledMessages.currentOffset() : offset);
+
+ for (org.apache.iggy.message.Message message : polledMessages.messages()) {
+ Exchange exchange = createExchange(message);
+ try {
+ iggyConsumer.getProcessor().process(exchange);
+ } catch (Exception e) {
+ bridgeExceptionHandlerToErrorHandler.handleException(e);
+ }
+ }
+ } catch (Exception e) {
+ bridgeExceptionHandlerToErrorHandler.handleException("Error polling messages from Iggy", e);
+ }
+ }
+
+ private PollingStrategy resolvePollingStrategy() {
+ switch (configuration.getPollingStrategy()) {
+ case "first":
+ return PollingStrategy.first();
+ case "last":
+ return PollingStrategy.last();
+ default:
+ return PollingStrategy.next();
+ }
+ }
+
+ private Exchange createExchange(org.apache.iggy.message.Message message) {
+ Exchange exchange = iggyConsumer.createExchange(true);
+
+ exchange.getIn().setBody(new String(message.payload())); // TODO is it ok?
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_ID, message.header().id());
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_OFFSET, message.header().offset());
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_ORIGIN_TIMESTAMP, message.header().originTimestamp());
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_TIMESTAMP, message.header().timestamp());
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_CHECKSUM, message.header().checksum());
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_LENGTH, message.header().payloadLength());
+ exchange.getIn().setHeader(IggyConstants.MESSAGE_SIZE, message.getSize());
+
+ message.userHeaders().ifPresent(userHeaders -> {
+ Map stringUserHeaders = userHeaders.entrySet().stream().collect(Collectors.toMap(
+ k -> k.getKey(),
+ hv -> hv.getValue().value() // TODO this way `HeaderKind kind` will be lost
+ ));
+
+ exchange.getIn().setHeaders(stringUserHeaders);
+ });
+
+ return exchange;
+ }
+
+ public void stop() {
+ running = false;
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java
new file mode 100644
index 0000000000000..81a20ce0a2bc7
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/IggyProducer.java
@@ -0,0 +1,138 @@
+/*
+ * 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.iggy;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.iggy.client.IggyClientConnectionPool;
+import org.apache.camel.support.DefaultAsyncProducer;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+import org.apache.iggy.identifier.StreamId;
+import org.apache.iggy.identifier.TopicId;
+import org.apache.iggy.message.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IggyProducer extends DefaultAsyncProducer {
+ private static final Logger LOG = LoggerFactory.getLogger(IggyProducer.class);
+
+ private final IggyEndpoint endpoint;
+ private IggyClientConnectionPool iggyClientConnectionPool;
+
+ public IggyProducer(IggyEndpoint endpoint) {
+ super(endpoint);
+ this.endpoint = endpoint;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ iggyClientConnectionPool = new IggyClientConnectionPool(
+ endpoint.getConfiguration().getHost(),
+ endpoint.getConfiguration().getPort(),
+ endpoint.getConfiguration().getUsername(),
+ endpoint.getConfiguration().getPassword(),
+ endpoint.getConfiguration().getClientTransport());
+
+ IggyBaseClient client = iggyClientConnectionPool.borrowObject();
+ endpoint.initializeTopic(client);
+ iggyClientConnectionPool.returnClient(client);
+ }
+
+ @Override
+ public boolean process(Exchange exchange, AsyncCallback callback) {
+ IggyConfiguration iggyConfiguration = endpoint.getConfiguration();
+
+ try {
+ Object body = exchange.getIn().getBody();
+
+ List messages;
+ if (body instanceof List bodyAsList) {
+ if (isListOfStrings(bodyAsList)) {
+ messages = (List) bodyAsList.stream()
+ .map(s -> Message.of((String) s))
+ .collect(Collectors.toList());
+ } else if (isListOfMessages(bodyAsList)) {
+ messages = bodyAsList;
+ } else {
+ throw new RuntimeCamelException(
+ String.format(
+ "Unsupported List body type: %s, only List or List are supported",
+ body.getClass()));
+ }
+ } else if (body instanceof Message bodyAsMessage) {
+ messages = Collections.singletonList(bodyAsMessage);
+ } else {
+ messages = Collections
+ .singletonList(Message.of(exchange.getContext().getTypeConverter().convertTo(String.class, body)));
+ }
+
+ // TODO Handle user header when they are implemented in the java client
+ /*
+ let message = IggyMessage::builder()
+ .payload(Bytes::from(json))
+ .user_headers(headers)
+ .build()
+ .unwrap();
+ */
+
+ IggyBaseClient client = iggyClientConnectionPool.borrowObject();
+
+ Optional topicOverride
+ = Optional.ofNullable(exchange.getMessage().getHeader(IggyConstants.TOPIC_OVERRIDE, String.class));
+ Optional streamOverride
+ = Optional.ofNullable(exchange.getMessage().getHeader(IggyConstants.STREAM_OVERRIDE, String.class));
+
+ String topic = topicOverride.orElse(endpoint.getTopicName());
+ String stream = streamOverride.orElse(iggyConfiguration.getStreamName());
+ if (topicOverride.isPresent() || streamOverride.isPresent()) {
+ endpoint.initializeTopic(client,
+ topic,
+ stream);
+ }
+
+ client.messages().sendMessages(
+ StreamId.of(stream),
+ TopicId.of(topic),
+ iggyConfiguration.getPartitioning(),
+ messages);
+
+ iggyClientConnectionPool.returnClient(client);
+ } catch (Exception e) {
+ exchange.setException(e);
+ }
+ callback.done(true);
+ return true;
+ }
+
+ private boolean isListOfStrings(List> list) {
+ return list != null &&
+ list.stream().allMatch(item -> item == null || item instanceof String);
+ }
+
+ private boolean isListOfMessages(List> list) {
+ return list != null &&
+ list.stream().allMatch(item -> item == null || item instanceof Message);
+ }
+
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/client/IggyClientConnectionPool.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/client/IggyClientConnectionPool.java
new file mode 100644
index 0000000000000..2387a2b9f93fe
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/client/IggyClientConnectionPool.java
@@ -0,0 +1,45 @@
+/*
+ * 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.iggy.client;
+
+import org.apache.commons.pool2.impl.GenericObjectPool;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+
+public class IggyClientConnectionPool {
+ private final GenericObjectPool pool;
+
+ public IggyClientConnectionPool(String host, int port, String username, String password, String transport) {
+ IggyClientFactory factory = new IggyClientFactory(host, port, username, password, transport);
+ this.pool = new GenericObjectPool<>(factory);
+ }
+
+ public IggyBaseClient borrowObject() throws Exception {
+ return pool.borrowObject();
+ }
+
+ public void returnClient(IggyBaseClient client) {
+ pool.returnObject(client);
+ }
+
+ public int getNumActive() {
+ return pool.getNumActive();
+ }
+
+ public int getNumIdle() {
+ return pool.getNumIdle();
+ }
+}
diff --git a/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/client/IggyClientFactory.java b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/client/IggyClientFactory.java
new file mode 100644
index 0000000000000..2177e7cf77172
--- /dev/null
+++ b/components/camel-iggy/src/main/java/org/apache/camel/component/iggy/client/IggyClientFactory.java
@@ -0,0 +1,71 @@
+/*
+ * 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.iggy.client;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.commons.pool2.BasePooledObjectFactory;
+import org.apache.commons.pool2.PooledObject;
+import org.apache.commons.pool2.impl.DefaultPooledObject;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+import org.apache.iggy.client.blocking.IggyClientBuilder;
+import org.apache.iggy.client.blocking.http.IggyHttpClient;
+import org.apache.iggy.client.blocking.tcp.IggyTcpClient;
+
+public class IggyClientFactory extends BasePooledObjectFactory {
+ private final String host;
+ private final int port;
+ private final String username;
+ private final String password;
+ private final String transport;
+
+ public IggyClientFactory(String host, int port, String username, String password, String transport) {
+ this.host = host;
+ this.port = port;
+ this.username = username;
+ this.password = password;
+ this.transport = transport;
+ }
+
+ @Override
+ public IggyBaseClient create() throws Exception {
+ IggyBaseClient iggyBaseClient = new IggyClientBuilder().withBaseClient(createClient()).build().getBaseClient();
+
+ loginIggyClient(iggyBaseClient);
+
+ return iggyBaseClient;
+ }
+
+ @Override
+ public PooledObject wrap(IggyBaseClient iggyBaseClient) {
+ return new DefaultPooledObject<>(iggyBaseClient);
+ }
+
+ private IggyBaseClient createClient() {
+ return switch (transport) {
+ case "HTTP" ->
+ new IggyHttpClient(String.format("http://%s:%d", host, port));
+ case "TCP" -> new IggyTcpClient(host, port);
+ default -> throw new RuntimeCamelException("Only HTTP or TCP transports are supported");
+ };
+ }
+
+ private void loginIggyClient(IggyBaseClient client) {
+ if (username != null) {
+ client.users().login(username, password);
+ }
+ }
+}
diff --git a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyComponentIT.java b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyComponentIT.java
new file mode 100644
index 0000000000000..71d40ddc5e234
--- /dev/null
+++ b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyComponentIT.java
@@ -0,0 +1,52 @@
+/*
+ * 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.iggy;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+public class IggyComponentIT extends IggyTestBase {
+
+ @Test
+ public void testComponent() throws Exception {
+ MockEndpoint mockEndpoint = contextExtension.getMockEndpoint("mock:result");
+ mockEndpoint.expectedBodiesReceived("Hello Iggy");
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", "Hello Iggy");
+
+ mockEndpoint.assertIsSatisfied();
+ }
+
+ protected RoutesBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .toF("iggy:%s?username=%s&password=%s&streamName=%s&host=%s&port=%d",
+ TOPIC, iggyService.username(), iggyService.password(), STREAM,
+ iggyService.host(), iggyService.port());
+
+ fromF("iggy:%s?username=%s&password=%s&streamName=%s&host=%s&port=%d&consumerGroupName=%s",
+ TOPIC, iggyService.username(), iggyService.password(), STREAM,
+ iggyService.host(), iggyService.port(), CONSUMER_GROUP)
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java
new file mode 100644
index 0000000000000..334aec6a4b729
--- /dev/null
+++ b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerIT.java
@@ -0,0 +1,101 @@
+/*
+ * 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.iggy;
+
+import java.util.Map;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class IggyConsumerIT extends IggyTestBase {
+
+ @Test
+ public void consumeOneMessage() throws InterruptedException {
+ String message = "Hello world";
+ MockEndpoint mockEndpoint = contextExtension.getMockEndpoint("mock:result");
+ mockEndpoint.expectedMessageCount(1);
+
+ sendMessage(message);
+
+ mockEndpoint.assertIsSatisfied();
+
+ Assertions.assertEquals(message, mockEndpoint.getExchanges().get(0).getMessage().getBody());
+ }
+
+ @Test
+ public void consumeMultipleMessages() throws InterruptedException {
+ int messages = 200;
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(messages);
+
+ for (int i = 0; i < messages; i++) {
+ sendMessage("First batch " + i);
+ }
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+
+ int nextBatch = 5;
+ contextExtension.getMockEndpoint("mock:result").reset();
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(nextBatch);
+
+ for (int i = 0; i < nextBatch; i++) {
+ sendMessage("Next batch " + i);
+ }
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+ }
+
+ @Test
+ public void checkHeaders() throws Exception {
+ String message = "Hello world";
+ MockEndpoint mockEndpoint = contextExtension.getMockEndpoint("mock:result");
+ mockEndpoint.expectedMessageCount(1);
+
+ sendMessage(message);
+
+ mockEndpoint.assertIsSatisfied();
+
+ Map headers = mockEndpoint.getExchanges().get(0).getMessage().getHeaders();
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_ID));
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_OFFSET));
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_ORIGIN_TIMESTAMP));
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_TIMESTAMP));
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_CHECKSUM));
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_LENGTH));
+ Assertions.assertNotNull(headers.get(IggyConstants.MESSAGE_SIZE));
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ fromF("iggy:%s?username=%s&password=%s&streamName=%s&host=%s&port=%d&consumerGroupName=%s",
+ TOPIC,
+ iggyService.username(),
+ iggyService.password(),
+ STREAM,
+ iggyService.host(),
+ iggyService.port(),
+ CONSUMER_GROUP)
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java
new file mode 100644
index 0000000000000..c106c1237fb7a
--- /dev/null
+++ b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyConsumerOffsetIT.java
@@ -0,0 +1,70 @@
+/*
+ * 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.iggy;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+public class IggyConsumerOffsetIT extends IggyTestBase {
+
+ int startingOffset = 5;
+
+ @Test
+ public void startConsumingFromAnOffsetAndSendMoreMessages() throws InterruptedException {
+ int messages = 10;
+ MockEndpoint mockEndpoint = contextExtension.getMockEndpoint("mock:result");
+ mockEndpoint.expectedMessageCount(messages - startingOffset);
+
+ for (int i = 0; i < messages; i++) {
+ sendMessage("Message " + i);
+ }
+
+ mockEndpoint.assertIsSatisfied();
+
+ // send more messages to check offset update
+ int newMessages = 20;
+ mockEndpoint.reset();
+ mockEndpoint.expectedMessageCount(newMessages);
+
+ for (int i = 0; i < newMessages; i++) {
+ sendMessage("Second Message " + i);
+ }
+
+ mockEndpoint.assertIsSatisfied();
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ fromF("iggy:%s?username=%s&password=%s&streamName=%s&host=%s&port=%d&consumerGroupName=%s&autoCommit=false&startingOffset=%d",
+ TOPIC,
+ iggyService.username(),
+ iggyService.password(),
+ STREAM,
+ iggyService.host(),
+ iggyService.port(),
+ CONSUMER_GROUP,
+ startingOffset)
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyProducerIT.java b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyProducerIT.java
new file mode 100644
index 0000000000000..02943d2c80b2f
--- /dev/null
+++ b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyProducerIT.java
@@ -0,0 +1,121 @@
+/*
+ * 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.iggy;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.iggy.message.Message;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class IggyProducerIT extends IggyTestBase {
+
+ @Test
+ public void testString() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", "Hello World");
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+ }
+
+ @Test
+ public void testListOfStrings() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", List.of("Hello", "World"));
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+ }
+
+ @Test
+ public void testListOfMessages() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", List.of(Message.of("Hello"), Message.of("World")));
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+ }
+
+ @Test
+ public void testMessage() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", Message.of("Hello World"));
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+ }
+
+ @Test
+ public void testBytes() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", "Hello World".getBytes());
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+ }
+
+ @Test
+ public void testComplexObject() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ record Character(String name) {
+ }
+
+ Map data = new HashMap();
+ data.put("test", new Character("pippo"));
+
+ contextExtension.getProducerTemplate().sendBody("direct:start", data);
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+
+ Assertions.assertThat(pollMessagesPayloadsAsString())
+ .containsAnyElementsOf(List.of("{test=Character[name=pippo]}"));
+ }
+
+ @Test
+ public void testStreamAndTopicOverride() throws Exception {
+ contextExtension.getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ contextExtension.getProducerTemplate().sendBodyAndHeaders("direct:start", "Hello World",
+ Map.of(IggyConstants.STREAM_OVERRIDE, "stream-override",
+ IggyConstants.TOPIC_OVERRIDE, "topic-override"));
+
+ contextExtension.getMockEndpoint("mock:result").assertIsSatisfied();
+
+ Assertions.assertThat(pollMessagesPayloadsAsStringFromCustomStreamTopic("stream-override", "topic-override"))
+ .containsAnyElementsOf(List.of("Hello World"));
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .toF("iggy:%s?username=%s&password=%s&streamName=%s&host=%s&port=%d",
+ TOPIC, iggyService.username(), iggyService.password(), STREAM,
+ iggyService.host(), iggyService.port())
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
new file mode 100644
index 0000000000000..055472856953e
--- /dev/null
+++ b/components/camel-iggy/src/test/java/org/apache/camel/component/iggy/IggyTestBase.java
@@ -0,0 +1,123 @@
+/*
+ * 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.iggy;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.test.infra.core.CamelContextExtension;
+import org.apache.camel.test.infra.core.DefaultCamelContextExtension;
+import org.apache.camel.test.infra.core.annotations.RouteFixture;
+import org.apache.camel.test.infra.iggy.services.IggyService;
+import org.apache.camel.test.infra.iggy.services.IggyServiceFactory;
+import org.apache.iggy.client.blocking.IggyBaseClient;
+import org.apache.iggy.client.blocking.tcp.IggyTcpClient;
+import org.apache.iggy.consumergroup.Consumer;
+import org.apache.iggy.identifier.ConsumerId;
+import org.apache.iggy.identifier.StreamId;
+import org.apache.iggy.identifier.TopicId;
+import org.apache.iggy.message.Message;
+import org.apache.iggy.message.Partitioning;
+import org.apache.iggy.message.PollingStrategy;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static java.util.Optional.empty;
+
+public abstract class IggyTestBase {
+
+ @Order(1)
+ @RegisterExtension
+ protected static IggyService iggyService = IggyServiceFactory.createService();
+
+ @Order(2)
+ @RegisterExtension
+ protected static CamelContextExtension contextExtension = new DefaultCamelContextExtension();
+
+ private static IggyBaseClient client;
+
+ protected static final String TOPIC = "test-topic";
+ protected static final String STREAM = "test-stream";
+ protected static final String CONSUMER_GROUP = "test-consumer-group";
+
+ @BeforeAll
+ public static void setup() {
+ client = new IggyTcpClient(iggyService.host(), iggyService.port());
+ client.users().login(iggyService.username(), iggyService.password());
+ }
+
+ @RouteFixture
+ public void createRouteBuilder(CamelContext context) throws Exception {
+ context.addRoutes(createRouteBuilder());
+ }
+
+ protected void sendMessage(String message) {
+ client.messages().sendMessages(
+ StreamId.of(STREAM),
+ TopicId.of(TOPIC),
+ Partitioning.balanced(),
+ Collections.singletonList(Message.of(message)));
+ }
+
+ protected Stream pollMessagesPayloadsAsStringFromCustomStreamTopic(String stream, String topic) {
+ return pollMessages(stream, topic).stream().map(message -> new String(message.payload()));
+ }
+
+ protected Stream pollMessagesPayloadsAsString() {
+ return pollMessages(null, null).stream().map(message -> new String(message.payload()));
+ }
+
+ protected List pollMessages(String stream, String topic) {
+ // Create consumer group if needed
+ stream = stream == null ? STREAM : stream;
+ topic = topic == null ? TOPIC : topic;
+ try {
+ client.consumerGroups().createConsumerGroup(
+ StreamId.of(stream),
+ TopicId.of(topic),
+ empty(),
+ CONSUMER_GROUP);
+ } catch (Exception e) {
+ // already created
+ }
+
+ client.consumerGroups().joinConsumerGroup(
+ StreamId.of(stream),
+ TopicId.of(topic),
+ ConsumerId.of(CONSUMER_GROUP));
+
+ List polledMessages = client.messages()
+ .pollMessages(
+ StreamId.of(stream),
+ TopicId.of(topic),
+ Optional.empty(),
+ Consumer.group(ConsumerId.of(CONSUMER_GROUP)),
+ PollingStrategy.next(),
+ 1000L, // for safety, not all the tests pollMessages
+ true)
+ .messages();
+
+ return polledMessages;
+ }
+
+ protected abstract RoutesBuilder createRouteBuilder() throws Exception;
+}
diff --git a/components/pom.xml b/components/pom.xml
index 21e62854a0c39..c6dbad867cbef 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -161,6 +161,7 @@
camel-ical
camel-iec60870
camel-ignite
+ camel-iggy
camel-infinispan
camel-influxdb
camel-influxdb2
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 bf628cfc0c8c6..832bc9647a9e2 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
@@ -155,6 +155,7 @@ hwcloud-smn
ibm-secrets-manager
iec60870-client
iec60870-server
+iggy
ignite-cache
ignite-compute
ignite-events
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 04cb4c4e4db94..4c71e23b24b1f 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
@@ -169,6 +169,7 @@ org.apache.camel.component.huaweicloud.smn.SimpleNotificationComponent=camel:hua
org.apache.camel.component.ibm.secrets.manager.IBMSecretsManagerComponent=camel:ibm-secrets-manager
org.apache.camel.component.iec60870.client.ClientComponent=camel:iec60870
org.apache.camel.component.iec60870.server.ServerComponent=camel:iec60870
+org.apache.camel.component.iggy.IggyComponent=camel:iggy
org.apache.camel.component.ignite.cache.IgniteCacheComponent=camel:ignite
org.apache.camel.component.ignite.compute.IgniteComputeComponent=camel:ignite
org.apache.camel.component.ignite.events.IgniteEventsComponent=camel:ignite
diff --git a/parent/pom.xml b/parent/pom.xml
index d9f265419040c..aaa1c1fb2bf27 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -239,6 +239,7 @@
2.0.22
4.1.1
77.1
+ 0.5.0
2.17.0
1.12.0
15.2.5.Final
@@ -1542,6 +1543,11 @@
camel-iec60870
${project.version}
+
+ org.apache.camel
+ camel-iggy
+ ${project.version}
+
org.apache.camel
camel-ignite
diff --git a/test-infra/camel-test-infra-iggy/pom.xml b/test-infra/camel-test-infra-iggy/pom.xml
new file mode 100644
index 0000000000000..f6a3eff92afce
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/pom.xml
@@ -0,0 +1,53 @@
+
+
+
+
+ camel-test-infra-parent
+ org.apache.camel
+ ../camel-test-infra-parent/pom.xml
+ 4.14.0-SNAPSHOT
+
+
+ 4.0.0
+
+ camel-test-infra-iggy
+ Camel :: Test Infra :: Iggy
+
+
+ false
+
+
+
+
+ org.apache.camel
+ camel-test-infra-common
+ ${project.version}
+ test-jar
+
+
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers-version}
+
+
+
+
+
diff --git a/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/common/IggyProperties.java b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/common/IggyProperties.java
new file mode 100644
index 0000000000000..ac3b052fb5378
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/common/IggyProperties.java
@@ -0,0 +1,34 @@
+/*
+ * 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.iggy.common;
+
+public final class IggyProperties {
+ public static final String IGGY_CONTAINER = "iggy.container";
+ public static final int DEFAULT_TCP_PORT = 8090;
+ public static final String DEFAULT_USERNAME = "iggy";
+ public static final String DEFAULT_PASSWORD = "Secret123!";
+
+ public static final String IGGY_SERVICE_HOST = "iggy.service.host";
+ public static final String IGGY_SERVICE_PORT = "iggy.service.port";
+ public static final String IGGY_SERVICE_USERNAME = "iggy.service.username";
+ public static final String IGGY_SERVICE_PASSWORD = "iggy.service.password";
+
+ private IggyProperties() {
+
+ }
+}
diff --git a/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyContainer.java b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyContainer.java
new file mode 100644
index 0000000000000..debddda2cc423
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyContainer.java
@@ -0,0 +1,52 @@
+/*
+ * 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.iggy.services;
+
+import org.apache.camel.test.infra.iggy.common.IggyProperties;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+
+public class IggyContainer extends GenericContainer {
+ public static final String CONTAINER_NAME = "iggy";
+
+ public IggyContainer(String imageName) {
+ super(DockerImageName.parse(imageName));
+ }
+
+ public static IggyContainer initContainer(String imageName, String networkAlias, boolean fixedPort) {
+ class TestInfraIggyContainer extends IggyContainer {
+ public TestInfraIggyContainer() {
+ super(imageName);
+ waitingFor(Wait.forListeningPort());
+
+ addEnv("IGGY_ROOT_USERNAME", IggyProperties.DEFAULT_USERNAME);
+ addEnv("IGGY_ROOT_PASSWORD", IggyProperties.DEFAULT_PASSWORD);
+
+ if (fixedPort) {
+ addFixedExposedPort(IggyProperties.DEFAULT_TCP_PORT, IggyProperties.DEFAULT_TCP_PORT);
+ } else {
+ withNetworkAliases(networkAlias)
+ .withExposedPorts(IggyProperties.DEFAULT_TCP_PORT);
+ }
+ }
+ }
+
+ return new TestInfraIggyContainer();
+ }
+}
diff --git a/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyInfraService.java b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyInfraService.java
new file mode 100644
index 0000000000000..43f3590b9a0ca
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyInfraService.java
@@ -0,0 +1,33 @@
+/*
+ * 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.iggy.services;
+
+import org.apache.camel.test.infra.common.services.InfrastructureService;
+
+/**
+ * Test infra service for Iggy
+ */
+public interface IggyInfraService extends InfrastructureService {
+
+ String host();
+
+ int port();
+
+ String username();
+
+ String password();
+}
diff --git a/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyLocalContainerInfraService.java b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyLocalContainerInfraService.java
new file mode 100644
index 0000000000000..2bd8f1c3f5b9b
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyLocalContainerInfraService.java
@@ -0,0 +1,93 @@
+/*
+ * 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.iggy.services;
+
+import org.apache.camel.spi.annotations.InfraService;
+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.apache.camel.test.infra.iggy.common.IggyProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@InfraService(service = IggyInfraService.class,
+ description = "Iggy distributed message streaming platform",
+ serviceAlias = { "iggy" })
+public class IggyLocalContainerInfraService implements IggyInfraService, ContainerService {
+ private static final Logger LOG = LoggerFactory.getLogger(IggyLocalContainerInfraService.class);
+
+ private final IggyContainer container;
+
+ public IggyLocalContainerInfraService() {
+ container = IggyContainer.initContainer(LocalPropertyResolver
+ .getProperty(IggyLocalContainerInfraService.class, IggyProperties.IGGY_CONTAINER), IggyContainer.CONTAINER_NAME,
+ ContainerEnvironmentUtil.isFixedPort(this.getClass()));
+ }
+
+ public IggyLocalContainerInfraService(String imageName) {
+ container = IggyContainer.initContainer(imageName, IggyContainer.CONTAINER_NAME,
+ ContainerEnvironmentUtil.isFixedPort(this.getClass()));
+ }
+
+ @Override
+ public void registerProperties() {
+ System.setProperty(IggyProperties.DEFAULT_USERNAME, username());
+ System.setProperty(IggyProperties.DEFAULT_PASSWORD, password());
+ System.setProperty(IggyProperties.IGGY_SERVICE_PORT, String.valueOf(port()));
+ System.setProperty(IggyProperties.IGGY_SERVICE_HOST, host());
+ }
+
+ @Override
+ public void initialize() {
+ LOG.info("Trying to start the Iggy container");
+ container.start();
+
+ registerProperties();
+ LOG.info("Iggy instance running at {}:{}", host(), port());
+ }
+
+ @Override
+ public void shutdown() {
+ LOG.info("Stopping the Iggy container");
+ container.stop();
+ }
+
+ @Override
+ public IggyContainer getContainer() {
+ return container;
+ }
+
+ @Override
+ public String host() {
+ return container.getHost();
+ }
+
+ @Override
+ public int port() {
+ return container.getMappedPort(IggyProperties.DEFAULT_TCP_PORT);
+ }
+
+ @Override
+ public String username() {
+ return IggyProperties.DEFAULT_USERNAME;
+ }
+
+ @Override
+ public String password() {
+ return IggyProperties.DEFAULT_PASSWORD;
+ }
+}
diff --git a/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyRemoteInfraService.java b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyRemoteInfraService.java
new file mode 100644
index 0000000000000..a2927814c94bd
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/main/java/org/apache/camel/test/infra/iggy/services/IggyRemoteInfraService.java
@@ -0,0 +1,64 @@
+/*
+ * 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.iggy.services;
+
+import org.apache.camel.test.infra.iggy.common.IggyProperties;
+
+public class IggyRemoteInfraService implements IggyInfraService {
+
+ @Override
+ public void registerProperties() {
+ // NO-OP
+ }
+
+ @Override
+ public void initialize() {
+ registerProperties();
+ }
+
+ @Override
+ public void shutdown() {
+ // NO-OP
+ }
+
+ @Override
+ public String host() {
+ return System.getProperty(IggyProperties.IGGY_SERVICE_HOST);
+ }
+
+ @Override
+ public int port() {
+ String port = System.getProperty(IggyProperties.IGGY_SERVICE_PORT);
+
+ if (port == null) {
+ return IggyProperties.DEFAULT_TCP_PORT;
+ }
+
+ return Integer.valueOf(port);
+ }
+
+ @Override
+ public String username() {
+ return System.getProperty(IggyProperties.IGGY_SERVICE_USERNAME);
+ }
+
+ @Override
+ public String password() {
+ return System.getProperty(IggyProperties.IGGY_SERVICE_PASSWORD);
+ }
+
+}
diff --git a/test-infra/camel-test-infra-iggy/src/main/resources/org/apache/camel/test/infra/iggy/services/container.properties b/test-infra/camel-test-infra-iggy/src/main/resources/org/apache/camel/test/infra/iggy/services/container.properties
new file mode 100644
index 0000000000000..8c920566f8f4e
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/main/resources/org/apache/camel/test/infra/iggy/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.
+## ---------------------------------------------------------------------------
+iggy.container=apache/iggy:edge
\ No newline at end of file
diff --git a/test-infra/camel-test-infra-iggy/src/test/java/org/apache/camel/test/infra/iggy/services/IggyService.java b/test-infra/camel-test-infra-iggy/src/test/java/org/apache/camel/test/infra/iggy/services/IggyService.java
new file mode 100644
index 0000000000000..4f2c794dd155d
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/test/java/org/apache/camel/test/infra/iggy/services/IggyService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.iggy.services;
+
+import org.apache.camel.test.infra.common.services.ContainerTestService;
+import org.apache.camel.test.infra.common.services.TestService;
+
+/**
+ * Test infra service for Iggy
+ */
+public interface IggyService extends TestService, IggyInfraService, ContainerTestService {
+}
diff --git a/test-infra/camel-test-infra-iggy/src/test/java/org/apache/camel/test/infra/iggy/services/IggyServiceFactory.java b/test-infra/camel-test-infra-iggy/src/test/java/org/apache/camel/test/infra/iggy/services/IggyServiceFactory.java
new file mode 100644
index 0000000000000..d093337a86950
--- /dev/null
+++ b/test-infra/camel-test-infra-iggy/src/test/java/org/apache/camel/test/infra/iggy/services/IggyServiceFactory.java
@@ -0,0 +1,42 @@
+/*
+ * 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.iggy.services;
+
+import org.apache.camel.test.infra.common.services.SimpleTestServiceBuilder;
+
+public final class IggyServiceFactory {
+ private IggyServiceFactory() {
+
+ }
+
+ public static SimpleTestServiceBuilder builder() {
+ return new SimpleTestServiceBuilder<>("iggy");
+ }
+
+ public static IggyService createService() {
+ return builder()
+ .addLocalMapping(IggyLocalContainerService::new)
+ .addRemoteMapping(IggyRemoteService::new)
+ .build();
+ }
+
+ public static class IggyRemoteService extends IggyRemoteInfraService implements IggyService {
+ }
+
+ public static class IggyLocalContainerService extends IggyLocalContainerInfraService implements IggyService {
+ }
+}
diff --git a/test-infra/pom.xml b/test-infra/pom.xml
index b6b885ed7b938..9138ff33c8920 100644
--- a/test-infra/pom.xml
+++ b/test-infra/pom.xml
@@ -94,6 +94,7 @@
camel-test-infra-neo4j
camel-test-infra-weaviate
camel-test-infra-ibmmq
+ camel-test-infra-iggy
camel-test-infra-all