From 1ca011860217b0095e41395ab5729486a217924d Mon Sep 17 00:00:00 2001 From: Thomas Date: Tue, 6 Oct 2026 13:46:51 +0200 Subject: [PATCH] CSB-8937: Add support for blob version ID access - Add blob version ID demo route Co-Authored-By: Claude Opus 4.6 --- azure/README.md | 47 +++++++++++++ .../README.adoc | 10 +++ .../camel/sample/BlobVersionRouteBuilder.java | 66 +++++++++++++++++++ .../src/main/resources/application.yml | 2 +- 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 azure/README.md create mode 100644 azure/camel-example-spring-boot-azure-storage-blob/src/main/java/camel/sample/BlobVersionRouteBuilder.java diff --git a/azure/README.md b/azure/README.md new file mode 100644 index 000000000..a1f6b623c --- /dev/null +++ b/azure/README.md @@ -0,0 +1,47 @@ +# Azure Examples — Test Account Setup + +Some Azure examples require a real Azure Storage account (e.g. blob versioning). +See each example's own README for how to run it. + +## Prerequisites + +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) (`az`) +- An Azure subscription (a [free account](https://azure.microsoft.com/en-us/pricing/purchase-options/azure-account) works) + +## Create a Test Storage Account + +```bash +# Login +az login + +# Create a resource group (delete it when done to avoid charges) +az group create --name camel-test-rg --location northeurope + +# Create a General-purpose v2 storage account +az storage account create \ + --name cameltestblob \ + --resource-group camel-test-rg \ + --location northeurope \ + --sku Standard_LRS \ + --kind StorageV2 + +# Enable blob versioning (required for version ID operations) +az storage account blob-service-properties update \ + --account-name cameltestblob \ + --resource-group camel-test-rg \ + --enable-versioning true + +# Get the access key +az storage account keys list \ + --account-name cameltestblob \ + --resource-group camel-test-rg \ + --query '[0].value' -o tsv +``` + +## Clean Up + +Delete the resource group to remove all resources and stop billing: + +```bash +az group delete --name camel-test-rg --yes +``` diff --git a/azure/camel-example-spring-boot-azure-storage-blob/README.adoc b/azure/camel-example-spring-boot-azure-storage-blob/README.adoc index 02a401bab..31e9c8094 100644 --- a/azure/camel-example-spring-boot-azure-storage-blob/README.adoc +++ b/azure/camel-example-spring-boot-azure-storage-blob/README.adoc @@ -8,6 +8,7 @@ This example demonstrates how to use the Apache Camel Azure Storage Blob compone * Set and get blob index tags * Find blobs by tag filter expressions * Create and read blob snapshots +* List blob versions by version ID === Running Tests (Azurite) @@ -28,6 +29,15 @@ To run against a real Azure Storage account: export AZURE_STORAGE_CONTAINER_NAME=yourcontainer mvn spring-boot:run +On startup the *version-demo* route uploads a blob twice and lists all versions with their version IDs: + + === Blob Version ID Demo === + Uploaded version 1 + Uploaded version 2 + version-demo.txt -- versionId=2026-10-06T11:30:00.1234567Z + version-demo.txt -- versionId=2026-10-06T11:30:01.2345678Z + === Demo complete === + === Help and Contributions If you hit any problems please let us know on the https://camel.apache.org/community/mailing-list/[Camel Forums]. diff --git a/azure/camel-example-spring-boot-azure-storage-blob/src/main/java/camel/sample/BlobVersionRouteBuilder.java b/azure/camel-example-spring-boot-azure-storage-blob/src/main/java/camel/sample/BlobVersionRouteBuilder.java new file mode 100644 index 000000000..e6cdf908c --- /dev/null +++ b/azure/camel-example-spring-boot-azure-storage-blob/src/main/java/camel/sample/BlobVersionRouteBuilder.java @@ -0,0 +1,66 @@ +/* + * 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 camel.sample; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; + +import com.azure.storage.blob.BlobServiceClient; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.azure.storage.blob.BlobConstants; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class BlobVersionRouteBuilder extends RouteBuilder { + + @Autowired + private BlobServiceClient serviceClient; + + @Value("${azure.storage.container-name}") + private String containerName; + + @Override + public void configure() { + from("timer:versionDemo?repeatCount=1&delay=0") + .routeId("version-demo") + .process(ex -> serviceClient.createBlobContainerIfNotExists(containerName)) + .log("=== Blob Version ID Demo ===") + .setHeader(BlobConstants.BLOB_NAME, constant("version-demo.txt")) + .process(ex -> ex.getIn().setBody( + new ByteArrayInputStream("Hello Version 1".getBytes(StandardCharsets.UTF_8)))) + .to("azure-storage-blob://{{azure.storage.account-name}}/{{azure.storage.container-name}}" + + "?operation=uploadBlockBlob&serviceClient=#serviceClient") + .log("Uploaded version 1") + .removeHeaders("CamelAzureStorageBlob*") + .setHeader(BlobConstants.BLOB_NAME, constant("version-demo.txt")) + .process(ex -> ex.getIn().setBody( + new ByteArrayInputStream("Hello Version 2".getBytes(StandardCharsets.UTF_8)))) + .to("azure-storage-blob://{{azure.storage.account-name}}/{{azure.storage.container-name}}" + + "?operation=uploadBlockBlob&serviceClient=#serviceClient") + .log("Uploaded version 2") + .to("azure-storage-blob://{{azure.storage.account-name}}/{{azure.storage.container-name}}" + + "?operation=listBlobVersions&serviceClient=#serviceClient") + .split(body()) + .log(" ${body.name} -- versionId=${body.versionId}") + .end() + .log("=== Demo complete ==="); + } +} diff --git a/azure/camel-example-spring-boot-azure-storage-blob/src/main/resources/application.yml b/azure/camel-example-spring-boot-azure-storage-blob/src/main/resources/application.yml index 27d640bdc..83bb23502 100644 --- a/azure/camel-example-spring-boot-azure-storage-blob/src/main/resources/application.yml +++ b/azure/camel-example-spring-boot-azure-storage-blob/src/main/resources/application.yml @@ -19,7 +19,7 @@ azure: storage: account-name: ${AZURE_STORAGE_ACCOUNT_NAME:devstoreaccount1} access-key: ${AZURE_STORAGE_ACCESS_KEY} - container-name: ${AZURE_STORAGE_CONTAINER_NAME:testcontainer} + container-name: ${AZURE_STORAGE_CONTAINER_NAME:yourcontainer} camel: component: