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 2026/04/16 09:40:44 UTC
(camel) branch main updated: CAMEL-23331: Add support for blob snapshot creation in camel-azure-storage-blob (#22638)
This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 037429fbe732 CAMEL-23331: Add support for blob snapshot creation in camel-azure-storage-blob (#22638)
037429fbe732 is described below
commit 037429fbe732b353d3b80751a907d9894febe83e
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Thu Apr 16 11:40:37 2026 +0200
CAMEL-23331: Add support for blob snapshot creation in camel-azure-storage-blob (#22638)
* CAMEL-23331: Add support for blob snapshot creation in camel-azure-storage-blob
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
Signed-off-by: Andrea Cosentino <an...@gmail.com>
* CAMEL-23331: Address review feedback — add getChangeFeed to enums list and fix copyBlob Javadoc
- BlobConfiguration: add getChangeFeed to the @UriParam producer enums list
(pre-existing gap — operation is valid in BlobOperationsDefinition and wired
in BlobProducer, but was missing from the metadata enum)
- BlobOperationsDefinition: fix copy-paste error in the copyBlob Javadoc
(was a duplicate of getChangeFeed's description)
Co-Authored-By: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---------
Signed-off-by: Andrea Cosentino <an...@gmail.com>
Co-authored-by: Claude Opus 4.6 <no...@anthropic.com>
---
.../catalog/components/azure-storage-blob.json | 9 ++++----
.../azure/storage/blob/azure-storage-blob.json | 9 ++++----
.../main/docs/azure-storage-blob-component.adoc | 12 +++++++++++
.../azure/storage/blob/BlobConfiguration.java | 2 +-
.../azure/storage/blob/BlobConstants.java | 4 ++++
.../azure/storage/blob/BlobExchangeHeaders.java | 5 +++++
.../storage/blob/BlobOperationsDefinition.java | 9 +++++---
.../component/azure/storage/blob/BlobProducer.java | 3 +++
.../storage/blob/client/BlobClientWrapper.java | 8 +++++++
.../storage/blob/operations/BlobOperations.java | 22 +++++++++++++++++++
.../blob/operations/BlobOperationsTest.java | 25 ++++++++++++++++++++++
.../endpoint/dsl/BlobEndpointBuilderFactory.java | 12 +++++++++++
12 files changed, 108 insertions(+), 12 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json
index 0959cfce0fa7..def0bf3906de 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/azure-storage-blob.json
@@ -63,7 +63,7 @@
"lazyStartProducer": { "index": 36, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
"maxConcurrency": { "index": 37, "kind": "property", "displayName": "Max Concurrency", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum number of parallel requests to use during upload with uploadBlockBlobChunk [...]
"maxSingleUploadSize": { "index": 38, "kind": "property", "displayName": "Max Single Upload Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum size in bytes for a single upload request with uploadBlockBlobChu [...]
- "operation": { "index": 39, "kind": "property", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getB [...]
+ "operation": { "index": 39, "kind": "property", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getB [...]
"pageBlobSize": { "index": 40, "kind": "property", "displayName": "Page Blob Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 512, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Specifies the maximum size for the page blob, up to 8 TB. The page blob [...]
"autowiredEnabled": { "index": 41, "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": 42, "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" },
@@ -75,7 +75,7 @@
"sourceBlobAccessKey": { "index": 48, "kind": "property", "displayName": "Source Blob 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.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Source Blob Access Key: for copyblob operation, sadly, we need to have an acc [...]
},
"headers": {
- "CamelAzureStorageBlobOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getBlobBloc [...]
+ "CamelAzureStorageBlobOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getBlobBloc [...]
"CamelAzureStorageBlobHttpHeaders": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "BlobHttpHeaders", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(uploadBlockBlob, commitBlobBlockList, createAppendBlob, createPageBlob) Additional parameters for a set of operations.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#BLOB_HTTP_HEA [...]
"CamelAzureStorageBlobETag": { "index": 2, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The E Tag of the blob", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#E_TAG" },
"CamelAzureStorageBlobCreationTime": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "OffsetDateTime", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creation time of the blob.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#CREATION_TIME" },
@@ -143,7 +143,8 @@
"CamelAzureStorageBlobSourceBlobContainerName": { "index": 65, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(copyBlob) The source blob container name to be used as source container name in a copy blob operation", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#SOURCE_BLOB_CONTAINER_NAME" },
"CamelAzureStorageBlobChangeFeedStartTime": { "index": 66, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "OffsetDateTime", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) It filters the results to return events approximately after the start time. Note: A few events belonging to the previous hour can also be returned. A few events belonging to this hour can [...]
"CamelAzureStorageBlobChangeFeedEndTime": { "index": 67, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "OffsetDateTime", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) It filters the results to return events approximately before the end time. Note: A few events belonging to the next hour can also be returned. A few events belonging to this hour can be miss [...]
- "CamelAzureStorageBlobContext": { "index": 68, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) This gives additional context that is passed through the Http pipeline during the service call.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#CHANGE_FEED_CONTEXT" }
+ "CamelAzureStorageBlobContext": { "index": 68, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) This gives additional context that is passed through the Http pipeline during the service call.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#CHANGE_FEED_CONTEXT" },
+ "CamelAzureStorageBlobSnapshotId": { "index": 69, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The snapshot identifier returned after creating a blob snapshot.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#BLOB_SNAPSHOT_ID" }
},
"properties": {
"accountName": { "index": 0, "kind": "path", "displayName": "Account Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Azure account name to be used for authentication with azure blob services" },
@@ -190,7 +191,7 @@
"downloadLinkExpiration": { "index": 41, "kind": "parameter", "displayName": "Download Link Expiration", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Override the default expiration (millis) of URL download link." },
"maxConcurrency": { "index": 42, "kind": "parameter", "displayName": "Max Concurrency", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum number of parallel requests to use during upload with uploadBlockBlobChun [...]
"maxSingleUploadSize": { "index": 43, "kind": "parameter", "displayName": "Max Single Upload Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum size in bytes for a single upload request with uploadBlockBlobCh [...]
- "operation": { "index": 44, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "get [...]
+ "operation": { "index": 44, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "get [...]
"pageBlobSize": { "index": 45, "kind": "parameter", "displayName": "Page Blob Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 512, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Specifies the maximum size for the page blob, up to 8 TB. The page blo [...]
"lazyStartProducer": { "index": 46, "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 [...]
"backoffErrorThreshold": { "index": 47, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
diff --git a/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json b/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json
index 0959cfce0fa7..def0bf3906de 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json
+++ b/components/camel-azure/camel-azure-storage-blob/src/generated/resources/META-INF/org/apache/camel/component/azure/storage/blob/azure-storage-blob.json
@@ -63,7 +63,7 @@
"lazyStartProducer": { "index": 36, "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fai [...]
"maxConcurrency": { "index": 37, "kind": "property", "displayName": "Max Concurrency", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum number of parallel requests to use during upload with uploadBlockBlobChunk [...]
"maxSingleUploadSize": { "index": 38, "kind": "property", "displayName": "Max Single Upload Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum size in bytes for a single upload request with uploadBlockBlobChu [...]
- "operation": { "index": 39, "kind": "property", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getB [...]
+ "operation": { "index": 39, "kind": "property", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getB [...]
"pageBlobSize": { "index": 40, "kind": "property", "displayName": "Page Blob Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 512, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Specifies the maximum size for the page blob, up to 8 TB. The page blob [...]
"autowiredEnabled": { "index": 41, "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": 42, "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" },
@@ -75,7 +75,7 @@
"sourceBlobAccessKey": { "index": 48, "kind": "property", "displayName": "Source Blob 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.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Source Blob Access Key: for copyblob operation, sadly, we need to have an acc [...]
},
"headers": {
- "CamelAzureStorageBlobOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getBlobBloc [...]
+ "CamelAzureStorageBlobOperation": { "index": 0, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "getBlobBloc [...]
"CamelAzureStorageBlobHttpHeaders": { "index": 1, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "BlobHttpHeaders", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(uploadBlockBlob, commitBlobBlockList, createAppendBlob, createPageBlob) Additional parameters for a set of operations.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#BLOB_HTTP_HEA [...]
"CamelAzureStorageBlobETag": { "index": 2, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The E Tag of the blob", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#E_TAG" },
"CamelAzureStorageBlobCreationTime": { "index": 3, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "OffsetDateTime", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "Creation time of the blob.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#CREATION_TIME" },
@@ -143,7 +143,8 @@
"CamelAzureStorageBlobSourceBlobContainerName": { "index": 65, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(copyBlob) The source blob container name to be used as source container name in a copy blob operation", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#SOURCE_BLOB_CONTAINER_NAME" },
"CamelAzureStorageBlobChangeFeedStartTime": { "index": 66, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "OffsetDateTime", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) It filters the results to return events approximately after the start time. Note: A few events belonging to the previous hour can also be returned. A few events belonging to this hour can [...]
"CamelAzureStorageBlobChangeFeedEndTime": { "index": 67, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "OffsetDateTime", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) It filters the results to return events approximately before the end time. Note: A few events belonging to the next hour can also be returned. A few events belonging to this hour can be miss [...]
- "CamelAzureStorageBlobContext": { "index": 68, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) This gives additional context that is passed through the Http pipeline during the service call.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#CHANGE_FEED_CONTEXT" }
+ "CamelAzureStorageBlobContext": { "index": 68, "kind": "header", "displayName": "", "group": "producer", "label": "producer", "required": false, "javaType": "Context", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "(getChangeFeed) This gives additional context that is passed through the Http pipeline during the service call.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#CHANGE_FEED_CONTEXT" },
+ "CamelAzureStorageBlobSnapshotId": { "index": 69, "kind": "header", "displayName": "", "group": "consumer", "label": "consumer", "required": false, "javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The snapshot identifier returned after creating a blob snapshot.", "constantName": "org.apache.camel.component.azure.storage.blob.BlobConstants#BLOB_SNAPSHOT_ID" }
},
"properties": {
"accountName": { "index": 0, "kind": "path", "displayName": "Account Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Azure account name to be used for authentication with azure blob services" },
@@ -190,7 +191,7 @@
"downloadLinkExpiration": { "index": 41, "kind": "parameter", "displayName": "Download Link Expiration", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Override the default expiration (millis) of URL download link." },
"maxConcurrency": { "index": 42, "kind": "parameter", "displayName": "Max Concurrency", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum number of parallel requests to use during upload with uploadBlockBlobChun [...]
"maxSingleUploadSize": { "index": 43, "kind": "parameter", "displayName": "Max Single Upload Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "The maximum size in bytes for a single upload request with uploadBlockBlobCh [...]
- "operation": { "index": 44, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "get [...]
+ "operation": { "index": 44, "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "enum", "javaType": "org.apache.camel.component.azure.storage.blob.BlobOperationsDefinition", "enum": [ "listBlobContainers", "createBlobContainer", "deleteBlobContainer", "listBlobs", "getBlob", "deleteBlob", "downloadBlobToFile", "downloadLink", "uploadBlockBlob", "uploadBlockBlobChunked", "stageBlockBlobList", "commitBlobBlockList", "get [...]
"pageBlobSize": { "index": 45, "kind": "parameter", "displayName": "Page Blob Size", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": 512, "configurationClass": "org.apache.camel.component.azure.storage.blob.BlobConfiguration", "configurationField": "configuration", "description": "Specifies the maximum size for the page blob, up to 8 TB. The page blo [...]
"lazyStartProducer": { "index": 46, "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 [...]
"backoffErrorThreshold": { "index": 47, "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "autowired": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc
index f5a8dbdd9cad..d439981e2633 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/docs/azure-storage-blob-component.adoc
@@ -164,6 +164,7 @@ and existing blocks together. Any blocks not specified in the block list and per
|`clearPageBlob`|`PageBlob`| Free the specified pages from the page blob. The size of the range must be a multiple of 512.
|`getPageBlobRanges`|`PageBlob`|Returns the list of valid page ranges for a page blob or snapshot of a page blob.
|`copyBlob`|`Common`|Copy a blob from one container to another one, even from different accounts.
+|`createBlobSnapshot`|`Common`|Creates a read-only snapshot of a blob. The snapshot ID is returned in the `CamelAzureStorageBlobSnapshotId` header.
|===
Refer to the example section in this page to learn how to use these operations into your camel application.
@@ -713,6 +714,17 @@ from("direct:copyBlob")
In this way the `file.txt` in the container `containerblob1` of the account `account`, will be copied to the container `containerblob2` of the same account.
+- `createBlobSnapshot`
+
+[source,java]
+--------------------------------------------------------------------------------
+
+from("direct:createBlobSnapshot")
+ .to("azure-storage-blob://camelazure/container1?blobName=hello.txt&operation=createBlobSnapshot&serviceClient=#client")
+ .log("Snapshot ID: ${header.CamelAzureStorageBlobSnapshotId}")
+ .to("mock:result");
+--------------------------------------------------------------------------------
+
=== SAS Token generation example
SAS Blob Container tokens can be generated programmatically or via Azure UI. To generate the token with java code, the following can be done:
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConfiguration.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConfiguration.java
index f5bc41119835..93262cab1995 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConfiguration.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConfiguration.java
@@ -51,7 +51,7 @@ public class BlobConfiguration implements Cloneable {
@UriParam(label = "producer",
enums = "listBlobContainers,createBlobContainer,deleteBlobContainer,listBlobs,getBlob,deleteBlob,downloadBlobToFile,downloadLink,"
+ "uploadBlockBlob,uploadBlockBlobChunked,stageBlockBlobList,commitBlobBlockList,getBlobBlockList,createAppendBlob,commitAppendBlob,createPageBlob,uploadPageBlob,resizePageBlob,"
- + "clearPageBlob,getPageBlobRanges",
+ + "clearPageBlob,getPageBlobRanges,getChangeFeed,copyBlob,createBlobSnapshot",
defaultValue = "listBlobContainers")
private BlobOperationsDefinition operation = BlobOperationsDefinition.listBlobContainers;
@UriParam(label = "common")
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConstants.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConstants.java
index c9608662e456..36759be2d68b 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConstants.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobConstants.java
@@ -283,6 +283,10 @@ public final class BlobConstants {
description = "(getChangeFeed) This gives additional context that is passed through the Http pipeline during the service call.",
javaType = "Context")
public static final String CHANGE_FEED_CONTEXT = HEADER_PREFIX + "Context";
+ @Metadata(label = "consumer",
+ description = "The snapshot identifier returned after creating a blob snapshot.",
+ javaType = "String")
+ public static final String BLOB_SNAPSHOT_ID = HEADER_PREFIX + "SnapshotId";
private BlobConstants() {
}
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobExchangeHeaders.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobExchangeHeaders.java
index 1725faba9ae7..cbeba193c098 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobExchangeHeaders.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobExchangeHeaders.java
@@ -476,4 +476,9 @@ public class BlobExchangeHeaders {
headers.put(BlobConstants.RAW_HTTP_HEADERS, httpHeaders);
return this;
}
+
+ public BlobExchangeHeaders snapshotId(final String snapshotId) {
+ headers.put(BlobConstants.BLOB_SNAPSHOT_ID, snapshotId);
+ return this;
+ }
}
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobOperationsDefinition.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobOperationsDefinition.java
index 5442aabdde9b..ecdac66f6c0a 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobOperationsDefinition.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobOperationsDefinition.java
@@ -134,8 +134,11 @@ public enum BlobOperationsDefinition {
*/
getChangeFeed,
/**
- * Returns transaction logs of all the changes that occur to the blobs and the blob metadata in your storage
- * account. The change feed provides ordered, guaranteed, durable, immutable, read-only log of these changes.
+ * Copy a blob from one container to another one, even from different accounts.
+ */
+ copyBlob,
+ /**
+ * Creates a read-only snapshot of a blob. The snapshot ID is returned in the exchange headers.
*/
- copyBlob
+ createBlobSnapshot
}
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobProducer.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobProducer.java
index b5ad91de57f6..601b8fec3c1c 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobProducer.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobProducer.java
@@ -129,6 +129,9 @@ public class BlobProducer extends DefaultProducer {
case copyBlob:
setResponse(exchange, getBlobOperations(exchange).copyBlob(exchange));
break;
+ case createBlobSnapshot:
+ setResponse(exchange, getBlobOperations(exchange).createBlobSnapshot(exchange));
+ break;
default:
throw new IllegalArgumentException("Unsupported operation");
}
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/client/BlobClientWrapper.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/client/BlobClientWrapper.java
index 40f00517b9e6..020f2822a089 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/client/BlobClientWrapper.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/client/BlobClientWrapper.java
@@ -60,6 +60,7 @@ import com.azure.storage.blob.options.ListPageRangesOptions;
import com.azure.storage.blob.sas.BlobSasPermission;
import com.azure.storage.blob.sas.BlobServiceSasSignatureValues;
import com.azure.storage.blob.specialized.AppendBlobClient;
+import com.azure.storage.blob.specialized.BlobClientBase;
import com.azure.storage.blob.specialized.BlobInputStream;
import com.azure.storage.blob.specialized.BlobLeaseClient;
import com.azure.storage.blob.specialized.BlobLeaseClientBuilder;
@@ -328,6 +329,13 @@ public class BlobClientWrapper {
return client.getPageBlobClient();
}
+ public Response<BlobClientBase> createSnapshot(
+ final Map<String, String> metadata,
+ final BlobRequestConditions requestConditions,
+ final Duration timeout) {
+ return client.createSnapshotWithResponse(metadata, requestConditions, timeout, Context.NONE);
+ }
+
public BlobLeaseClient getLeaseClient() {
return new BlobLeaseClientBuilder().blobClient(client).buildClient();
}
diff --git a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperations.java b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperations.java
index c577d3604715..61ef7ec079b3 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperations.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperations.java
@@ -50,6 +50,7 @@ import com.azure.storage.blob.models.PageRangeItem;
import com.azure.storage.blob.models.ParallelTransferOptions;
import com.azure.storage.blob.sas.BlobSasPermission;
import com.azure.storage.blob.sas.BlobServiceSasSignatureValues;
+import com.azure.storage.blob.specialized.BlobClientBase;
import com.azure.storage.blob.specialized.BlobLeaseClient;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
@@ -581,6 +582,27 @@ public class BlobOperations {
return BlobOperationResponse.create(response);
}
+ public BlobOperationResponse createBlobSnapshot(final Exchange exchange) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Creating a snapshot of blob [{}] from exchange [{}]...", configurationProxy.getBlobName(exchange),
+ exchange);
+ }
+
+ final BlobCommonRequestOptions commonRequestOptions = getCommonRequestOptions(exchange);
+
+ final Response<BlobClientBase> response = client.createSnapshot(
+ commonRequestOptions.getMetadata(),
+ commonRequestOptions.getBlobRequestConditions(),
+ commonRequestOptions.getTimeout());
+
+ final BlobClientBase snapshotClient = response.getValue();
+ final BlobExchangeHeaders exchangeHeaders = BlobExchangeHeaders.create()
+ .snapshotId(snapshotClient.getSnapshotId())
+ .httpHeaders(response.getHeaders());
+
+ return BlobOperationResponse.create(snapshotClient.getSnapshotId(), exchangeHeaders.toMap());
+ }
+
private DownloadRetryOptions getDownloadRetryOptions(final BlobConfigurationOptionsProxy configurationProxy) {
return new DownloadRetryOptions().setMaxRetryRequests(configurationProxy.getMaxRetryRequests());
}
diff --git a/components/camel-azure/camel-azure-storage-blob/src/test/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperationsTest.java b/components/camel-azure/camel-azure-storage-blob/src/test/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperationsTest.java
index 12c28cad6832..0cc1303c7c54 100644
--- a/components/camel-azure/camel-azure-storage-blob/src/test/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperationsTest.java
+++ b/components/camel-azure/camel-azure-storage-blob/src/test/java/org/apache/camel/component/azure/storage/blob/operations/BlobOperationsTest.java
@@ -32,6 +32,7 @@ import com.azure.core.http.rest.ResponseBase;
import com.azure.storage.blob.models.BlobDownloadHeaders;
import com.azure.storage.blob.models.BlobProperties;
import com.azure.storage.blob.models.BlockBlobItem;
+import com.azure.storage.blob.specialized.BlobClientBase;
import com.azure.storage.blob.specialized.BlobLeaseClient;
import org.apache.camel.Exchange;
import org.apache.camel.component.azure.storage.blob.BlobBlock;
@@ -205,6 +206,30 @@ class BlobOperationsTest extends CamelTestSupport {
assertTrue((boolean) response.getBody());
}
+ @Test
+ void testCreateBlobSnapshot() {
+ final String snapshotId = "2026-04-15T10:00:00.0000000Z";
+ final HttpHeaders httpHeaders = new HttpHeaders().set("x-test-header", "123");
+
+ final BlobClientBase snapshotClient = mock(BlobClientBase.class);
+ when(snapshotClient.getSnapshotId()).thenReturn(snapshotId);
+
+ when(client.createSnapshot(any(), any(), any()))
+ .thenReturn(new ResponseBase<>(null, 201, httpHeaders, snapshotClient, null));
+
+ final Exchange exchange = new DefaultExchange(context);
+
+ final BlobOperations operations = new BlobOperations(configuration, client);
+ final BlobOperationResponse response = operations.createBlobSnapshot(exchange);
+
+ assertNotNull(response);
+ assertEquals(snapshotId, response.getBody());
+ assertNotNull(response.getHeaders());
+ assertEquals(snapshotId, response.getHeaders().get(BlobConstants.BLOB_SNAPSHOT_ID));
+ assertEquals("123", ((HttpHeaders) response.getHeaders().get(BlobConstants.RAW_HTTP_HEADERS))
+ .get("x-test-header").getValue());
+ }
+
private BlobProperties createBlobProperties() {
return new BlobProperties(
OffsetDateTime.now(), null, null, 0L, null, null, null, null, null,
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BlobEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BlobEndpointBuilderFactory.java
index a3c7f1e6136e..61deb2a93d16 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BlobEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/BlobEndpointBuilderFactory.java
@@ -4270,6 +4270,18 @@ public interface BlobEndpointBuilderFactory {
public String azureStorageBlobContext() {
return "CamelAzureStorageBlobContext";
}
+ /**
+ * The snapshot identifier returned after creating a blob snapshot.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: consumer
+ *
+ * @return the name of the header {@code AzureStorageBlobSnapshotId}.
+ */
+ public String azureStorageBlobSnapshotId() {
+ return "CamelAzureStorageBlobSnapshotId";
+ }
}
static BlobEndpointBuilder endpointBuilder(String componentName, String path) {
class BlobEndpointBuilderImpl extends AbstractEndpointBuilder implements BlobEndpointBuilder, AdvancedBlobEndpointBuilder {