# SkillPatch skill: azure-cosmos-java

This skill provides comprehensive guidance for using the Azure Cosmos DB SDK for Java, covering both synchronous and asynchronous (reactive) client patterns. It includes installation via Maven, authentication methods (key-based and with customizations), and core workflows for database and container creation, as well as CRUD operations. It targets Java developers building NoSQL applications on Azure Cosmos DB.

You (the agent) were given this URL and asked to use this skill. This is a **public** skill — no SkillPatch account, API key, or prior setup is required. Two ways to use it:

**1. Use it right now** — the skill's complete file tree (SKILL.md + all reference files) is inlined below; read `SKILL.md` first, then follow it, consulting the other files as it directs.

**2. Install the exact package onto disk** (recommended if you can run a shell — this reproduces the skill byte-for-byte, including any binary assets that can't be inlined):

```bash
mkdir -p .claude/skills/azure-cosmos-java
curl -sSL https://skillpatch.dev/install_skill/azure-cosmos-java | tar -xz -C .claude/skills/
```

(`.claude/skills/` is Claude Code's convention; use whatever directory your agent loads skills from.)


---

## Skill files (2)

- `SKILL.md`
- `references/examples.md`


### `SKILL.md`

````markdown
---
name: azure-cosmos-java
description: |
  Azure Cosmos DB SDK for Java. NoSQL database operations with global distribution, multi-model support, and reactive patterns.
  Triggers: "CosmosClient java", "CosmosAsyncClient", "cosmos database java", "cosmosdb java", "document database java".
license: MIT
metadata:
  author: Microsoft
  version: "1.0.0"
  package: azure-cosmos
---

# Azure Cosmos DB SDK for Java

Client library for Azure Cosmos DB NoSQL API with global distribution and reactive patterns.

## Installation

```xml
<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-cosmos</artifactId>
    <version>LATEST</version>
</dependency>
```

Or use Azure SDK BOM:

```xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-sdk-bom</artifactId>
            <version>{bom_version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-cosmos</artifactId>
    </dependency>
</dependencies>
```

## Environment Variables

```bash
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_KEY=<your-primary-key>
```

## Authentication

### Key-based Authentication

```java
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;

CosmosClient client = new CosmosClientBuilder()
    .endpoint(System.getenv("COSMOS_ENDPOINT"))
    .key(System.getenv("COSMOS_KEY"))
    .buildClient();
```

### Async Client

```java
import com.azure.cosmos.CosmosAsyncClient;

CosmosAsyncClient asyncClient = new CosmosClientBuilder()
    .endpoint(serviceEndpoint)
    .key(key)
    .buildAsyncClient();
```

### With Customizations

```java
import com.azure.cosmos.ConsistencyLevel;
import java.util.Arrays;

CosmosClient client = new CosmosClientBuilder()
    .endpoint(serviceEndpoint)
    .key(key)
    .directMode(directConnectionConfig, gatewayConnectionConfig)
    .consistencyLevel(ConsistencyLevel.SESSION)
    .connectionSharingAcrossClientsEnabled(true)
    .contentResponseOnWriteEnabled(true)
    .userAgentSuffix("my-application")
    .preferredRegions(Arrays.asList("West US", "East US"))
    .buildClient();
```

## Client Hierarchy

| Class | Purpose |
|-------|---------|
| `CosmosClient` / `CosmosAsyncClient` | Account-level operations |
| `CosmosDatabase` / `CosmosAsyncDatabase` | Database operations |
| `CosmosContainer` / `CosmosAsyncContainer` | Container/item operations |

## Core Workflow

### Create Database

```java
// Sync
client.createDatabaseIfNotExists("myDatabase")
    .map(response -> client.getDatabase(response.getProperties().getId()));

// Async with chaining
asyncClient.createDatabaseIfNotExists("myDatabase")
    .map(response -> asyncClient.getDatabase(response.getProperties().getId()))
    .subscribe(database -> System.out.println("Created: " + database.getId()));
```

### Create Container

```java
asyncClient.createDatabaseIfNotExists("myDatabase")
    .flatMap(dbResponse -> {
        String databaseId = dbResponse.getProperties().getId();
        return asyncClient.getDatabase(databaseId)
            .createContainerIfNotExists("myContainer", "/partitionKey")
            .map(containerResponse -> asyncClient.getDatabase(databaseId)
                .getContainer(containerResponse.getProperties().getId()));
    })
    .subscribe(container -> System.out.println("Container: " + container.getId()));
```

### CRUD Operations

```java
import com.azure.cosmos.models.PartitionKey;

CosmosAsyncContainer container = asyncClient
    .getDatabase("myDatabase")
    .getContainer("myContainer");

// Create
container.createItem(new User("1", "John Doe", "john@example.com"))
    .flatMap(response -> {
        System.out.println("Created: " + response.getItem());
        // Read
        return container.readItem(
            response.getItem().getId(),
            new PartitionKey(response.getItem().getId()),
            User.class);
    })
    .flatMap(response -> {
        System.out.println("Read: " + response.getItem());
        // Update
        User user = response.getItem();
        user.setEmail("john.doe@example.com");
        return container.replaceItem(
            user,
            user.getId(),
            new PartitionKey(user.getId()));
    })
    .flatMap(response -> {
        // Delete
        return container.deleteItem(
            response.getItem().getId(),
            new PartitionKey(response.getItem().getId()));
    })
    .block();
```

### Query Documents

```java
import com.azure.cosmos.models.CosmosQueryRequestOptions;
import com.azure.cosmos.util.CosmosPagedIterable;

CosmosContainer container = client.getDatabase("myDatabase").getContainer("myContainer");

String query = "SELECT * FROM c WHERE c.status = @status";
CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();

CosmosPagedIterable<User> results = container.queryItems(
    query,
    options,
    User.class
);

results.forEach(user -> System.out.println("User: " + user.getName()));
```

## Key Concepts

### Partition Keys

Choose a partition key with:
- High cardinality (many distinct values)
- Even distribution of data and requests
- Frequently used in queries

### Consistency Levels

| Level | Guarantee |
|-------|-----------|
| Strong | Linearizability |
| Bounded Staleness | Consistent prefix with bounded lag |
| Session | Consistent prefix within session |
| Consistent Prefix | Reads never see out-of-order writes |
| Eventual | No ordering guarantee |

### Request Units (RUs)

All operations consume RUs. Check response headers:

```java
CosmosItemResponse<User> response = container.createItem(user);
System.out.println("RU charge: " + response.getRequestCharge());
```

## Best Practices

1. **Reuse CosmosClient** — Create once, reuse throughout application
2. **Use async client** for high-throughput scenarios
3. **Choose partition key carefully** — Affects performance and scalability
4. **Enable content response on write** for immediate access to created items
5. **Configure preferred regions** for geo-distributed applications
6. **Handle 429 errors** with retry policies (built-in by default)
7. **Use direct mode** for lowest latency in production

## Error Handling

```java
import com.azure.cosmos.CosmosException;

try {
    container.createItem(item);
} catch (CosmosException e) {
    System.err.println("Status: " + e.getStatusCode());
    System.err.println("Message: " + e.getMessage());
    System.err.println("Request charge: " + e.getRequestCharge());
    
    if (e.getStatusCode() == 409) {
        System.err.println("Item already exists");
    } else if (e.getStatusCode() == 429) {
        System.err.println("Rate limited, retry after: " + e.getRetryAfterDuration());
    }
}
```

## Reference Links

| Resource | URL |
|----------|-----|
| Maven Package | https://central.sonatype.com/artifact/com.azure/azure-cosmos |
| API Documentation | https://azuresdkdocs.z19.web.core.windows.net/java/azure-cosmos/latest/index.html |
| Product Docs | https://learn.microsoft.com/azure/cosmos-db/ |
| Samples | https://github.com/Azure-Samples/azure-cosmos-java-sql-api-samples |
| Performance Guide | https://learn.microsoft.com/azure/cosmos-db/performance-tips-java-sdk-v4-sql |
| Troubleshooting | https://learn.microsoft.com/azure/cosmos-db/troubleshoot-java-sdk-v4-sql |

````


### `references/examples.md`

````markdown
# Azure Cosmos DB Java SDK - Examples

Comprehensive code examples for the Azure Cosmos DB SDK for Java.

## Table of Contents

- [Maven Dependency](#maven-dependency)
- [Client Creation](#client-creation)
- [Database Operations](#database-operations)
- [Container Operations](#container-operations)
- [CRUD Operations (Sync)](#crud-operations-sync)
- [CRUD Operations (Async)](#crud-operations-async)
- [SQL Queries](#sql-queries)

---

## Maven Dependency

```xml
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.azure</groupId>
            <artifactId>azure-sdk-bom</artifactId>
            <version>{bom_version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-cosmos</artifactId>
    </dependency>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-identity</artifactId>
    </dependency>
</dependencies>
```

---

## Client Creation

### Synchronous Client (CosmosClient)

```java
import com.azure.cosmos.ConsistencyLevel;
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;
import java.util.Arrays;

// Basic client with key authentication
CosmosClient cosmosClient = new CosmosClientBuilder()
    .endpoint("<YOUR ENDPOINT HERE>")
    .key("<YOUR KEY HERE>")
    .buildClient();

// Client with full configuration
CosmosClient cosmosClient = new CosmosClientBuilder()
    .endpoint(serviceEndpoint)
    .key(key)
    .preferredRegions(Arrays.asList("West US", "East US"))
    .consistencyLevel(ConsistencyLevel.SESSION)
    .contentResponseOnWriteEnabled(true)
    .connectionSharingAcrossClientsEnabled(true)
    .userAgentSuffix("my-application-client")
    .buildClient();
```

### Asynchronous Client (CosmosAsyncClient)

```java
import com.azure.cosmos.CosmosAsyncClient;
import java.util.ArrayList;

ArrayList<String> preferredRegions = new ArrayList<>();
preferredRegions.add("West US");

CosmosAsyncClient cosmosAsyncClient = new CosmosClientBuilder()
    .endpoint(serviceEndpoint)
    .key(masterKey)
    .preferredRegions(preferredRegions)
    .consistencyLevel(ConsistencyLevel.SESSION)
    .contentResponseOnWriteEnabled(true)
    .buildAsyncClient();
```

### Client with DefaultAzureCredential (Recommended)

```java
import com.azure.identity.DefaultAzureCredentialBuilder;

CosmosClient cosmosClient = new CosmosClientBuilder()
    .endpoint(serviceEndpoint)
    .credential(new DefaultAzureCredentialBuilder().build())
    .preferredRegions(Arrays.asList("West US"))
    .consistencyLevel(ConsistencyLevel.SESSION)
    .contentResponseOnWriteEnabled(true)
    .buildClient();
```

---

## Database Operations

```java
import com.azure.cosmos.CosmosDatabase;
import com.azure.cosmos.models.CosmosDatabaseResponse;
import com.azure.cosmos.models.CosmosDatabaseRequestOptions;

// Create database if not exists
CosmosDatabaseResponse databaseResponse = cosmosClient.createDatabaseIfNotExists("AzureSampleFamilyDB");
CosmosDatabase database = cosmosClient.getDatabase(databaseResponse.getProperties().getId());

// Get existing database reference
CosmosDatabase database = cosmosClient.getDatabase("AzureSampleFamilyDB");

// Delete database
CosmosDatabaseResponse deleteResponse = database.delete(new CosmosDatabaseRequestOptions());
System.out.println("Status code for database delete: " + deleteResponse.getStatusCode());
```

---

## Container Operations

```java
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.models.CosmosContainerProperties;
import com.azure.cosmos.models.CosmosContainerResponse;
import com.azure.cosmos.models.ThroughputProperties;

// Create container with partition key and throughput
CosmosContainerProperties containerProperties = 
    new CosmosContainerProperties("FamilyContainer", "/lastName");

// Manual throughput (400 RU/s)
ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);

CosmosContainerResponse containerResponse = database.createContainerIfNotExists(
    containerProperties, 
    throughputProperties
);

CosmosContainer container = database.getContainer(containerResponse.getProperties().getId());

// Get existing container reference
CosmosContainer container = database.getContainer("FamilyContainer");

// Delete container
container.delete();
```

---

## CRUD Operations (Sync)

```java
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.CosmosException;
import com.azure.cosmos.models.CosmosItemRequestOptions;
import com.azure.cosmos.models.CosmosItemResponse;
import com.azure.cosmos.models.PartitionKey;
import java.time.Duration;

// ============ CREATE ============
Family family = new Family();
family.setId("AndersenFamily");
family.setLastName("Andersen");
family.setRegistered(true);

CosmosItemRequestOptions options = new CosmosItemRequestOptions();
CosmosItemResponse<Family> createResponse = container.createItem(
    family, 
    new PartitionKey(family.getLastName()), 
    options
);

System.out.printf("Created item with request charge of %.2f within duration %s%n",
    createResponse.getRequestCharge(), 
    createResponse.getDuration());

// ============ READ (Point Read) ============
try {
    CosmosItemResponse<Family> readResponse = container.readItem(
        "AndersenFamily",                    // id
        new PartitionKey("Andersen"),        // partition key
        Family.class
    );
    
    Family readFamily = readResponse.getItem();
    double requestCharge = readResponse.getRequestCharge();
    Duration requestLatency = readResponse.getDuration();
    
    System.out.printf("Read item id=%s with charge=%.2f, latency=%s%n",
        readFamily.getId(), requestCharge, requestLatency);
        
} catch (CosmosException e) {
    System.err.printf("Read failed with status code %d: %s%n", 
        e.getStatusCode(), e.getMessage());
}

// ============ UPDATE (Replace) ============
family.setDistrict("NewDistrict");
CosmosItemResponse<Family> replaceResponse = container.replaceItem(
    family,
    family.getId(),
    new PartitionKey(family.getLastName()),
    new CosmosItemRequestOptions()
);

System.out.printf("Replaced item id=%s, district=%s, charge=%.2f%n",
    replaceResponse.getItem().getId(),
    replaceResponse.getItem().getDistrict(),
    replaceResponse.getRequestCharge());

// ============ UPSERT (Create or Replace) ============
family.setRegistered(false);
CosmosItemResponse<Family> upsertResponse = container.upsertItem(family);

System.out.printf("Upserted item with charge=%.2f within duration %s%n",
    upsertResponse.getRequestCharge(), 
    upsertResponse.getDuration());

// ============ DELETE ============
container.deleteItem(
    family.getId(),
    new PartitionKey(family.getLastName()),
    new CosmosItemRequestOptions()
);
```

---

## CRUD Operations (Async)

```java
import com.azure.cosmos.CosmosAsyncContainer;
import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;

// ============ CREATE (Async) ============
Mono<CosmosItemResponse<Family>> createMono = cosmosAsyncContainer.createItem(family);

createMono.subscribe(response -> {
    System.out.printf("Created item with request charge of %.2f%n", 
        response.getRequestCharge());
});

// ============ CHAINED CRUD OPERATIONS ============
cosmosAsyncContainer.createItem(new Family("carla.davis@outlook.com", "Carla Davis"))
    .flatMap(response -> {
        System.out.println("Created item: " + response.getItem().getId());
        // Read that item
        return cosmosAsyncContainer.readItem(
            response.getItem().getId(),
            new PartitionKey(response.getItem().getLastName()), 
            Family.class
        );
    })
    .flatMap(response -> {
        System.out.println("Read item: " + response.getItem().getId());
        // Replace that item
        Family p = response.getItem();
        p.setDistrict("SFO");
        return cosmosAsyncContainer.replaceItem(
            p, 
            response.getItem().getId(),
            new PartitionKey(response.getItem().getLastName())
        );
    })
    .flatMap(response -> {
        // Delete that item
        return cosmosAsyncContainer.deleteItem(
            response.getItem().getId(),
            new PartitionKey(response.getItem().getLastName())
        );
    })
    .block(); // Block only for demo - avoid in production

// ============ BATCH CREATE (Async) ============
Flux<Family> familiesToCreate = Flux.just(family1, family2, family3, family4);

double totalCharge = familiesToCreate
    .flatMap(family -> cosmosAsyncContainer.createItem(family))
    .flatMap(itemResponse -> {
        System.out.printf("Created item ID: %s with charge %.2f%n",
            itemResponse.getItem().getId(),
            itemResponse.getRequestCharge());
        return Mono.just(itemResponse.getRequestCharge());
    })
    .reduce(0.0, Double::sum)
    .block();

System.out.printf("Total request charge: %.2f%n", totalCharge);
```

---

## SQL Queries

### Basic Queries

```java
import com.azure.cosmos.models.CosmosQueryRequestOptions;
import com.azure.cosmos.util.CosmosPagedIterable;

CosmosQueryRequestOptions queryOptions = new CosmosQueryRequestOptions();
queryOptions.setQueryMetricsEnabled(true);

// Query all documents
CosmosPagedIterable<Family> families = container.queryItems(
    "SELECT * FROM c", 
    queryOptions, 
    Family.class
);

for (Family family : families) {
    System.out.println("Family: " + family.getId());
}

// Query with WHERE clause
String query = "SELECT * FROM Family WHERE Family.lastName IN ('Andersen', 'Wakefield', 'Johnson')";
CosmosPagedIterable<Family> filteredFamilies = container.queryItems(
    query, 
    queryOptions, 
    Family.class
);
```

### Parameterized Queries (Recommended)

```java
import com.azure.cosmos.models.SqlParameter;
import com.azure.cosmos.models.SqlQuerySpec;
import java.util.ArrayList;

// Single parameter
ArrayList<SqlParameter> paramList = new ArrayList<>();
paramList.add(new SqlParameter("@id", "AndersenFamily"));

SqlQuerySpec querySpec = new SqlQuerySpec(
    "SELECT * FROM Families f WHERE (f.id = @id)",
    paramList
);

CosmosPagedIterable<Family> families = container.queryItems(
    querySpec, 
    new CosmosQueryRequestOptions(), 
    Family.class
);

// Multiple parameters
paramList = new ArrayList<>();
paramList.add(new SqlParameter("@id", "AndersenFamily"));
paramList.add(new SqlParameter("@city", "Seattle"));

querySpec = new SqlQuerySpec(
    "SELECT * FROM Families f WHERE f.id = @id AND f.Address.City = @city",
    paramList
);

CosmosPagedIterable<Family> result = container.queryItems(
    querySpec, 
    new CosmosQueryRequestOptions(), 
    Family.class
);
```

### Queries with Paging

```java
import com.azure.cosmos.models.FeedResponse;

String query = "SELECT * FROM Families";
int pageSize = 100;
String continuationToken = null;
double totalRequestCharge = 0.0;

do {
    CosmosQueryRequestOptions queryOptions = new CosmosQueryRequestOptions();
    
    Iterable<FeedResponse<Family>> feedResponseIterator = container
        .queryItems(query, queryOptions, Family.class)
        .iterableByPage(continuationToken, pageSize);

    for (FeedResponse<Family> page : feedResponseIterator) {
        System.out.printf("Page with %d items, charge: %.2f%n", 
            page.getResults().size(),
            page.getRequestCharge());
        
        totalRequestCharge += page.getRequestCharge();
        
        // Process items in this page
        for (Family family : page.getResults()) {
            System.out.println("  - " + family.getId());
        }
        
        // Get continuation token for next page
        continuationToken = page.getContinuationToken();
    }
} while (continuationToken != null);

System.out.printf("Total request charge: %.2f%n", totalRequestCharge);
```

````
