Skip to content

Refactor to multi-module Java 11 cloud storage SDK with official CSP SDKs - #65

Merged
maheshkumargangula merged 19 commits into
v1.4.10from
claude/cloud-storage-actions-F9tgm
Mar 13, 2026
Merged

Refactor to multi-module Java 11 cloud storage SDK with official CSP SDKs#65
maheshkumargangula merged 19 commits into
v1.4.10from
claude/cloud-storage-actions-F9tgm

Conversation

@maheshkumargangula

Copy link
Copy Markdown
Collaborator

Summary

Complete refactor of the Sunbird Cloud Storage SDK from a single Scala/jclouds-based module to a multi-module pure Java 11 Maven project using official cloud provider SDKs. This is a breaking change released as version 2.0.0.

Key Changes

  • Architecture: Converted from monolithic Scala codebase to modular Maven structure with separate implementations for each cloud provider

    • cloud-storage-sdk-api: Core interfaces, models, factory, and shared abstractions
    • cloud-storage-sdk-aws: AWS S3 and Ceph S3 (via endpoint override)
    • cloud-storage-sdk-azure: Azure Blob Storage
    • cloud-storage-sdk-gcp: Google Cloud Storage
    • cloud-storage-sdk-oci: Oracle Cloud Infrastructure Object Storage
  • Language & Runtime: Upgraded from Scala to pure Java 11, replacing all Scala source files with Java equivalents

  • Dependencies: Replaced jclouds with official cloud SDKs:

    • AWS SDK v2 (2.25.0)
    • Azure Storage Blob SDK (12.25.0)
    • Google Cloud Storage SDK (2.30.0)
    • OCI Java SDK (3.30.0)
    • Removed Scala, jclouds, and Joda-Time dependencies
  • Core Implementation:

    • AbstractStorageService: Shared orchestration logic for upload, download, signed URLs, delete, copy, search, and metadata operations
    • StorageServiceFactory: ServiceLoader-based factory for dynamic provider discovery
    • StorageConfig: Builder pattern configuration supporting multiple auth types (ACCESS_KEY, OIDC, IAM, IAM_ROLE, INSTANCE_PROFILE)
    • Blob and DeleteTarget models replacing Scala case classes
  • Utilities: Replaced Joda-Time with Java 11 java.time API in DateRangeUtil; added FileUtil for file operations and zip extraction

  • Testing:

    • Unit tests using JUnit 5 with in-memory storage implementation (no credentials required)
    • Integration test base class with environment variable guards to skip tests when credentials unavailable
    • CSP-specific integration tests for AWS, Azure, GCP, and OCI
  • Documentation: Added comprehensive PLAN.md and TESTING.md guides

  • CI/CD: Updated GitHub Actions and CircleCI configurations for Java 11 builds

Notable Implementation Details

  • Ceph S3: Integrated into AWS module via configurable endpoint override (no separate module)
  • OCI Authentication: Supports both Instance Principal and explicit credentials
  • Signed URLs: CSP-specific implementations with configurable TTL
  • Retry Logic: Configurable retry mechanism in abstract base class
  • Service Discovery: Uses Java ServiceLoader SPI for provider registration via META-INF/services

https://claude.ai/code/session_01KrRXhCQDoUCac99315Fnh6

claude and others added 19 commits February 19, 2026 10:18
…tations

Replace the single Scala/jclouds-based module with a multi-module pure Java 11
Maven project. Each CSP (AWS, Azure, GCP, OCI) gets its own module using the
official cloud SDK, with OIDC-based auth as the primary approach and Access Key
as a configurable fallback.

Modules:
- cloud-storage-sdk-api: Interface, models, factory (ServiceLoader), abstract base
- cloud-storage-sdk-aws: AWS S3 + Ceph S3 support (AWS SDK v2)
- cloud-storage-sdk-azure: Azure Blob Storage (azure-storage-blob + azure-identity)
- cloud-storage-sdk-gcp: Google Cloud Storage (google-cloud-storage)
- cloud-storage-sdk-oci: OCI Object Storage (oci-java-sdk-objectstorage)

Key changes:
- Drop jclouds, Scala, and Joda-Time dependencies entirely
- Pure Java 11 with java.time for date operations
- ServiceLoader-based CSP discovery via StorageServiceProvider SPI
- StorageConfig uses Builder pattern with AuthType and StorageType enums
- AbstractStorageService provides shared orchestration (retry, search, copy, etc.)
- IStorageService extends AutoCloseable for try-with-resources support

https://claude.ai/code/session_01KrRXhCQDoUCac99315Fnh6
- API module: unit tests for DateRangeUtil, FileUtil, and
  AbstractStorageService (in-memory implementation, no credentials)
- CSP modules: integration tests extending BaseStorageServiceIntegrationTest
  that auto-skip via JUnit 5 assumeTrue() when env vars are absent
- API POM: publish test-jar so CSP modules can extend the base test class
- CSP POMs: depend on api test-jar for shared test infrastructure
- TESTING.md: comprehensive guide covering env vars, auth types, and
  examples for running tests from cloud-permissioned VMs

https://claude.ai/code/session_01KrRXhCQDoUCac99315Fnh6
Captures module layout, key source files, StorageConfig/AuthType enums,
the 12 AbstractStorageService primitives, per-CSP auth patterns, service
discovery via ServiceLoader, test strategy, build commands, package
structure, and common modification patterns.

https://claude.ai/code/session_01KrRXhCQDoUCac99315Fnh6
CircleCI is no longer used. Removes .circleci/config.yml and the
corresponding reference in PLAN.md Phase 6.

https://claude.ai/code/session_01KrRXhCQDoUCac99315Fnh6
- Add managed dependency for cloud-storage-sdk-api test-jar classifier
  in parent POM so CSP modules resolve the version correctly
- Pin maven-jar-plugin to 3.3.0 in pluginManagement
- Add GitHub Actions CI workflow (ci.yml) for build + test on push/PR
- Add GitHub Actions SonarCloud workflow (sonar.yml) for static analysis

https://claude.ai/code/session_01KrRXhCQDoUCac99315Fnh6
Compute a relativePath for files under a directory and join it to objectKey with an explicit '/' separator before calling upload. This prevents malformed object keys when objectKey doesn't end with a separator and preserves the directory structure during recursive (sync and async) uploads. The change extracts the relative path calculation and applies it in both upload loops.
Problem: Used .toList() method which is only available in Java 16+, but project targets Java 11.

  Solution: Replaced .toList() with .collect(Collectors.toList()) and added Collectors import.
fix: Decoding blob url since azure sdk percent-encodes the blob name
fix: Update test cases to cover the optional slash in objectKey
@maheshkumargangula
maheshkumargangula merged commit 7460f82 into v1.4.10 Mar 13, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants