DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Optimizing Java Applications for Arm64 in the Cloud
  • Mastering Multi-Cloud and Edge Data Synchronization: A Retail Use Case With KubeMQ’s Java SDK
  • Engineering LLMOps: Building Robust CI/CD Pipelines for LLM Applications on Google Cloud
  • Using Java for Developing Agentic AI Applications: The Enterprise-Ready Stack in 2026

Trending

  • From APIs to Actions: Rethinking Back-End Design for Agents
  • Smart Deployment Strategies for Modern Applications
  • Introduction to Tactical DDD With Java: Steps to Build Semantic Code
  • OpenAPI From Code With Spring and Java: A Recipe for Your CI
  1. DZone
  2. Coding
  3. Java
  4. MultiCloudJ: Building Cloud-Agnostic Applications in Java

MultiCloudJ: Building Cloud-Agnostic Applications in Java

MultiCloudJ is an open-source Java SDK from Salesforce helping developers to write their application once and run anywhere.

By 
Sandeep Pal user avatar
Sandeep Pal
·
Oct. 20, 25 · Analysis
Likes (3)
Comment
Save
Tweet
Share
4.1K Views

Join the DZone community and get the full member experience.

Join For Free

According to a 2024 Gartner report, more than 92% of large enterprises now operate in multi-cloud environments. This reflects strategic priorities such as geographic scalability, high availability, regulatory compliance, and cost optimization.

But with these benefits comes significant complexity. Each provider — AWS, GCP, Alibaba Cloud, and others — exposes its own APIs, semantics, and SDKs. As a result, development teams must reconcile divergent models for storage, databases, identity, and more. The outcome is often fragmented codebases filled with conditional logic, code forking, duplicated workflows, and costly rewrites when onboarding new providers. For large organizations, this slows delivery, increases operational risk, and erodes the developer experience.

Ideally, enterprises would rely on a shared abstraction layer - one that standardizes semantics across providers while encapsulating provider-specific details. Previous efforts, such as Apache Jclouds, attempted to solve this for a subset of services, such as blobstore, compute, and load balancers, but struggled with a REST-based architecture that lagged behind evolving cloud features, ultimately landing in the Apache Attic. This created a gap in the Java ecosystem: the need for an actively maintained, extensible SDK with deep, provider-backed integration.

MultiCloudJ, recently open-sourced by Salesforce, fills that gap. Built directly on official provider SDKs rather than raw REST APIs, it ensures compatibility with the latest features while offering cloud-neutral abstractions. With portable APIs, driver layers, and provider implementations, MultiCloudJ gives Java developers a modern, unified SDK for building cloud-agnostic applications.

The Multi-Cloud Challenge

Enterprises are rapidly adopting multi-cloud strategies to strengthen resilience, meet compliance needs, and avoid over-reliance on a single provider. The business motivations are clear:

  • Resilience and availability: Enable failover, disaster recovery, and regional deployments for low latency.
  • Compliance: Satisfy data sovereignty and regulatory requirements with regional providers.
  • Cost optimization: Run workloads on the most cost-effective cloud infrastructure.
  • Leverage: Reduce vendor lock-in and strengthen negotiation power with providers.
  • Time-to-market: Accelerate rollouts by avoiding costly rewrites tied to a single provider’s SDK.

Yet these benefits for the business often create challenges for developers. Each provider exposes unique SDKs and semantics, forcing teams to duplicate logic, maintain sprawling if/else, case switch branches, complete code forks, and manage inconsistent workflows. Onboarding a new provider typically requires expensive refactoring, while steep learning curves slow down delivery.

In practice, the strategic promise of multi-cloud often translates into day-to-day friction for engineers, who spend more time reconciling SDK differences than building business value.

Without MultiCloud SDK


The Need for a Unified Approach

This growing gap between enterprise strategy and developer experience calls for a new abstraction: a way to standardize cloud access without sacrificing provider capabilities. By offering consistent interfaces across storage, databases, and messaging services, such an approach reduces duplication, simplifies onboarding, and allows teams to focus on business logic instead of cloud-specific rewrites.

That need is what led to the creation of MultiCloudJ — an open-source Java SDK designed to make multi-cloud development practical and standardized.

With MultiCloud SDK


What Does MultiCloudJ Offer?

MultiCloudJ is a modular Java SDK that exposes cloud-neutral interfaces for some of the most commonly used cloud services:

  • Blob/Object storage: 
    • Backed by AWS S3, Google Cloud GCS, Alibaba OSS
  • Document stores: 
    • AWS DynamoDB, GCP Firestore, Alibaba Tablestore
  • Security Token Service (STS): for credential delegation
  • Pub/Sub (message queues): coming soon..

By encapsulating native provider SDKs behind a uniform API, MultiCloudJ centralizes provider-specific complexity. Applications interact only with portable abstractions, while the SDK manages request translation to a specific provider, semantic differences, and provides a consistent response.

Architecture Deep Dive

MultiCloudJ follows a three-layer architecture:

Architecture of MultiCloudJ SDK

1. Portable Layer (Public API)

Developer-facing layer with portable methods (such upload(), download(), delete()) for blobstore.

Java
BucketClient client = BucketClient.builder("aws")
  .withBucket("exampleBucket")
  .withRegion("us-east-1");

UploadRequest req = new UploadRequest.Builder()
  .withKey("foo/bar.jpg")
  .build();

UploadResponse res = client.upload(req, "sample-content");


Switching to GCP or Alibaba requires changing only the cloud-specific values, such as the provider name from “aws” to “gcp” or Alibaba; bucket name, region name, and business logic remain unchanged.

2. Driver Layer (Abstraction and Coordination)

Defines core operations and shared validation.

Java
public abstract class AbstractBlobStore {
  protected abstract UploadResponse doUpload(UploadRequest request);
  protected abstract void doDelete(String key);
}


This shields the public API from leaking provider details.

3. Provider Layer (Substrate Implementations)

Implements cloud-specific logic using native SDKs.

Java
public class AWSBlobStore extends AbstractBlobStore {
@Override
protected UploadResponse doUpload(UploadRequest request) {
  PutObjectRequest putReq = PutObjectRequest.builder()
    .bucket(bucket)
    .key(request.getKey())
    .build();
  s3Client.putObject(putReq, RequestBody.fromString(request.getContent()));
  return new UploadResponse(...);
  }
}


Design Benefits

  • Portability: Swap providers without rewriting application code.
  • Unified, cloud-agnostic interfaces: Write once and interact with multiple clouds through consistent APIs.
  • Extensibility: Onboard new providers or services without modifying existing code.
  • Flexibility: Override defaults or inject custom implementations as needed.
  • Uniform semantics: Normalize differences across providers to simplify development.
    • Example – Object deletion: AWS S3 returns 200 OK when deleting a non-existent object, while Google Cloud Storage returns 404 Not Found. MultiCloudJ abstracts this by providing a consistent, predictable response.
    • Example – Pagination: DynamoDB uses LastEvaluatedKey for continuation, while Firestore relies on the last document of a page. MultiCloudJ standardizes pagination into a uniform API.
  • Reliability: Robust error handling and retry mechanisms ensure consistent, dependable operation.

Note: MultiCloudJ strives for uniform semantics but does not replicate every provider-specific capability; there are always some rare exceptions. For example, global transactions are available in DynamoDB, Firestore, and CosmosDB, but not in Alibaba Tablestore. In such cases, the SDK throws explicit exceptions to signal unsupported features.

Real-World Use Cases

  • Global SaaS platforms: deploy to AWS in North America and Alibaba Cloud in Asia
  • Hybrid cloud deployments: route workloads by business unit or geography
  • Disaster recovery: maintain a fallback provider for failover
  • Cross-cloud replication: sync documents or blobs across providers
  • Migration: shift workloads between providers with minimal application changes

Getting Started for Developers

Maven Dependency

XML
<dependency>
  <groupId>com.salesforce.multicloudj</groupId>
  <artifactId>docstore-client</artifactId>
  <version>0.2.2</version>
</dependency>


Switch docstore with blobstore, sts, or provider modules.

Runtime Configuration

Include provider-specific modules with Maven profiles:

XML
<dependency>
  <groupId>com.salesforce.multicloudj</groupId>
  <artifactId>docstore-gcp</artifactId>
  <version>0.2.2</version>
</dependency>


Example: Writing to a Document Store

Java
CollectionOptions opts = new CollectionOptions.CollectionOptionsBuilder()
  .withTableName("books")
  .withPartitionKey("title")
  .withSortKey("author")
  .build();

DocStoreClient client = DocStoreClient.builder("aws")
  .withRegion("us-west-2")
  .withCollectionOptions(opts)
  .build();

Book book = new Book("YellowBook", "Zoe", "Seattle", 3.99f,
Map.of("Ch1", 5, "Ch2", 10), null);

client.create(new Document(book));


Switching to Firestore or Tablestore requires only updating provider and resource configs.

Lessons Learned in Building MultiCloudJ

Conformance Testing Across Providers

To ensure consistent behavior, all MultiCloudJ tests are written against abstract driver classes. This allows the same test suite to run across different providers, with each provider supplying its own configuration (credentials, resource names, etc.). This approach guarantees uniform behavior and quickly highlights any provider-specific deviations.

Testing in CI Environments

Running full integration tests in CI pipelines posed challenges, primarily because securely managing live credentials for multiple providers is risky. To solve this, the team used Wiremock as a proxy, recording and replaying provider responses. This enabled reliable CI testing without requiring actual provider credentials, while still validating real-world request/response flows.

Handling Cloud-Specific Features

MultiCloudJ generally avoids exposing features unique to a single provider, as doing so would compromise portability. However, in some cases, the team chose to implement provider-specific functionality at the SDK layer while keeping a consistent client-facing experience. For example, Google Cloud Storage lacks native multipart upload support, so MultiCloudJ implements it internally using composable objects — giving developers a seamless, uniform experience.

Defining Meaningful Semantics

Each provider has its own interpretation of common operations, making it critical to standardize semantics for developers. Some differences are simple, while others require more nuanced handling, such as pagination approaches for GCP Firestore, and no multi-part upload support in Google Cloud SDK natively. We need to design the common semantics very carefully to offer uniform behavior.

Leverage the cloud provider SDK instead of reinventing the wheel.

Leverage provider SDKs instead of reinventing the wheel. We considered reviving Apache jclouds, but building directly on raw REST APIs is impractical. Cloud providers’ SDKs already handle the heavy lifting - request signing, headers, authentication flows, TLS, error handling, and endpoint management. Recreating and maintaining all of that ourselves would be fragile, time-consuming, and unsustainable.

Conclusion

MultiCloudJ tackles one of the toughest challenges in enterprise cloud engineering: achieving portability without compromising capability. By abstracting core services through provider-backed APIs, it delivers a consistent developer experience and reduces the operational complexity of multi-cloud environments.

For enterprises navigating compliance, cost, and resilience requirements, MultiCloudJ offers a practical and sustainable path forward. The project is open source under Salesforce’s GitHub organization and welcomes community contributions and feedback: github.com/salesforce/multicloudj.

Software development kit applications Cloud Java (programming language)

Opinions expressed by DZone contributors are their own.

Related

  • Optimizing Java Applications for Arm64 in the Cloud
  • Mastering Multi-Cloud and Edge Data Synchronization: A Retail Use Case With KubeMQ’s Java SDK
  • Engineering LLMOps: Building Robust CI/CD Pipelines for LLM Applications on Google Cloud
  • Using Java for Developing Agentic AI Applications: The Enterprise-Ready Stack in 2026

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook