You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2025/09/24 12:44:54 UTC
(camel) branch CAMEL-22445 created (now 0f0db341fb4)
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a change to branch CAMEL-22445
in repository https://gitbox.apache.org/repos/asf/camel.git
at 0f0db341fb4 Camel-AWS2-S3 Streaming Upload: Implement timestamp-based file grouping for AWS S3 streaming upload
This branch includes the following new commits:
new 0f0db341fb4 Camel-AWS2-S3 Streaming Upload: Implement timestamp-based file grouping for AWS S3 streaming upload
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(camel) 01/01: Camel-AWS2-S3 Streaming Upload: Implement timestamp-based file grouping for AWS S3 streaming upload
Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch CAMEL-22445
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 0f0db341fb4863dd37982b896fb6d88ef78fb47e
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Sep 24 10:57:29 2025 +0200
Camel-AWS2-S3 Streaming Upload: Implement timestamp-based file grouping for AWS S3 streaming upload
Signed-off-by: Andrea Cosentino <an...@gmail.com>
---
.../apache/camel/catalog/components/aws2-s3.json | 114 +++---
.../aws2/s3/AWS2S3ComponentConfigurer.java | 18 +
.../aws2/s3/AWS2S3EndpointConfigurer.java | 18 +
.../aws2/s3/AWS2S3EndpointUriFactory.java | 5 +-
.../apache/camel/component/aws2/s3/aws2-s3.json | 114 +++---
.../src/main/docs/aws2-s3-component.adoc | 102 ++++++
.../component/aws2/s3/AWS2S3Configuration.java | 42 +++
.../aws2/s3/stream/AWS2S3StreamUploadProducer.java | 206 +++++++++++
...S3StreamUploadTimestampGroupingEdgeCasesIT.java | 333 ++++++++++++++++++
.../S3StreamUploadTimestampGroupingIT.java | 381 +++++++++++++++++++++
.../AWS2S3StreamUploadProducerTimestampTest.java | 282 +++++++++++++++
.../dsl/Aws2S3ComponentBuilderFactory.java | 59 ++++
.../endpoint/dsl/AWS2S3EndpointBuilderFactory.java | 84 +++++
13 files changed, 1649 insertions(+), 109 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json
index e2945ec0b23..e7860a73683 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-s3.json
@@ -64,27 +64,30 @@
"storageClass": { "index": 37, "kind": "property", "displayName": "Storage Class", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The storage class to set in the com.amazonaws.services.s3.model.PutObjectRequest request." },
"streamingUploadMode": { "index": 38, "kind": "property", "displayName": "Streaming Upload Mode", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "When stream mode is true, the upload to bucket will be done in streaming" },
"streamingUploadTimeout": { "index": 39, "kind": "property", "displayName": "Streaming Upload Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "While streaming upload mode is true, this option set the timeout to complete upload" },
- "awsKMSKeyId": { "index": 40, "kind": "property", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
- "conditionalWritesEnabled": { "index": 41, "kind": "property", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object key [...]
- "useAwsKMS": { "index": 42, "kind": "property", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
- "useCustomerKey": { "index": 43, "kind": "property", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
- "useSSES3": { "index": 44, "kind": "property", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
- "amazonS3Client": { "index": 45, "kind": "property", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazon [...]
- "amazonS3Presigner": { "index": 46, "kind": "property", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request, [...]
- "autowiredEnabled": { "index": 47, "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 [...]
- "healthCheckConsumerEnabled": { "index": 48, "kind": "property", "displayName": "Health Check Consumer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all consumer based health checks from this component" },
- "healthCheckProducerEnabled": { "index": 49, "kind": "property", "displayName": "Health Check Producer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all producer based health checks from this component. Notice: Camel has by default disabled all producer based health-checks. You can turn on produce [...]
- "proxyHost": { "index": 50, "kind": "property", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
- "proxyPort": { "index": 51, "kind": "property", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
- "proxyProtocol": { "index": 52, "kind": "property", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when i [...]
- "accessKey": { "index": 53, "kind": "property", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
- "profileCredentialsName": { "index": 54, "kind": "property", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
- "secretKey": { "index": 55, "kind": "property", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
- "sessionToken": { "index": 56, "kind": "property", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
- "trustAllCertificates": { "index": 57, "kind": "property", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
- "useDefaultCredentialsProvider": { "index": 58, "kind": "property", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
- "useProfileCredentialsProvider": { "index": 59, "kind": "property", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
- "useSessionCredentials": { "index": 60, "kind": "property", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials. [...]
+ "timestampGroupingEnabled": { "index": 40, "kind": "property", "displayName": "Timestamp Grouping Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Enable timestamp-based grouping of messages into time windows [...]
+ "timestampHeaderName": { "index": 41, "kind": "property", "displayName": "Timestamp Header Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CamelMessageTimestamp", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The name of the message header containing the [...]
+ "timestampWindowSizeMillis": { "index": 42, "kind": "property", "displayName": "Timestamp Window Size Millis", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The size of the time window in milliseconds for timestamp-ba [...]
+ "awsKMSKeyId": { "index": 43, "kind": "property", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
+ "conditionalWritesEnabled": { "index": 44, "kind": "property", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object key [...]
+ "useAwsKMS": { "index": 45, "kind": "property", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
+ "useCustomerKey": { "index": 46, "kind": "property", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
+ "useSSES3": { "index": 47, "kind": "property", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
+ "amazonS3Client": { "index": 48, "kind": "property", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazon [...]
+ "amazonS3Presigner": { "index": 49, "kind": "property", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request, [...]
+ "autowiredEnabled": { "index": 50, "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 [...]
+ "healthCheckConsumerEnabled": { "index": 51, "kind": "property", "displayName": "Health Check Consumer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all consumer based health checks from this component" },
+ "healthCheckProducerEnabled": { "index": 52, "kind": "property", "displayName": "Health Check Producer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all producer based health checks from this component. Notice: Camel has by default disabled all producer based health-checks. You can turn on produce [...]
+ "proxyHost": { "index": 53, "kind": "property", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
+ "proxyPort": { "index": 54, "kind": "property", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
+ "proxyProtocol": { "index": 55, "kind": "property", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when i [...]
+ "accessKey": { "index": 56, "kind": "property", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+ "profileCredentialsName": { "index": 57, "kind": "property", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
+ "secretKey": { "index": 58, "kind": "property", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
+ "sessionToken": { "index": 59, "kind": "property", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
+ "trustAllCertificates": { "index": 60, "kind": "property", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
+ "useDefaultCredentialsProvider": { "index": 61, "kind": "property", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
+ "useProfileCredentialsProvider": { "index": 62, "kind": "property", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
+ "useSessionCredentials": { "index": 63, "kind": "property", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials. [...]
},
"headers": {
"CamelAwsS3BucketName": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The bucket Name (can be dynamic using the simple language in the producer) which this object will be stored or which will be used for the current operation or in which this object is contained.", "constantName": "org.apache.camel.component.aws [...]
@@ -173,38 +176,41 @@
"storageClass": { "index": 43, "kind": "parameter", "displayName": "Storage Class", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The storage class to set in the com.amazonaws.services.s3.model.PutObjectRequest request." },
"streamingUploadMode": { "index": 44, "kind": "parameter", "displayName": "Streaming Upload Mode", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "When stream mode is true, the upload to bucket will be done in streaming" },
"streamingUploadTimeout": { "index": 45, "kind": "parameter", "displayName": "Streaming Upload Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "While streaming upload mode is true, this option set the timeout to complete upload" },
- "awsKMSKeyId": { "index": 46, "kind": "parameter", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
- "conditionalWritesEnabled": { "index": 47, "kind": "parameter", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object ke [...]
- "lazyStartProducer": { "index": 48, "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 produ [...]
- "useAwsKMS": { "index": 49, "kind": "parameter", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
- "useCustomerKey": { "index": 50, "kind": "parameter", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
- "useSSES3": { "index": 51, "kind": "parameter", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
- "amazonS3Client": { "index": 52, "kind": "parameter", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazo [...]
- "amazonS3Presigner": { "index": 53, "kind": "parameter", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request [...]
- "proxyHost": { "index": 54, "kind": "parameter", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
- "proxyPort": { "index": 55, "kind": "parameter", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
- "proxyProtocol": { "index": 56, "kind": "parameter", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when [...]
- "backoffErrorThreshold": { "index": 57, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
- "backoffIdleThreshold": { "index": 58, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." },
- "backoffMultiplier": { "index": 59, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is h [...]
- "delay": { "index": 60, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." },
- "greedy": { "index": 61, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." },
- "initialDelay": { "index": 62, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." },
- "repeatCount": { "index": 63, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." },
- "runLoggingLevel": { "index": 64, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the log [...]
- "scheduledExecutorService": { "index": 65, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." },
- "scheduler": { "index": 66, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" },
- "schedulerProperties": { "index": 67, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This i [...]
- "startScheduler": { "index": 68, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." },
- "timeUnit": { "index": 69, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." },
- "useFixedDelay": { "index": 70, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." },
- "accessKey": { "index": 71, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
- "profileCredentialsName": { "index": 72, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
- "secretKey": { "index": 73, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
- "sessionToken": { "index": 74, "kind": "parameter", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
- "trustAllCertificates": { "index": 75, "kind": "parameter", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
- "useDefaultCredentialsProvider": { "index": 76, "kind": "parameter", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
- "useProfileCredentialsProvider": { "index": 77, "kind": "parameter", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
- "useSessionCredentials": { "index": 78, "kind": "parameter", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials [...]
+ "timestampGroupingEnabled": { "index": 46, "kind": "parameter", "displayName": "Timestamp Grouping Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Enable timestamp-based grouping of messages into time window [...]
+ "timestampHeaderName": { "index": 47, "kind": "parameter", "displayName": "Timestamp Header Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CamelMessageTimestamp", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The name of the message header containing th [...]
+ "timestampWindowSizeMillis": { "index": 48, "kind": "parameter", "displayName": "Timestamp Window Size Millis", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The size of the time window in milliseconds for timestamp-b [...]
+ "awsKMSKeyId": { "index": 49, "kind": "parameter", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
+ "conditionalWritesEnabled": { "index": 50, "kind": "parameter", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object ke [...]
+ "lazyStartProducer": { "index": 51, "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 produ [...]
+ "useAwsKMS": { "index": 52, "kind": "parameter", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
+ "useCustomerKey": { "index": 53, "kind": "parameter", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
+ "useSSES3": { "index": 54, "kind": "parameter", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
+ "amazonS3Client": { "index": 55, "kind": "parameter", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazo [...]
+ "amazonS3Presigner": { "index": 56, "kind": "parameter", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request [...]
+ "proxyHost": { "index": 57, "kind": "parameter", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
+ "proxyPort": { "index": 58, "kind": "parameter", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
+ "proxyProtocol": { "index": 59, "kind": "parameter", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when [...]
+ "backoffErrorThreshold": { "index": 60, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
+ "backoffIdleThreshold": { "index": 61, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." },
+ "backoffMultiplier": { "index": 62, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is h [...]
+ "delay": { "index": 63, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." },
+ "greedy": { "index": 64, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." },
+ "initialDelay": { "index": 65, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." },
+ "repeatCount": { "index": 66, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." },
+ "runLoggingLevel": { "index": 67, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the log [...]
+ "scheduledExecutorService": { "index": 68, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." },
+ "scheduler": { "index": 69, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" },
+ "schedulerProperties": { "index": 70, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This i [...]
+ "startScheduler": { "index": 71, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." },
+ "timeUnit": { "index": 72, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." },
+ "useFixedDelay": { "index": 73, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." },
+ "accessKey": { "index": 74, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+ "profileCredentialsName": { "index": 75, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
+ "secretKey": { "index": 76, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
+ "sessionToken": { "index": 77, "kind": "parameter", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
+ "trustAllCertificates": { "index": 78, "kind": "parameter", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
+ "useDefaultCredentialsProvider": { "index": 79, "kind": "parameter", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
+ "useProfileCredentialsProvider": { "index": 80, "kind": "parameter", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
+ "useSessionCredentials": { "index": 81, "kind": "parameter", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials [...]
}
}
diff --git a/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3ComponentConfigurer.java b/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3ComponentConfigurer.java
index ee31356e19b..3506417fe0f 100644
--- a/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3ComponentConfigurer.java
+++ b/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3ComponentConfigurer.java
@@ -130,6 +130,12 @@ public class AWS2S3ComponentConfigurer extends PropertyConfigurerSupport impleme
case "streamingUploadMode": getOrCreateConfiguration(target).setStreamingUploadMode(property(camelContext, boolean.class, value)); return true;
case "streaminguploadtimeout":
case "streamingUploadTimeout": getOrCreateConfiguration(target).setStreamingUploadTimeout(property(camelContext, long.class, value)); return true;
+ case "timestampgroupingenabled":
+ case "timestampGroupingEnabled": getOrCreateConfiguration(target).setTimestampGroupingEnabled(property(camelContext, boolean.class, value)); return true;
+ case "timestampheadername":
+ case "timestampHeaderName": getOrCreateConfiguration(target).setTimestampHeaderName(property(camelContext, java.lang.String.class, value)); return true;
+ case "timestampwindowsizemillis":
+ case "timestampWindowSizeMillis": getOrCreateConfiguration(target).setTimestampWindowSizeMillis(property(camelContext, long.class, value)); return true;
case "trustallcertificates":
case "trustAllCertificates": getOrCreateConfiguration(target).setTrustAllCertificates(property(camelContext, boolean.class, value)); return true;
case "uriendpointoverride":
@@ -258,6 +264,12 @@ public class AWS2S3ComponentConfigurer extends PropertyConfigurerSupport impleme
case "streamingUploadMode": return boolean.class;
case "streaminguploadtimeout":
case "streamingUploadTimeout": return long.class;
+ case "timestampgroupingenabled":
+ case "timestampGroupingEnabled": return boolean.class;
+ case "timestampheadername":
+ case "timestampHeaderName": return java.lang.String.class;
+ case "timestampwindowsizemillis":
+ case "timestampWindowSizeMillis": return long.class;
case "trustallcertificates":
case "trustAllCertificates": return boolean.class;
case "uriendpointoverride":
@@ -382,6 +394,12 @@ public class AWS2S3ComponentConfigurer extends PropertyConfigurerSupport impleme
case "streamingUploadMode": return getOrCreateConfiguration(target).isStreamingUploadMode();
case "streaminguploadtimeout":
case "streamingUploadTimeout": return getOrCreateConfiguration(target).getStreamingUploadTimeout();
+ case "timestampgroupingenabled":
+ case "timestampGroupingEnabled": return getOrCreateConfiguration(target).isTimestampGroupingEnabled();
+ case "timestampheadername":
+ case "timestampHeaderName": return getOrCreateConfiguration(target).getTimestampHeaderName();
+ case "timestampwindowsizemillis":
+ case "timestampWindowSizeMillis": return getOrCreateConfiguration(target).getTimestampWindowSizeMillis();
case "trustallcertificates":
case "trustAllCertificates": return getOrCreateConfiguration(target).isTrustAllCertificates();
case "uriendpointoverride":
diff --git a/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointConfigurer.java b/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointConfigurer.java
index c3f585cd840..7e8d372807c 100644
--- a/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointConfigurer.java
+++ b/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointConfigurer.java
@@ -153,6 +153,12 @@ public class AWS2S3EndpointConfigurer extends PropertyConfigurerSupport implemen
case "streamingUploadTimeout": target.getConfiguration().setStreamingUploadTimeout(property(camelContext, long.class, value)); return true;
case "timeunit":
case "timeUnit": target.setTimeUnit(property(camelContext, java.util.concurrent.TimeUnit.class, value)); return true;
+ case "timestampgroupingenabled":
+ case "timestampGroupingEnabled": target.getConfiguration().setTimestampGroupingEnabled(property(camelContext, boolean.class, value)); return true;
+ case "timestampheadername":
+ case "timestampHeaderName": target.getConfiguration().setTimestampHeaderName(property(camelContext, java.lang.String.class, value)); return true;
+ case "timestampwindowsizemillis":
+ case "timestampWindowSizeMillis": target.getConfiguration().setTimestampWindowSizeMillis(property(camelContext, long.class, value)); return true;
case "trustallcertificates":
case "trustAllCertificates": target.getConfiguration().setTrustAllCertificates(property(camelContext, boolean.class, value)); return true;
case "uriendpointoverride":
@@ -313,6 +319,12 @@ public class AWS2S3EndpointConfigurer extends PropertyConfigurerSupport implemen
case "streamingUploadTimeout": return long.class;
case "timeunit":
case "timeUnit": return java.util.concurrent.TimeUnit.class;
+ case "timestampgroupingenabled":
+ case "timestampGroupingEnabled": return boolean.class;
+ case "timestampheadername":
+ case "timestampHeaderName": return java.lang.String.class;
+ case "timestampwindowsizemillis":
+ case "timestampWindowSizeMillis": return long.class;
case "trustallcertificates":
case "trustAllCertificates": return boolean.class;
case "uriendpointoverride":
@@ -469,6 +481,12 @@ public class AWS2S3EndpointConfigurer extends PropertyConfigurerSupport implemen
case "streamingUploadTimeout": return target.getConfiguration().getStreamingUploadTimeout();
case "timeunit":
case "timeUnit": return target.getTimeUnit();
+ case "timestampgroupingenabled":
+ case "timestampGroupingEnabled": return target.getConfiguration().isTimestampGroupingEnabled();
+ case "timestampheadername":
+ case "timestampHeaderName": return target.getConfiguration().getTimestampHeaderName();
+ case "timestampwindowsizemillis":
+ case "timestampWindowSizeMillis": return target.getConfiguration().getTimestampWindowSizeMillis();
case "trustallcertificates":
case "trustAllCertificates": return target.getConfiguration().isTrustAllCertificates();
case "uriendpointoverride":
diff --git a/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointUriFactory.java b/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointUriFactory.java
index 96482e2c710..825e8cc1d57 100644
--- a/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointUriFactory.java
+++ b/components/camel-aws/camel-aws2-s3/src/generated/java/org/apache/camel/component/aws2/s3/AWS2S3EndpointUriFactory.java
@@ -23,7 +23,7 @@ public class AWS2S3EndpointUriFactory extends org.apache.camel.support.component
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(79);
+ Set<String> props = new HashSet<>(82);
props.add("accessKey");
props.add("amazonS3Client");
props.add("amazonS3Presigner");
@@ -94,6 +94,9 @@ public class AWS2S3EndpointUriFactory extends org.apache.camel.support.component
props.add("streamingUploadMode");
props.add("streamingUploadTimeout");
props.add("timeUnit");
+ props.add("timestampGroupingEnabled");
+ props.add("timestampHeaderName");
+ props.add("timestampWindowSizeMillis");
props.add("trustAllCertificates");
props.add("uriEndpointOverride");
props.add("useAwsKMS");
diff --git a/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json b/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json
index e2945ec0b23..e7860a73683 100644
--- a/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json
+++ b/components/camel-aws/camel-aws2-s3/src/generated/resources/META-INF/org/apache/camel/component/aws2/s3/aws2-s3.json
@@ -64,27 +64,30 @@
"storageClass": { "index": 37, "kind": "property", "displayName": "Storage Class", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The storage class to set in the com.amazonaws.services.s3.model.PutObjectRequest request." },
"streamingUploadMode": { "index": 38, "kind": "property", "displayName": "Streaming Upload Mode", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "When stream mode is true, the upload to bucket will be done in streaming" },
"streamingUploadTimeout": { "index": 39, "kind": "property", "displayName": "Streaming Upload Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "While streaming upload mode is true, this option set the timeout to complete upload" },
- "awsKMSKeyId": { "index": 40, "kind": "property", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
- "conditionalWritesEnabled": { "index": 41, "kind": "property", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object key [...]
- "useAwsKMS": { "index": 42, "kind": "property", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
- "useCustomerKey": { "index": 43, "kind": "property", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
- "useSSES3": { "index": 44, "kind": "property", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
- "amazonS3Client": { "index": 45, "kind": "property", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazon [...]
- "amazonS3Presigner": { "index": 46, "kind": "property", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request, [...]
- "autowiredEnabled": { "index": 47, "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 [...]
- "healthCheckConsumerEnabled": { "index": 48, "kind": "property", "displayName": "Health Check Consumer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all consumer based health checks from this component" },
- "healthCheckProducerEnabled": { "index": 49, "kind": "property", "displayName": "Health Check Producer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all producer based health checks from this component. Notice: Camel has by default disabled all producer based health-checks. You can turn on produce [...]
- "proxyHost": { "index": 50, "kind": "property", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
- "proxyPort": { "index": 51, "kind": "property", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
- "proxyProtocol": { "index": 52, "kind": "property", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when i [...]
- "accessKey": { "index": 53, "kind": "property", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
- "profileCredentialsName": { "index": 54, "kind": "property", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
- "secretKey": { "index": 55, "kind": "property", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
- "sessionToken": { "index": 56, "kind": "property", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
- "trustAllCertificates": { "index": 57, "kind": "property", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
- "useDefaultCredentialsProvider": { "index": 58, "kind": "property", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
- "useProfileCredentialsProvider": { "index": 59, "kind": "property", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
- "useSessionCredentials": { "index": 60, "kind": "property", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials. [...]
+ "timestampGroupingEnabled": { "index": 40, "kind": "property", "displayName": "Timestamp Grouping Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Enable timestamp-based grouping of messages into time windows [...]
+ "timestampHeaderName": { "index": 41, "kind": "property", "displayName": "Timestamp Header Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CamelMessageTimestamp", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The name of the message header containing the [...]
+ "timestampWindowSizeMillis": { "index": 42, "kind": "property", "displayName": "Timestamp Window Size Millis", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The size of the time window in milliseconds for timestamp-ba [...]
+ "awsKMSKeyId": { "index": 43, "kind": "property", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
+ "conditionalWritesEnabled": { "index": 44, "kind": "property", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object key [...]
+ "useAwsKMS": { "index": 45, "kind": "property", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
+ "useCustomerKey": { "index": 46, "kind": "property", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
+ "useSSES3": { "index": 47, "kind": "property", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
+ "amazonS3Client": { "index": 48, "kind": "property", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazon [...]
+ "amazonS3Presigner": { "index": 49, "kind": "property", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request, [...]
+ "autowiredEnabled": { "index": 50, "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 [...]
+ "healthCheckConsumerEnabled": { "index": 51, "kind": "property", "displayName": "Health Check Consumer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all consumer based health checks from this component" },
+ "healthCheckProducerEnabled": { "index": 52, "kind": "property", "displayName": "Health Check Producer Enabled", "group": "health", "label": "health", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Used for enabling or disabling all producer based health checks from this component. Notice: Camel has by default disabled all producer based health-checks. You can turn on produce [...]
+ "proxyHost": { "index": 53, "kind": "property", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
+ "proxyPort": { "index": 54, "kind": "property", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
+ "proxyProtocol": { "index": 55, "kind": "property", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when i [...]
+ "accessKey": { "index": 56, "kind": "property", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+ "profileCredentialsName": { "index": 57, "kind": "property", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
+ "secretKey": { "index": 58, "kind": "property", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
+ "sessionToken": { "index": 59, "kind": "property", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
+ "trustAllCertificates": { "index": 60, "kind": "property", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
+ "useDefaultCredentialsProvider": { "index": 61, "kind": "property", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
+ "useProfileCredentialsProvider": { "index": 62, "kind": "property", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load cr [...]
+ "useSessionCredentials": { "index": 63, "kind": "property", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials. [...]
},
"headers": {
"CamelAwsS3BucketName": { "index": 0, "kind": "header", "displayName": "", "group": "common", "label": "", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The bucket Name (can be dynamic using the simple language in the producer) which this object will be stored or which will be used for the current operation or in which this object is contained.", "constantName": "org.apache.camel.component.aws [...]
@@ -173,38 +176,41 @@
"storageClass": { "index": 43, "kind": "parameter", "displayName": "Storage Class", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The storage class to set in the com.amazonaws.services.s3.model.PutObjectRequest request." },
"streamingUploadMode": { "index": 44, "kind": "parameter", "displayName": "Streaming Upload Mode", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "When stream mode is true, the upload to bucket will be done in streaming" },
"streamingUploadTimeout": { "index": 45, "kind": "parameter", "displayName": "Streaming Upload Timeout", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "While streaming upload mode is true, this option set the timeout to complete upload" },
- "awsKMSKeyId": { "index": 46, "kind": "parameter", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
- "conditionalWritesEnabled": { "index": 47, "kind": "parameter", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object ke [...]
- "lazyStartProducer": { "index": 48, "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 produ [...]
- "useAwsKMS": { "index": 49, "kind": "parameter", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
- "useCustomerKey": { "index": 50, "kind": "parameter", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
- "useSSES3": { "index": 51, "kind": "parameter", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
- "amazonS3Client": { "index": 52, "kind": "parameter", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazo [...]
- "amazonS3Presigner": { "index": 53, "kind": "parameter", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request [...]
- "proxyHost": { "index": 54, "kind": "parameter", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
- "proxyPort": { "index": 55, "kind": "parameter", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
- "proxyProtocol": { "index": 56, "kind": "parameter", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when [...]
- "backoffErrorThreshold": { "index": 57, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
- "backoffIdleThreshold": { "index": 58, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." },
- "backoffMultiplier": { "index": 59, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is h [...]
- "delay": { "index": 60, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." },
- "greedy": { "index": 61, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." },
- "initialDelay": { "index": 62, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." },
- "repeatCount": { "index": 63, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." },
- "runLoggingLevel": { "index": 64, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the log [...]
- "scheduledExecutorService": { "index": 65, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." },
- "scheduler": { "index": 66, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" },
- "schedulerProperties": { "index": 67, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This i [...]
- "startScheduler": { "index": 68, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." },
- "timeUnit": { "index": 69, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." },
- "useFixedDelay": { "index": 70, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." },
- "accessKey": { "index": 71, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
- "profileCredentialsName": { "index": 72, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
- "secretKey": { "index": 73, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
- "sessionToken": { "index": 74, "kind": "parameter", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
- "trustAllCertificates": { "index": 75, "kind": "parameter", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
- "useDefaultCredentialsProvider": { "index": 76, "kind": "parameter", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
- "useProfileCredentialsProvider": { "index": 77, "kind": "parameter", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
- "useSessionCredentials": { "index": 78, "kind": "parameter", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials [...]
+ "timestampGroupingEnabled": { "index": 46, "kind": "parameter", "displayName": "Timestamp Grouping Enabled", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Enable timestamp-based grouping of messages into time window [...]
+ "timestampHeaderName": { "index": 47, "kind": "parameter", "displayName": "Timestamp Header Name", "group": "producer", "label": "producer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "CamelMessageTimestamp", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The name of the message header containing th [...]
+ "timestampWindowSizeMillis": { "index": 48, "kind": "parameter", "displayName": "Timestamp Window Size Millis", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 300000, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "The size of the time window in milliseconds for timestamp-b [...]
+ "awsKMSKeyId": { "index": 49, "kind": "parameter", "displayName": "Aws KMSKey Id", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define the id of KMS key to use in case KMS is enabled" },
+ "conditionalWritesEnabled": { "index": 50, "kind": "parameter", "displayName": "Conditional Writes Enabled", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Uploads the object only if the object ke [...]
+ "lazyStartProducer": { "index": 51, "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 produ [...]
+ "useAwsKMS": { "index": 52, "kind": "parameter", "displayName": "Use Aws KMS", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if KMS must be used or not" },
+ "useCustomerKey": { "index": 53, "kind": "parameter", "displayName": "Use Customer Key", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if Customer Key must be used or not" },
+ "useSSES3": { "index": 54, "kind": "parameter", "displayName": "Use SSES3", "group": "producer (advanced)", "label": "producer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Define if SSE S3 must be used or not" },
+ "amazonS3Client": { "index": 55, "kind": "parameter", "displayName": "Amazon S3 Client", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.S3Client", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Reference to a com.amazonaws.services.s3.Amazo [...]
+ "amazonS3Presigner": { "index": 56, "kind": "parameter", "displayName": "Amazon S3 Presigner", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.s3.presigner.S3Presigner", "deprecated": false, "deprecationNote": "", "autowired": true, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "An S3 Presigner for Request [...]
+ "proxyHost": { "index": 57, "kind": "parameter", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
+ "proxyPort": { "index": 58, "kind": "parameter", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Specify a proxy port to be used inside the client definition." },
+ "proxyProtocol": { "index": 59, "kind": "parameter", "displayName": "Proxy Protocol", "group": "proxy", "label": "proxy", "required": false, "type": "enum", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when [...]
+ "backoffErrorThreshold": { "index": 60, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
+ "backoffIdleThreshold": { "index": 61, "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." },
+ "backoffMultiplier": { "index": 62, "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is h [...]
+ "delay": { "index": 63, "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 500, "description": "Milliseconds before the next poll." },
+ "greedy": { "index": 64, "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." },
+ "initialDelay": { "index": 65, "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 1000, "description": "Milliseconds before the first poll starts." },
+ "repeatCount": { "index": 66, "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 0, "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." },
+ "runLoggingLevel": { "index": 67, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the log [...]
+ "scheduledExecutorService": { "index": 68, "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "autowired": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." },
+ "scheduler": { "index": 69, "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.lang.Object", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler" },
+ "schedulerProperties": { "index": 70, "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "autowired": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This i [...]
+ "startScheduler": { "index": 71, "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether the scheduler should be auto started." },
+ "timeUnit": { "index": 72, "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "enum", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." },
+ "useFixedDelay": { "index": 73, "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." },
+ "accessKey": { "index": 74, "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+ "profileCredentialsName": { "index": 75, "kind": "parameter", "displayName": "Profile Credentials Name", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If using a profile credentials provider, this parameter will set the profile name" },
+ "secretKey": { "index": 76, "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" },
+ "sessionToken": { "index": 77, "kind": "parameter", "displayName": "Session Token", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Amazon AWS Session Token used when the user needs to assume an IAM role" },
+ "trustAllCertificates": { "index": 78, "kind": "parameter", "displayName": "Trust All Certificates", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "If we want to trust all certificates in case of overriding the endpoint" },
+ "useDefaultCredentialsProvider": { "index": 79, "kind": "parameter", "displayName": "Use Default Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
+ "useProfileCredentialsProvider": { "index": 80, "kind": "parameter", "displayName": "Use Profile Credentials Provider", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to load c [...]
+ "useSessionCredentials": { "index": 81, "kind": "parameter", "displayName": "Use Session Credentials", "group": "security", "label": "security", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.s3.AWS2S3Configuration", "configurationField": "configuration", "description": "Set whether the S3 client should expect to use Session Credentials [...]
}
}
diff --git a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc
index 8c95b466030..722032b7b46 100644
--- a/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc
+++ b/components/camel-aws/camel-aws2-s3/src/main/docs/aws2-s3-component.adoc
@@ -421,6 +421,8 @@ The upload will be completed when the batchSize has been completed or the batchM
There are two possible naming strategies: progressive and random.
With the progressive strategy, each file will have the name composed by keyName option and a progressive counter, and eventually the file extension (if any), while with the random strategy a UUID will be added after keyName and eventually the file extension will be appended.
+Additionally, streaming upload mode supports timestamp-based file grouping, which allows messages to be automatically grouped into time windows based on their timestamps.
+
As an example:
[source,java]
@@ -478,6 +480,106 @@ from(kafka("topic1").brokers("localhost:9092"))
In this case, the upload will be completed after 10 seconds.
+==== Timestamp Grouping
+
+The streaming upload mode also supports timestamp-based file grouping, which allows messages to be automatically grouped into time windows and written to the same S3 file based on their timestamps. This feature enables append-like behavior where messages with timestamps falling within the same time window are combined into a single file.
+
+To enable timestamp grouping, use the following configuration options:
+
+- `timestampGroupingEnabled`: Set to `true` to enable timestamp-based grouping (default: `false`)
+- `timestampWindowSizeMillis`: The size of the time window in milliseconds (default: `300000` = 5 minutes)
+- `timestampHeaderName`: The name of the message header containing the timestamp (default: `Exchange.MESSAGE_TIMESTAMP`)
+
+Messages are grouped based on their timestamps extracted from the specified header. The timestamp can be provided as:
+
+- Long: Unix timestamp in milliseconds
+- Date: Java Date object
+- String: String representation of Unix timestamp in milliseconds
+
+Files are automatically named using a timestamp-based pattern that includes the time window information.
+
+===== Example Configuration
+
+Basic timestamp grouping with 5-minute windows:
+
+[source,java]
+--------------------------------------------------------------------------------
+from("timer:messages?period=10000")
+ .setHeader(Exchange.MESSAGE_TIMESTAMP, simple("${date:now:timestamp}"))
+ .setBody(constant("Message with timestamp"))
+ .to("aws2-s3://my-bucket?streamingUploadMode=true"
+ + "×tampGroupingEnabled=true"
+ + "×tampWindowSizeMillis=300000"
+ + "&keyName=grouped-messages.txt");
+--------------------------------------------------------------------------------
+
+Custom window size (1 minute) with custom header name:
+
+[source,java]
+--------------------------------------------------------------------------------
+from("direct:timestamped")
+ .setHeader("MyTimestamp", simple("${date:now:timestamp}"))
+ .setBody("Custom timestamped message")
+ .to("aws2-s3://my-bucket?streamingUploadMode=true"
+ + "×tampGroupingEnabled=true"
+ + "×tampWindowSizeMillis=60000"
+ + "×tampHeaderName=MyTimestamp"
+ + "&keyName=custom-grouped.txt");
+--------------------------------------------------------------------------------
+
+Large files with multipart and timestamp grouping:
+
+[source,java]
+--------------------------------------------------------------------------------
+from("direct:large-timestamped")
+ .setHeader(Exchange.MESSAGE_TIMESTAMP, simple("${date:now:timestamp}"))
+ .setBody("Large message content...")
+ .to("aws2-s3://my-bucket?streamingUploadMode=true"
+ + "×tampGroupingEnabled=true"
+ + "×tampWindowSizeMillis=1800000" // 30 minutes
+ + "&multiPartUpload=true"
+ + "&partSize=5242880" // 5MB parts
+ + "&keyName=large-grouped.txt");
+--------------------------------------------------------------------------------
+
+===== File Naming
+
+Files are automatically named using the following pattern:
+```
+{baseFileName}_{YYYYMMDD}_{HHMM}_{HHMM-HHMM}.{extension}
+```
+
+For time windows smaller than 1 minute, seconds precision is used:
+```
+{baseFileName}_{YYYYMMDD}_{HHMMSS}_{HHMMSS-HHMMSS}.{extension}
+```
+
+Example file names:
+- 5-minute window: `messages_20240101_0800_0800-0805.txt`
+- 1-minute window: `data_20240315_1430_1430-1431.log`
+- 5-second window: `events_20241225_000000_000000-000005.json`
+
+===== Time Window Examples
+
+With a 5-minute window (300000ms):
+- Window 1: 08:00:00 - 08:04:59 → `file_20240101_0800_0800-0805.txt`
+- Window 2: 08:05:00 - 08:09:59 → `file_20240101_0805_0805-0810.txt`
+- Window 3: 08:10:00 - 08:14:59 → `file_20240101_0810_0810-0815.txt`
+
+===== Fallback Behavior
+
+- If no timestamp header is found, the current system time is used
+- If the timestamp header contains invalid data, the current system time is used
+- Warning messages are logged when fallback behavior occurs
+
+===== Performance Considerations
+
+- Multiple concurrent time windows are supported
+- Each window maintains its own upload state
+- Memory usage scales with the number of active time windows
+- Completed windows are automatically cleaned up
+- Works with all existing streaming upload features (multipart uploads, timeouts, etc.)
+
=== Bucket Auto-creation
With the option `autoCreateBucket` users are able to avoid the auto-creation of an S3 Bucket in case it doesn't exist. The default for this option is `false`.
diff --git a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Configuration.java b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Configuration.java
index f84228d05db..86a2adfa275 100644
--- a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Configuration.java
+++ b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Configuration.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.aws2.s3;
+import org.apache.camel.Exchange;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.component.aws2.s3.stream.AWSS3NamingStrategyEnum;
import org.apache.camel.component.aws2.s3.stream.AWSS3RestartingPolicyEnum;
@@ -143,6 +144,12 @@ public class AWS2S3Configuration implements Cloneable {
private long streamingUploadTimeout;
@UriParam(defaultValue = "override", label = "producer")
private AWSS3RestartingPolicyEnum restartingPolicy = AWSS3RestartingPolicyEnum.override;
+ @UriParam(label = "producer")
+ private boolean timestampGroupingEnabled;
+ @UriParam(defaultValue = "300000", label = "producer")
+ private long timestampWindowSizeMillis = 300000; // 5 minutes default
+ @UriParam(defaultValue = "CamelMessageTimestamp", label = "producer")
+ private String timestampHeaderName = Exchange.MESSAGE_TIMESTAMP;
public long getPartSize() {
return partSize;
@@ -795,6 +802,41 @@ public class AWS2S3Configuration implements Cloneable {
this.conditionalWritesEnabled = conditionalWritesEnabled;
}
+ public boolean isTimestampGroupingEnabled() {
+ return timestampGroupingEnabled;
+ }
+
+ /**
+ * Enable timestamp-based grouping of messages into time windows for file creation. When enabled, messages are
+ * grouped by their timestamp header into time windows.
+ */
+ public void setTimestampGroupingEnabled(boolean timestampGroupingEnabled) {
+ this.timestampGroupingEnabled = timestampGroupingEnabled;
+ }
+
+ public long getTimestampWindowSizeMillis() {
+ return timestampWindowSizeMillis;
+ }
+
+ /**
+ * The size of the time window in milliseconds for timestamp-based grouping. Messages within the same time window
+ * will be written to the same file. Default is 300000 (5 minutes).
+ */
+ public void setTimestampWindowSizeMillis(long timestampWindowSizeMillis) {
+ this.timestampWindowSizeMillis = timestampWindowSizeMillis;
+ }
+
+ public String getTimestampHeaderName() {
+ return timestampHeaderName;
+ }
+
+ /**
+ * The name of the message header containing the timestamp for grouping. Default is "CamelMessageTimestamp".
+ */
+ public void setTimestampHeaderName(String timestampHeaderName) {
+ this.timestampHeaderName = timestampHeaderName;
+ }
+
public AWS2S3Configuration copy() {
try {
return (AWS2S3Configuration) super.clone();
diff --git a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducer.java b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducer.java
index 93baccd8248..87acfcec40b 100644
--- a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducer.java
+++ b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducer.java
@@ -18,10 +18,15 @@ package org.apache.camel.component.aws2.s3.stream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.Date;
import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -67,6 +72,7 @@ public class AWS2S3StreamUploadProducer extends DefaultProducer {
private static final String TIMEOUT_CHECKER_EXECUTOR_NAME = "S3_Streaming_Upload_Timeout_Checker";
private AtomicInteger part = new AtomicInteger();
private UploadState uploadAggregate = null;
+ private final Map<Long, UploadState> timestampBasedUploads = new ConcurrentHashMap<>();
private final Lock lock = new ReentrantLock();
private transient String s3ProducerToString;
private ScheduledExecutorService timeoutCheckerExecutorService;
@@ -100,6 +106,15 @@ public class AWS2S3StreamUploadProducer extends DefaultProducer {
uploadPart(uploadAggregate);
completeUpload(uploadAggregate);
}
+
+ // Complete any pending timestamp-based uploads
+ for (UploadState state : timestampBasedUploads.values()) {
+ if (ObjectHelper.isNotEmpty(state) && state.buffer.size() > 0) {
+ uploadPart(state);
+ completeUpload(state);
+ }
+ }
+ timestampBasedUploads.clear();
} finally {
lock.unlock();
}
@@ -125,6 +140,20 @@ public class AWS2S3StreamUploadProducer extends DefaultProducer {
completeUpload(uploadAggregate);
uploadAggregate = null;
}
+
+ // Handle timestamp-based uploads timeout
+ if (getConfiguration().isTimestampGroupingEnabled()) {
+ List<Long> keysToRemove = new ArrayList<>();
+ for (Map.Entry<Long, UploadState> entry : timestampBasedUploads.entrySet()) {
+ UploadState state = entry.getValue();
+ if (ObjectHelper.isNotEmpty(state) && state.buffer.size() > 0) {
+ uploadPart(state);
+ completeUpload(state);
+ keysToRemove.add(entry.getKey());
+ }
+ }
+ keysToRemove.forEach(timestampBasedUploads::remove);
+ }
} finally {
lock.unlock();
}
@@ -133,6 +162,14 @@ public class AWS2S3StreamUploadProducer extends DefaultProducer {
@Override
public void process(final Exchange exchange) throws Exception {
+ if (getConfiguration().isTimestampGroupingEnabled()) {
+ processWithTimestampGrouping(exchange);
+ } else {
+ processWithoutTimestampGrouping(exchange);
+ }
+ }
+
+ private void processWithoutTimestampGrouping(final Exchange exchange) throws Exception {
InputStream is = exchange.getIn().getMandatoryBody(InputStream.class);
UploadState state = null;
@@ -273,6 +310,120 @@ public class AWS2S3StreamUploadProducer extends DefaultProducer {
}
}
+ private void processWithTimestampGrouping(final Exchange exchange) throws Exception {
+ InputStream is = exchange.getIn().getMandatoryBody(InputStream.class);
+
+ // Extract timestamp from exchange
+ Long messageTimestamp = extractTimestampFromExchange(exchange);
+ if (messageTimestamp == null) {
+ LOG.warn("No valid timestamp found in exchange header '{}', falling back to current time",
+ getConfiguration().getTimestampHeaderName());
+ messageTimestamp = System.currentTimeMillis();
+ }
+
+ // Calculate the timestamp window
+ long timestampWindow = getTimestampWindow(messageTimestamp);
+
+ byte[] b;
+ int totalSize = 0;
+ int maxRead = (getConfiguration().isMultiPartUpload()
+ ? Math.toIntExact(getConfiguration().getPartSize()) : getConfiguration().getBufferSize());
+
+ // Get or create upload state for this timestamp window
+ UploadState state = timestampBasedUploads.get(timestampWindow);
+ if (state != null) {
+ state.index++;
+ maxRead -= state.buffer.size();
+ }
+
+ while ((b = AWS2S3Utils.toByteArray(is, maxRead)).length > 0) {
+ totalSize += b.length;
+ if (getConfiguration().isMultiPartUpload())
+ maxRead -= b.length;
+
+ lock.lock();
+ try {
+ // Get or create upload state for this timestamp window
+ if (!timestampBasedUploads.containsKey(timestampWindow)) {
+ UploadState newState = new UploadState();
+
+ // Generate timestamp-based filename
+ final String keyName = getConfiguration().getKeyName();
+ final String fileName = AWS2S3Utils.determineFileName(keyName);
+ final String extension = AWS2S3Utils.determineFileExtension(keyName);
+ newState.dynamicKeyName = generateTimestampBasedFileName(fileName, extension, timestampWindow);
+
+ // Initialize multipart upload
+ CreateMultipartUploadRequest.Builder createMultipartUploadRequest
+ = CreateMultipartUploadRequest.builder().bucket(getConfiguration().getBucketName())
+ .key(newState.dynamicKeyName).checksumAlgorithm(algorithm);
+
+ String storageClass = AWS2S3Utils.determineStorageClass(exchange, getConfiguration());
+ if (storageClass != null) {
+ createMultipartUploadRequest.storageClass(storageClass);
+ }
+
+ String cannedAcl = exchange.getIn().getHeader(AWS2S3Constants.CANNED_ACL, String.class);
+ if (cannedAcl != null) {
+ ObjectCannedACL objectAcl = ObjectCannedACL.valueOf(cannedAcl);
+ createMultipartUploadRequest.acl(objectAcl);
+ }
+
+ BucketCannedACL acl = exchange.getIn().getHeader(AWS2S3Constants.ACL, BucketCannedACL.class);
+ if (acl != null) {
+ createMultipartUploadRequest.acl(acl.toString());
+ }
+
+ AWS2S3Utils.setEncryption(createMultipartUploadRequest, getConfiguration());
+
+ LOG.trace("Initiating multipart upload [{}] for timestamp window {}", createMultipartUploadRequest,
+ timestampWindow);
+ newState.initResponse
+ = getEndpoint().getS3Client().createMultipartUpload(createMultipartUploadRequest.build());
+
+ timestampBasedUploads.put(timestampWindow, newState);
+ }
+ state = timestampBasedUploads.get(timestampWindow);
+
+ state.buffer.write(b);
+
+ if (getConfiguration().isMultiPartUpload() && state.buffer.size() >= getConfiguration().getPartSize()) {
+ uploadPart(state);
+ maxRead = Math.toIntExact(getConfiguration().getPartSize());
+ continue;
+ }
+
+ if (state.buffer.size() >= getConfiguration().getBatchSize()
+ || (state.index >= getConfiguration().getBatchMessageNumber()
+ && state.buffer.size() < getConfiguration().getPartSize())) {
+
+ if (state.buffer.size() > 0)
+ uploadPart(state);
+ CompleteMultipartUploadResponse uploadResult = completeUpload(state);
+ timestampBasedUploads.remove(timestampWindow);
+
+ Message message = getMessageForResponse(exchange);
+ message.setHeader(AWS2S3Constants.E_TAG, uploadResult.eTag());
+ if (uploadResult.versionId() != null) {
+ message.setHeader(AWS2S3Constants.VERSION_ID, uploadResult.versionId());
+ }
+ }
+
+ } catch (Exception e) {
+ if (state != null && state.initResponse != null) {
+ getEndpoint().getS3Client()
+ .abortMultipartUpload(
+ AbortMultipartUploadRequest.builder().bucket(getConfiguration().getBucketName())
+ .key(state.dynamicKeyName).uploadId(state.initResponse.uploadId()).build());
+ timestampBasedUploads.remove(timestampWindow);
+ }
+ throw e;
+ } finally {
+ lock.unlock();
+ }
+ }
+ }
+
private CompleteMultipartUploadResponse completeUpload(UploadState state) {
CompletedMultipartUpload completeMultipartUpload
= CompletedMultipartUpload.builder().parts(state.completedParts).build();
@@ -375,6 +526,61 @@ public class AWS2S3StreamUploadProducer extends DefaultProducer {
return dynamicKeyName;
}
+ private long getTimestampWindow(long timestamp) {
+ long windowSize = getConfiguration().getTimestampWindowSizeMillis();
+ return (timestamp / windowSize) * windowSize;
+ }
+
+ private String generateTimestampBasedFileName(String baseFileName, String extension, long timestampWindow) {
+ Date windowStart = new Date(timestampWindow);
+ Date windowEnd = new Date(timestampWindow + getConfiguration().getTimestampWindowSizeMillis());
+
+ // Use seconds precision for windows smaller than 1 minute, minutes precision otherwise
+ String datePattern, timePattern;
+ if (getConfiguration().getTimestampWindowSizeMillis() < 60000) {
+ datePattern = "yyyyMMdd_HHmmss";
+ timePattern = "HHmmss";
+ } else {
+ datePattern = "yyyyMMdd_HHmm";
+ timePattern = "HHmm";
+ }
+
+ SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
+ sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+ SimpleDateFormat timeFormat = new SimpleDateFormat(timePattern);
+ timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String timeRange = timeFormat.format(windowStart) + "-" + timeFormat.format(windowEnd);
+
+ if (extension != null && !extension.isEmpty()) {
+ return baseFileName + "_" + sdf.format(windowStart) + "_" + timeRange + extension;
+ } else {
+ return baseFileName + "_" + sdf.format(windowStart) + "_" + timeRange;
+ }
+ }
+
+ private Long extractTimestampFromExchange(Exchange exchange) {
+ String headerName = getConfiguration().getTimestampHeaderName();
+ Object timestampObj = exchange.getIn().getHeader(headerName);
+
+ if (timestampObj instanceof Long) {
+ return (Long) timestampObj;
+ } else if (timestampObj instanceof Date) {
+ return ((Date) timestampObj).getTime();
+ } else if (timestampObj instanceof String) {
+ try {
+ return Long.parseLong((String) timestampObj);
+ } catch (NumberFormatException e) {
+ LOG.warn("Cannot parse timestamp header '{}' with value '{}'", headerName, timestampObj);
+ return null;
+ }
+ } else if (timestampObj != null) {
+ LOG.warn("Unsupported timestamp header type: {} for header '{}'", timestampObj.getClass(), headerName);
+ }
+
+ return null;
+ }
+
private void setStartingPart() {
if (getConfiguration().getNamingStrategy().equals(AWSS3NamingStrategyEnum.progressive)) {
ArrayList<S3Object> list = new ArrayList<>();
diff --git a/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/integration/S3StreamUploadTimestampGroupingEdgeCasesIT.java b/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/integration/S3StreamUploadTimestampGroupingEdgeCasesIT.java
new file mode 100644
index 00000000000..bf26f73164f
--- /dev/null
+++ b/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/integration/S3StreamUploadTimestampGroupingEdgeCasesIT.java
@@ -0,0 +1,333 @@
+/*
+ * 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.aws2.s3.integration;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.s3.AWS2S3Constants;
+import org.apache.camel.component.aws2.s3.AWS2S3Operations;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class S3StreamUploadTimestampGroupingEdgeCasesIT extends Aws2S3Base {
+
+ @EndpointInject
+ private ProducerTemplate template;
+
+ @EndpointInject("mock:result")
+ private MockEndpoint result;
+
+ @Test
+ public void testTimestampGroupingWithInvalidStringTimestamp() throws Exception {
+ result.reset();
+ result.expectedMessageCount(5);
+
+ // Test with invalid string timestamp - should fall back to current time
+ for (int i = 0; i < 5; i++) {
+ template.sendBodyAndHeader("direct:timestampGrouping",
+ "Message with invalid timestamp: " + i,
+ Exchange.MESSAGE_TIMESTAMP, "invalid-timestamp-" + i);
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "edgeTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should create at least 1 file even with invalid timestamps");
+ }
+
+ @Test
+ public void testTimestampGroupingWithMixedTimestampTypes() throws Exception {
+ result.reset();
+ result.expectedMessageCount(6);
+
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ // Mix of Long, Date, String, and invalid timestamps
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message 1 - Long",
+ Exchange.MESSAGE_TIMESTAMP, baseTime);
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message 2 - Date",
+ Exchange.MESSAGE_TIMESTAMP, new Date(baseTime + 60000));
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message 3 - String",
+ Exchange.MESSAGE_TIMESTAMP, String.valueOf(baseTime + 120000));
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message 4 - Invalid",
+ Exchange.MESSAGE_TIMESTAMP, "not-a-timestamp");
+ template.sendBody("direct:timestampGrouping", "Message 5 - No header");
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message 6 - Null",
+ Exchange.MESSAGE_TIMESTAMP, null);
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "edgeTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should handle mixed timestamp types gracefully");
+ }
+
+ @Test
+ public void testTimestampGroupingWithVeryLargeWindow() throws Exception {
+ result.reset();
+ result.expectedMessageCount(10);
+
+ // Test with very large window (1 hour = 3600000ms)
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ // Send messages spread over 30 minutes - should all go to same window
+ for (int i = 0; i < 10; i++) {
+ long timestamp = baseTime + (i * 180000); // 3 minutes apart
+ template.sendBodyAndHeader("direct:timestampGroupingLargeWindow",
+ "Message in large window: " + i,
+ Exchange.MESSAGE_TIMESTAMP, timestamp);
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "largeWindowTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertEquals(1, resp.size(), "Should create only 1 file for large time window");
+ }
+
+ @Test
+ public void testTimestampGroupingWithVerySmallWindow() throws Exception {
+ result.reset();
+ result.expectedMessageCount(6);
+
+ // Test with very small window (5 seconds = 5000ms)
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ // Send messages spread across 3 different 5-second windows to ensure clear separation
+ // Window 1: 08:00:00 - 08:00:05
+ template.sendBodyAndHeader("direct:timestampGroupingSmallWindow",
+ "Message in window 1a", Exchange.MESSAGE_TIMESTAMP, baseTime);
+ template.sendBodyAndHeader("direct:timestampGroupingSmallWindow",
+ "Message in window 1b", Exchange.MESSAGE_TIMESTAMP, baseTime + 2000);
+
+ // Window 2: 08:00:10 - 08:00:15 (skip 5 seconds to be in different window)
+ template.sendBodyAndHeader("direct:timestampGroupingSmallWindow",
+ "Message in window 2a", Exchange.MESSAGE_TIMESTAMP, baseTime + 10000);
+ template.sendBodyAndHeader("direct:timestampGroupingSmallWindow",
+ "Message in window 2b", Exchange.MESSAGE_TIMESTAMP, baseTime + 12000);
+
+ // Window 3: 08:00:20 - 08:00:25
+ template.sendBodyAndHeader("direct:timestampGroupingSmallWindow",
+ "Message in window 3a", Exchange.MESSAGE_TIMESTAMP, baseTime + 20000);
+ template.sendBodyAndHeader("direct:timestampGroupingSmallWindow",
+ "Message in window 3b", Exchange.MESSAGE_TIMESTAMP, baseTime + 22000);
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ // Add a delay to ensure all uploads complete via timeout
+ Thread.sleep(5000);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "smallWindowTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 3, "Should create 3 files for 3 different 5-second windows, got: " + resp.size());
+ }
+
+ @Test
+ public void testTimestampGroupingWithBoundaryTimestamps() throws Exception {
+ result.reset();
+ result.expectedMessageCount(6);
+
+ // Test messages exactly at window boundaries
+ long windowStart = 1704096000000L; // Exact start of 5-minute window
+ long windowSize = 300000L; // 5 minutes
+
+ // Send messages at exact boundaries
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message at window start",
+ Exchange.MESSAGE_TIMESTAMP, windowStart);
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message 1ms before window end",
+ Exchange.MESSAGE_TIMESTAMP, windowStart + windowSize - 1);
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message at next window start",
+ Exchange.MESSAGE_TIMESTAMP, windowStart + windowSize);
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message in first window middle",
+ Exchange.MESSAGE_TIMESTAMP, windowStart + windowSize / 2);
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message in second window middle",
+ Exchange.MESSAGE_TIMESTAMP, windowStart + windowSize + windowSize / 2);
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message at exact boundary",
+ Exchange.MESSAGE_TIMESTAMP, windowStart + windowSize);
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "edgeTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertEquals(2, resp.size(), "Should create exactly 2 files for boundary timestamps");
+ }
+
+ @Test
+ public void testTimestampGroupingWithOldTimestamps() throws Exception {
+ result.reset();
+ result.expectedMessageCount(8);
+
+ // Test with very old timestamps (year 2000)
+ long oldBaseTime = 946684800000L; // 2000-01-01 00:00:00 UTC
+
+ for (int i = 0; i < 8; i++) {
+ long timestamp = oldBaseTime + (i * 60000); // 1 minute apart
+ template.sendBodyAndHeader("direct:timestampGrouping",
+ "Message with old timestamp: " + i,
+ Exchange.MESSAGE_TIMESTAMP, timestamp);
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "edgeTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should handle old timestamps correctly");
+
+ // Verify files have correct naming with old dates
+ boolean foundOldDateFile = false;
+ for (S3Object s3Object : resp) {
+ String key = s3Object.key();
+ if (key.contains("20000101")) { // Check for year 2000
+ foundOldDateFile = true;
+ break;
+ }
+ }
+ assertTrue(foundOldDateFile, "Should create files with old date naming");
+ }
+
+ @Test
+ public void testTimestampGroupingWithFutureTimestamps() throws Exception {
+ result.reset();
+ result.expectedMessageCount(6);
+
+ // Test with future timestamps (year 2030)
+ long futureBaseTime = 1893456000000L; // 2030-01-01 00:00:00 UTC
+
+ for (int i = 0; i < 6; i++) {
+ long timestamp = futureBaseTime + (i * 60000); // 1 minute apart
+ template.sendBodyAndHeader("direct:timestampGrouping",
+ "Message with future timestamp: " + i,
+ Exchange.MESSAGE_TIMESTAMP, timestamp);
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "edgeTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should handle future timestamps correctly");
+
+ // Verify files have correct naming with future dates
+ boolean foundFutureDateFile = false;
+ for (S3Object s3Object : resp) {
+ String key = s3Object.key();
+ if (key.contains("20300101")) { // Check for year 2030
+ foundFutureDateFile = true;
+ break;
+ }
+ }
+ assertTrue(foundFutureDateFile, "Should create files with future date naming");
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ // Standard timestamp grouping route
+ String timestampGroupingEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=edgeTest.txt"
+ + "&batchMessageNumber=3×tampGroupingEnabled=true×tampWindowSizeMillis=300000"
+ + "×tampHeaderName=CamelMessageTimestamp",
+ name.get());
+
+ from("direct:timestampGrouping").to(timestampGroupingEndpoint).to("mock:result");
+
+ // Large window test (1 hour)
+ String largeWindowEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=largeWindowTest.txt"
+ + "&batchMessageNumber=5×tampGroupingEnabled=true×tampWindowSizeMillis=3600000"
+ + "×tampHeaderName=CamelMessageTimestamp",
+ name.get());
+
+ from("direct:timestampGroupingLargeWindow").to(largeWindowEndpoint).to("mock:result");
+
+ // Small window test (5 seconds)
+ String smallWindowEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=smallWindowTest.txt"
+ + "&batchMessageNumber=3×tampGroupingEnabled=true×tampWindowSizeMillis=5000"
+ + "×tampHeaderName=CamelMessageTimestamp&streamingUploadTimeout=2000",
+ name.get());
+
+ from("direct:timestampGroupingSmallWindow").to(smallWindowEndpoint).to("mock:result");
+
+ // Common route for listing objects
+ String listEndpoint = String.format("aws2-s3://%s?autoCreateBucket=true", name.get());
+ from("direct:listObjects").to(listEndpoint);
+ }
+ };
+ }
+}
diff --git a/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/integration/S3StreamUploadTimestampGroupingIT.java b/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/integration/S3StreamUploadTimestampGroupingIT.java
new file mode 100644
index 00000000000..548b0073054
--- /dev/null
+++ b/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/integration/S3StreamUploadTimestampGroupingIT.java
@@ -0,0 +1,381 @@
+/*
+ * 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.aws2.s3.integration;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.s3.AWS2S3Constants;
+import org.apache.camel.component.aws2.s3.AWS2S3Operations;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class S3StreamUploadTimestampGroupingIT extends Aws2S3Base {
+
+ @EndpointInject
+ private ProducerTemplate template;
+
+ @EndpointInject("mock:result")
+ private MockEndpoint result;
+
+ @Test
+ public void testTimestampGroupingBasic() throws Exception {
+ result.reset();
+ result.expectedMessageCount(20);
+
+ // Send messages with timestamps in two different 5-minute windows
+ // Window 1: 2024-01-01 08:00:00 to 08:05:00
+ long baseTime1 = 1704096000000L; // 2024-01-01 08:00:00 UTC
+ // Window 2: 2024-01-01 08:05:00 to 08:10:00
+ long baseTime2 = 1704096300000L; // 2024-01-01 08:05:00 UTC
+
+ // Send 10 messages for first window
+ for (int i = 0; i < 10; i++) {
+ template.sendBodyAndHeader("direct:timestampGroupingBasic", "Message from window 1: " + i,
+ Exchange.MESSAGE_TIMESTAMP, baseTime1 + (i * 10000)); // spread within window
+ }
+
+ // Send 10 messages for second window
+ for (int i = 0; i < 10; i++) {
+ template.sendBodyAndHeader("direct:timestampGroupingBasic", "Message from window 2: " + i,
+ Exchange.MESSAGE_TIMESTAMP, baseTime2 + (i * 10000)); // spread within window
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "basicTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertEquals(2, resp.size(), "Should create 2 files for 2 different timestamp windows");
+
+ // Verify files have timestamp-based naming
+ boolean foundWindow1File = false;
+ boolean foundWindow2File = false;
+
+ for (S3Object s3Object : resp) {
+ String key = s3Object.key();
+ if (key.contains("20240101_0800_0800-0805")) {
+ foundWindow1File = true;
+ } else if (key.contains("20240101_0805_0805-0810")) {
+ foundWindow2File = true;
+ }
+ }
+
+ assertTrue(foundWindow1File, "Should find file for first timestamp window");
+ assertTrue(foundWindow2File, "Should find file for second timestamp window");
+ }
+
+ @Test
+ public void testTimestampGroupingWithStringTimestamp() throws Exception {
+ result.reset();
+ result.expectedMessageCount(15);
+
+ // Test with string timestamp headers
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ for (int i = 0; i < 15; i++) {
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message with string timestamp: " + i,
+ Exchange.MESSAGE_TIMESTAMP, String.valueOf(baseTime + (i * 10000)));
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "timestampTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should create at least 1 file for timestamp window");
+ }
+
+ @Test
+ public void testTimestampGroupingFallbackToCurrentTime() throws Exception {
+ result.reset();
+ result.expectedMessageCount(5);
+
+ // Send messages without timestamp headers - should fall back to current time
+ for (int i = 0; i < 5; i++) {
+ template.sendBody("direct:timestampGrouping", "Message without timestamp: " + i);
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "timestampTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should create at least 1 file even without timestamp header");
+ }
+
+ @Test
+ public void testTimestampGroupingWithDateTimestamp() throws Exception {
+ result.reset();
+ result.expectedMessageCount(12);
+
+ // Test with Date timestamp headers
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ for (int i = 0; i < 12; i++) {
+ Date messageDate = new Date(baseTime + (i * 30000)); // 30 seconds apart
+ template.sendBodyAndHeader("direct:timestampGrouping", "Message with Date timestamp: " + i,
+ Exchange.MESSAGE_TIMESTAMP, messageDate);
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "timestampTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should create at least 1 file for Date timestamps");
+ }
+
+ @Test
+ public void testTimestampGroupingLargeTimeSpan() throws Exception {
+ result.reset();
+ result.expectedMessageCount(30);
+
+ // Test spanning multiple time windows over 30 minutes
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ // Send messages across 6 different 5-minute windows (30 minutes total)
+ for (int window = 0; window < 6; window++) {
+ for (int msg = 0; msg < 5; msg++) {
+ long timestamp = baseTime + (window * 300000) + (msg * 10000); // 5-minute windows
+ template.sendBodyAndHeader("direct:timestampGroupingLargeSpan",
+ String.format("Window %d, Message %d", window, msg),
+ Exchange.MESSAGE_TIMESTAMP, timestamp);
+ }
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "largeSpanTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertEquals(6, resp.size(), "Should create 6 files for 6 different timestamp windows");
+
+ // Verify all files have timestamp-based naming pattern
+ for (S3Object s3Object : resp) {
+ String key = s3Object.key();
+ assertTrue(key.matches("largeSpanTest_\\d{8}_\\d{4}_\\d{4}-\\d{4}\\.txt"),
+ "File should have timestamp-based name pattern: " + key);
+ }
+ }
+
+ @Test
+ public void testTimestampGroupingWithCustomWindow() throws Exception {
+ result.reset();
+ result.expectedMessageCount(20);
+
+ // Test with 1-minute windows instead of default 5-minute
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ // Send messages across 4 different 1-minute windows
+ for (int window = 0; window < 4; window++) {
+ for (int msg = 0; msg < 5; msg++) {
+ long timestamp = baseTime + (window * 60000) + (msg * 5000); // 1-minute windows
+ template.sendBodyAndHeader("direct:timestampGroupingCustomWindow",
+ String.format("1min Window %d, Message %d", window, msg),
+ Exchange.MESSAGE_TIMESTAMP, timestamp);
+ }
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "customWindowTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertEquals(4, resp.size(), "Should create 4 files for 4 different 1-minute windows");
+ }
+
+ @Test
+ public void testTimestampGroupingWithCustomHeaderName() throws Exception {
+ result.reset();
+ result.expectedMessageCount(8);
+
+ // Test with custom timestamp header name
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ for (int i = 0; i < 8; i++) {
+ template.sendBodyAndHeader("direct:timestampGroupingCustomHeader",
+ "Message with custom header: " + i,
+ "MyCustomTimestamp", baseTime + (i * 30000));
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "customHeaderTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertTrue(resp.size() >= 1, "Should create at least 1 file with custom timestamp header");
+ }
+
+ @Test
+ public void testTimestampGroupingMultipartUpload() throws Exception {
+ result.reset();
+ result.expectedMessageCount(6);
+
+ // Test with multipart upload enabled and larger messages
+ long baseTime = 1704096000000L; // 2024-01-01 08:00:00 UTC
+ StringBuilder largeContent = new StringBuilder();
+ for (int i = 0; i < 1000; i++) {
+ largeContent.append("This is line ").append(i).append(" of a large message for multipart testing.\n");
+ }
+
+ // Send large messages in two different windows
+ for (int window = 0; window < 2; window++) {
+ for (int msg = 0; msg < 3; msg++) {
+ long timestamp = baseTime + (window * 300000) + (msg * 10000);
+ template.sendBodyAndHeader("direct:timestampGroupingMultipart",
+ largeContent.toString() + " Window: " + window + ", Message: " + msg,
+ Exchange.MESSAGE_TIMESTAMP, timestamp);
+ }
+ }
+
+ MockEndpoint.assertIsSatisfied(context);
+
+ Exchange ex = template.request("direct:listObjects", new Processor() {
+ @Override
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+ exchange.getIn().setHeader(AWS2S3Constants.PREFIX, "multipartTest");
+ }
+ });
+
+ List<S3Object> resp = ex.getMessage().getBody(List.class);
+ assertEquals(2, resp.size(), "Should create 2 files for 2 different timestamp windows with multipart");
+
+ // Verify files are reasonably large (indicating multipart worked)
+ for (S3Object s3Object : resp) {
+ assertTrue(s3Object.size() > 50000, "Multipart files should be substantial in size");
+ }
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ // Route for basic timestamp grouping test
+ String basicTestEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=basicTest.txt"
+ + "&batchMessageNumber=5×tampGroupingEnabled=true×tampWindowSizeMillis=300000"
+ + "×tampHeaderName=CamelMessageTimestamp",
+ name.get());
+
+ from("direct:timestampGroupingBasic").to(basicTestEndpoint).to("mock:result");
+
+ // Route for large span test
+ String largeSpanEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=largeSpanTest.txt"
+ + "&batchMessageNumber=5×tampGroupingEnabled=true×tampWindowSizeMillis=300000"
+ + "×tampHeaderName=CamelMessageTimestamp",
+ name.get());
+
+ from("direct:timestampGroupingLargeSpan").to(largeSpanEndpoint).to("mock:result");
+
+ // Route for timestamp grouping with 5-minute windows (other tests)
+ String timestampGroupingEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=timestampTest.txt"
+ + "&batchMessageNumber=5×tampGroupingEnabled=true×tampWindowSizeMillis=300000"
+ + "×tampHeaderName=CamelMessageTimestamp",
+ name.get());
+
+ from("direct:timestampGrouping").to(timestampGroupingEndpoint).to("mock:result");
+
+ // Route for timestamp grouping with custom 1-minute windows
+ String customWindowEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=customWindowTest.txt"
+ + "&batchMessageNumber=5×tampGroupingEnabled=true×tampWindowSizeMillis=60000"
+ + "×tampHeaderName=CamelMessageTimestamp",
+ name.get());
+
+ from("direct:timestampGroupingCustomWindow").to(customWindowEndpoint).to("mock:result");
+
+ // Route for timestamp grouping with custom header name
+ String customHeaderEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=customHeaderTest.txt"
+ + "&batchMessageNumber=4×tampGroupingEnabled=true×tampWindowSizeMillis=300000"
+ + "×tampHeaderName=MyCustomTimestamp",
+ name.get());
+
+ from("direct:timestampGroupingCustomHeader").to(customHeaderEndpoint).to("mock:result");
+
+ // Route for timestamp grouping with multipart upload
+ String multipartEndpoint = String.format(
+ "aws2-s3://%s?autoCreateBucket=true&streamingUploadMode=true&keyName=multipartTest.txt"
+ + "&batchMessageNumber=3×tampGroupingEnabled=true×tampWindowSizeMillis=300000"
+ + "×tampHeaderName=CamelMessageTimestamp&multiPartUpload=true&partSize=5242880",
+ name.get());
+
+ from("direct:timestampGroupingMultipart").to(multipartEndpoint).to("mock:result");
+
+ // Common route for listing objects
+ String listEndpoint = String.format("aws2-s3://%s?autoCreateBucket=true", name.get());
+ from("direct:listObjects").to(listEndpoint);
+ }
+ };
+ }
+}
diff --git a/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducerTimestampTest.java b/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducerTimestampTest.java
new file mode 100644
index 00000000000..4089a9669d8
--- /dev/null
+++ b/components/camel-aws/camel-aws2-s3/src/test/java/org/apache/camel/component/aws2/s3/stream/AWS2S3StreamUploadProducerTimestampTest.java
@@ -0,0 +1,282 @@
+/*
+ * 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.aws2.s3.stream;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.aws2.s3.AWS2S3Configuration;
+import org.apache.camel.component.aws2.s3.AWS2S3Endpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.Mockito.when;
+
+public class AWS2S3StreamUploadProducerTimestampTest {
+
+ @Mock
+ private AWS2S3Endpoint endpoint;
+
+ @Mock
+ private AWS2S3Configuration configuration;
+
+ private AWS2S3StreamUploadProducer producer;
+ private DefaultCamelContext camelContext;
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ camelContext = new DefaultCamelContext();
+
+ when(endpoint.getConfiguration()).thenReturn(configuration);
+ when(endpoint.getCamelContext()).thenReturn(camelContext);
+
+ producer = new AWS2S3StreamUploadProducer(endpoint);
+ }
+
+ @Test
+ public void testGetTimestampWindow() throws Exception {
+ // Configure 5-minute windows (300000ms)
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(300000L);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod("getTimestampWindow", long.class);
+ method.setAccessible(true);
+
+ // Test timestamp: 2024-01-01 08:02:30 UTC (1704096150000)
+ long timestamp = 1704096150000L;
+ long expectedWindow = 1704096000000L; // Should round down to 08:00:00
+
+ long actualWindow = (Long) method.invoke(producer, timestamp);
+ assertEquals(expectedWindow, actualWindow, "Should round down to window start");
+
+ // Test exact window boundary
+ long boundaryTimestamp = 1704096000000L; // Exactly 08:00:00
+ long boundaryWindow = (Long) method.invoke(producer, boundaryTimestamp);
+ assertEquals(boundaryTimestamp, boundaryWindow, "Boundary timestamp should map to itself");
+
+ // Test just before next window
+ long beforeNextWindow = 1704096299999L; // 07:59:59.999
+ long beforeNextWindowResult = (Long) method.invoke(producer, beforeNextWindow);
+ assertEquals(1704096000000L, beforeNextWindowResult, "Should still be in same window");
+ }
+
+ @Test
+ public void testGenerateTimestampBasedFileName() throws Exception {
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "generateTimestampBasedFileName", String.class, String.class, long.class);
+ method.setAccessible(true);
+
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(300000L); // 5 minutes
+
+ // Test with extension
+ long timestampWindow = 1704096000000L; // 2024-01-01 08:00:00 UTC
+ String fileName = (String) method.invoke(producer, "testfile", ".txt", timestampWindow);
+ assertEquals("testfile_20240101_0800_0800-0805.txt", fileName);
+
+ // Test without extension
+ fileName = (String) method.invoke(producer, "testfile", null, timestampWindow);
+ assertEquals("testfile_20240101_0800_0800-0805", fileName);
+
+ // Test with empty extension
+ fileName = (String) method.invoke(producer, "testfile", "", timestampWindow);
+ assertEquals("testfile_20240101_0800_0800-0805", fileName);
+
+ // Test different time window
+ long timestampWindow2 = 1704096300000L; // 2024-01-01 08:05:00 UTC
+ fileName = (String) method.invoke(producer, "myfile", ".log", timestampWindow2);
+ assertEquals("myfile_20240101_0805_0805-0810.log", fileName);
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithLong() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn(Exchange.MESSAGE_TIMESTAMP);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+
+ // Test with Long timestamp
+ long expectedTimestamp = 1704096000000L;
+ exchange.getIn().setHeader(Exchange.MESSAGE_TIMESTAMP, expectedTimestamp);
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNotNull(result);
+ assertEquals(expectedTimestamp, result.longValue());
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithDate() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn(Exchange.MESSAGE_TIMESTAMP);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+
+ // Test with Date timestamp
+ long expectedTimestamp = 1704096000000L;
+ Date date = new Date(expectedTimestamp);
+ exchange.getIn().setHeader(Exchange.MESSAGE_TIMESTAMP, date);
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNotNull(result);
+ assertEquals(expectedTimestamp, result.longValue());
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithString() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn(Exchange.MESSAGE_TIMESTAMP);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+
+ // Test with String timestamp
+ long expectedTimestamp = 1704096000000L;
+ exchange.getIn().setHeader("CamelMessageTimestamp", String.valueOf(expectedTimestamp));
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNotNull(result);
+ assertEquals(expectedTimestamp, result.longValue());
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithInvalidString() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn(Exchange.MESSAGE_TIMESTAMP);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+
+ // Test with invalid string timestamp
+ exchange.getIn().setHeader("CamelMessageTimestamp", "not-a-timestamp");
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNull(result, "Should return null for invalid timestamp string");
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithMissingHeader() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn(Exchange.MESSAGE_TIMESTAMP);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+ // No timestamp header set
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNull(result, "Should return null when timestamp header is missing");
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithNullHeader() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn(Exchange.MESSAGE_TIMESTAMP);
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+ exchange.getIn().setHeader("CamelMessageTimestamp", null);
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNull(result, "Should return null when timestamp header is null");
+ }
+
+ @Test
+ public void testExtractTimestampFromExchangeWithCustomHeaderName() throws Exception {
+ when(configuration.getTimestampHeaderName()).thenReturn("MyCustomTimestamp");
+
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "extractTimestampFromExchange", Exchange.class);
+ method.setAccessible(true);
+
+ Exchange exchange = new DefaultExchange(camelContext);
+
+ // Test with custom header name
+ long expectedTimestamp = 1704096000000L;
+ exchange.getIn().setHeader("MyCustomTimestamp", expectedTimestamp);
+
+ Long result = (Long) method.invoke(producer, exchange);
+ assertNotNull(result);
+ assertEquals(expectedTimestamp, result.longValue());
+ }
+
+ @Test
+ public void testTimestampWindowCalculationWithDifferentWindowSizes() throws Exception {
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod("getTimestampWindow", long.class);
+ method.setAccessible(true);
+
+ long baseTimestamp = 1704096150000L; // 2024-01-01 08:02:30 UTC
+
+ // Test 1-minute windows
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(60000L);
+ long window1min = (Long) method.invoke(producer, baseTimestamp);
+ assertEquals(1704096120000L, window1min); // Should round to 08:02:00
+
+ // Test 1-hour windows
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(3600000L);
+ long window1hour = (Long) method.invoke(producer, baseTimestamp);
+ assertEquals(1704096000000L, window1hour); // Should round to 08:00:00
+
+ // Test 1-second windows
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(1000L);
+ long window1sec = (Long) method.invoke(producer, baseTimestamp);
+ assertEquals(1704096150000L, window1sec); // Should round to 08:02:30
+ }
+
+ @Test
+ public void testGenerateTimestampBasedFileNameWithDifferentWindowSizes() throws Exception {
+ Method method = AWS2S3StreamUploadProducer.class.getDeclaredMethod(
+ "generateTimestampBasedFileName", String.class, String.class, long.class);
+ method.setAccessible(true);
+
+ long timestampWindow = 1704096000000L; // 2024-01-01 08:00:00 UTC
+
+ // Test 1-minute window
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(60000L);
+ String fileName1min = (String) method.invoke(producer, "test", ".txt", timestampWindow);
+ assertEquals("test_20240101_0800_0800-0801.txt", fileName1min);
+
+ // Test 1-hour window
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(3600000L);
+ String fileName1hour = (String) method.invoke(producer, "test", ".txt", timestampWindow);
+ assertEquals("test_20240101_0800_0800-0900.txt", fileName1hour);
+
+ // Test 30-minute window
+ when(configuration.getTimestampWindowSizeMillis()).thenReturn(1800000L);
+ String fileName30min = (String) method.invoke(producer, "test", ".txt", timestampWindow);
+ assertEquals("test_20240101_0800_0800-0830.txt", fileName30min);
+ }
+}
diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2S3ComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2S3ComponentBuilderFactory.java
index b778dcb9638..9c32260d8a4 100644
--- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2S3ComponentBuilderFactory.java
+++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2S3ComponentBuilderFactory.java
@@ -781,6 +781,62 @@ public interface Aws2S3ComponentBuilderFactory {
return this;
}
+
+ /**
+ * Enable timestamp-based grouping of messages into time windows for
+ * file creation. When enabled, messages are grouped by their timestamp
+ * header into time windows.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param timestampGroupingEnabled the value to set
+ * @return the dsl builder
+ */
+ default Aws2S3ComponentBuilder timestampGroupingEnabled(boolean timestampGroupingEnabled) {
+ doSetProperty("timestampGroupingEnabled", timestampGroupingEnabled);
+ return this;
+ }
+
+
+ /**
+ * The name of the message header containing the timestamp for grouping.
+ * Default is CamelMessageTimestamp.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: CamelMessageTimestamp
+ * Group: producer
+ *
+ * @param timestampHeaderName the value to set
+ * @return the dsl builder
+ */
+ default Aws2S3ComponentBuilder timestampHeaderName(java.lang.String timestampHeaderName) {
+ doSetProperty("timestampHeaderName", timestampHeaderName);
+ return this;
+ }
+
+
+ /**
+ * The size of the time window in milliseconds for timestamp-based
+ * grouping. Messages within the same time window will be written to the
+ * same file. Default is 300000 (5 minutes).
+ *
+ * The option is a: <code>long</code> type.
+ *
+ * Default: 300000
+ * Group: producer
+ *
+ * @param timestampWindowSizeMillis the value to set
+ * @return the dsl builder
+ */
+ default Aws2S3ComponentBuilder timestampWindowSizeMillis(long timestampWindowSizeMillis) {
+ doSetProperty("timestampWindowSizeMillis", timestampWindowSizeMillis);
+ return this;
+ }
+
/**
* Define the id of KMS key to use in case KMS is enabled.
*
@@ -1202,6 +1258,9 @@ public interface Aws2S3ComponentBuilderFactory {
case "storageClass": getOrCreateConfiguration((AWS2S3Component) component).setStorageClass((java.lang.String) value); return true;
case "streamingUploadMode": getOrCreateConfiguration((AWS2S3Component) component).setStreamingUploadMode((boolean) value); return true;
case "streamingUploadTimeout": getOrCreateConfiguration((AWS2S3Component) component).setStreamingUploadTimeout((long) value); return true;
+ case "timestampGroupingEnabled": getOrCreateConfiguration((AWS2S3Component) component).setTimestampGroupingEnabled((boolean) value); return true;
+ case "timestampHeaderName": getOrCreateConfiguration((AWS2S3Component) component).setTimestampHeaderName((java.lang.String) value); return true;
+ case "timestampWindowSizeMillis": getOrCreateConfiguration((AWS2S3Component) component).setTimestampWindowSizeMillis((long) value); return true;
case "awsKMSKeyId": getOrCreateConfiguration((AWS2S3Component) component).setAwsKMSKeyId((java.lang.String) value); return true;
case "conditionalWritesEnabled": getOrCreateConfiguration((AWS2S3Component) component).setConditionalWritesEnabled((boolean) value); return true;
case "useAwsKMS": getOrCreateConfiguration((AWS2S3Component) component).setUseAwsKMS((boolean) value); return true;
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AWS2S3EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AWS2S3EndpointBuilderFactory.java
index 0f2bcccc41e..63d794fb6c5 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AWS2S3EndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/AWS2S3EndpointBuilderFactory.java
@@ -2365,6 +2365,90 @@ public interface AWS2S3EndpointBuilderFactory {
doSetProperty("streamingUploadTimeout", streamingUploadTimeout);
return this;
}
+ /**
+ * Enable timestamp-based grouping of messages into time windows for
+ * file creation. When enabled, messages are grouped by their timestamp
+ * header into time windows.
+ *
+ * The option is a: <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param timestampGroupingEnabled the value to set
+ * @return the dsl builder
+ */
+ default AWS2S3EndpointProducerBuilder timestampGroupingEnabled(boolean timestampGroupingEnabled) {
+ doSetProperty("timestampGroupingEnabled", timestampGroupingEnabled);
+ return this;
+ }
+ /**
+ * Enable timestamp-based grouping of messages into time windows for
+ * file creation. When enabled, messages are grouped by their timestamp
+ * header into time windows.
+ *
+ * The option will be converted to a <code>boolean</code> type.
+ *
+ * Default: false
+ * Group: producer
+ *
+ * @param timestampGroupingEnabled the value to set
+ * @return the dsl builder
+ */
+ default AWS2S3EndpointProducerBuilder timestampGroupingEnabled(String timestampGroupingEnabled) {
+ doSetProperty("timestampGroupingEnabled", timestampGroupingEnabled);
+ return this;
+ }
+ /**
+ * The name of the message header containing the timestamp for grouping.
+ * Default is CamelMessageTimestamp.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Default: CamelMessageTimestamp
+ * Group: producer
+ *
+ * @param timestampHeaderName the value to set
+ * @return the dsl builder
+ */
+ default AWS2S3EndpointProducerBuilder timestampHeaderName(String timestampHeaderName) {
+ doSetProperty("timestampHeaderName", timestampHeaderName);
+ return this;
+ }
+ /**
+ * The size of the time window in milliseconds for timestamp-based
+ * grouping. Messages within the same time window will be written to the
+ * same file. Default is 300000 (5 minutes).
+ *
+ * The option is a: <code>long</code> type.
+ *
+ * Default: 300000
+ * Group: producer
+ *
+ * @param timestampWindowSizeMillis the value to set
+ * @return the dsl builder
+ */
+ default AWS2S3EndpointProducerBuilder timestampWindowSizeMillis(long timestampWindowSizeMillis) {
+ doSetProperty("timestampWindowSizeMillis", timestampWindowSizeMillis);
+ return this;
+ }
+ /**
+ * The size of the time window in milliseconds for timestamp-based
+ * grouping. Messages within the same time window will be written to the
+ * same file. Default is 300000 (5 minutes).
+ *
+ * The option will be converted to a <code>long</code> type.
+ *
+ * Default: 300000
+ * Group: producer
+ *
+ * @param timestampWindowSizeMillis the value to set
+ * @return the dsl builder
+ */
+ default AWS2S3EndpointProducerBuilder timestampWindowSizeMillis(String timestampWindowSizeMillis) {
+ doSetProperty("timestampWindowSizeMillis", timestampWindowSizeMillis);
+ return this;
+ }
/**
* To define a proxy host when instantiating the SQS client.
*