Skip to content

Commit 37f3e90

Browse files
authored
Merge pull request #38 from AzureCosmosDB/copilot/add-cosmositemresponse-unwrapping-guidance
Add readItem() / CosmosItemResponse unwrapping guidance to sdk-java-content-response rule
2 parents 71ef5ef + d0cbf8b commit 37f3e90

2 files changed

Lines changed: 124 additions & 16 deletions

File tree

skills/cosmosdb-best-practices/AGENTS.md

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Performance optimization and best practices guide for Azure Cosmos DB applicatio
5555
- 4.6 [Configure SSL and connection mode for Cosmos DB Emulator](#46-configure-ssl-and-connection-mode-for-cosmos-db-emulator)
5656
- 4.7 [Use ETags for optimistic concurrency on read-modify-write operations](#47-use-etags-for-optimistic-concurrency-on-read-modify-write-operations)
5757
- 4.8 [Configure Excluded Regions for Dynamic Failover](#48-configure-excluded-regions-for-dynamic-failover)
58-
- 4.9 [Enable content response on write operations in Java SDK](#49-enable-content-response-on-write-operations-in-java-sdk)
58+
- 4.9 [Unwrap CosmosItemResponse and enable content response in Java SDK](#49-unwrap-cosmositemresponse-and-enable-content-response-in-java-sdk)
5959
- 4.10 [Use dependent @Bean methods for Cosmos DB initialization in Spring Boot](#410-use-dependent-bean-methods-for-cosmos-db-initialization-in-spring-boot)
6060
- 4.11 [Spring Boot and Java version compatibility for Cosmos DB SDK](#411-spring-boot-and-java-version-compatibility-for-cosmos-db-sdk)
6161
- 4.12 [Configure local development environment to avoid cloud connection conflicts](#412-configure-local-development-environment-to-avoid-cloud-connection-conflicts)
@@ -3589,11 +3589,64 @@ var outageOptions = new ItemRequestOptions
35893589
Reference: [Performance tips - .NET SDK Excluded Regions](https://learn.microsoft.com/en-us/azure/cosmos-db/performance-tips-dotnet-sdk-v3#excluded-regions)
35903590
Reference: [Performance tips - Java SDK Excluded Regions](https://learn.microsoft.com/en-us/azure/cosmos-db/performance-tips-java-sdk-v4#excluded-regions)
35913591

3592-
### 4.9 Enable content response on write operations in Java SDK
3592+
### 4.9 Unwrap CosmosItemResponse and enable content response in Java SDK
35933593

3594-
**Impact: MEDIUM** (ensures created/updated documents are returned from write operations)
3594+
**Impact: MEDIUM** (prevents type errors from missing getItem() on reads and null content on writes)
35953595

3596-
## Enable Content Response on Write Operations (Java)
3596+
## Unwrap CosmosItemResponse with getItem() (Java)
3597+
3598+
All Cosmos DB Java SDK point-read and write operations (`readItem`, `createItem`, `upsertItem`, `replaceItem`) return `CosmosItemResponse<T>`, **not** `T` directly. You must call `.getItem()` to extract the entity. Treating the response wrapper as the entity causes compilation errors or incorrect behavior.
3599+
3600+
### Always unwrap readItem() with getItem()
3601+
3602+
`readItem()` always returns `CosmosItemResponse<T>`. You must call `.getItem()` to get the actual document.
3603+
3604+
**Incorrect — treating CosmosItemResponse as the entity:**
3605+
3606+
```java
3607+
// ❌ WRONG: readItem returns CosmosItemResponse<Player>, NOT Player
3608+
public Player getPlayer(String playerId) {
3609+
Player player = container.readItem(
3610+
playerId, new PartitionKey(playerId), Player.class); // ❌ Compilation error!
3611+
return player;
3612+
}
3613+
```
3614+
3615+
```java
3616+
// ❌ WRONG (async): Mono<CosmosItemResponse<Player>> is not Mono<Player>
3617+
public Mono<Player> getPlayer(String playerId) {
3618+
return container.readItem(
3619+
playerId, new PartitionKey(playerId), Player.class); // ❌ Type mismatch!
3620+
}
3621+
```
3622+
3623+
**Correct — unwrap with getItem():**
3624+
3625+
```java
3626+
// ✅ CORRECT: Call getItem() to extract the entity from the response
3627+
public Player getPlayer(String playerId) {
3628+
CosmosItemResponse<Player> response = container.readItem(
3629+
playerId, new PartitionKey(playerId), Player.class);
3630+
return response.getItem(); // ✅ Returns the Player entity
3631+
}
3632+
```
3633+
3634+
```java
3635+
// ✅ CORRECT (async): Map the response to extract the entity
3636+
public Mono<Player> getPlayer(String playerId) {
3637+
return container.readItem(
3638+
playerId, new PartitionKey(playerId), Player.class)
3639+
.map(response -> response.getItem()); // ✅ Unwrap to Player
3640+
}
3641+
```
3642+
3643+
> **Why this matters:** `CosmosItemResponse<T>` is a wrapper that holds the entity (`getItem()`),
3644+
> request charge (`getRequestCharge()`), ETag (`getETag()`), headers, and diagnostics.
3645+
> Assigning the response directly to a variable of type `T` is a compile-time error in
3646+
> synchronous code and a type-mismatch error in reactive chains. This affects `readItem`,
3647+
> `createItem`, `upsertItem`, and `replaceItem` — all return `CosmosItemResponse<T>`.
3648+
3649+
### Enable Content Response on Write Operations
35973650

35983651
By default, the Java Cosmos DB SDK does **not** return the document content after create/upsert operations. The response contains only metadata (headers, diagnostics) but the `getItem()` method returns null. You must explicitly enable content response if you need the created document.
35993652

@@ -3693,11 +3746,12 @@ for (Order order : ordersToInsert) {
36933746
Enabling content response does NOT increase RU cost - the document is already fetched server-side for the write operation. It only affects the response payload size over the network.
36943747

36953748
**Key Points:**
3696-
- Java SDK returns null by default for created/upserted items
3697-
- Enable `contentResponseOnWriteEnabled(true)` to get documents back
3749+
- `readItem()`, `createItem()`, `upsertItem()`, and `replaceItem()` all return `CosmosItemResponse<T>` — always call `.getItem()` to get `T`
3750+
- In reactive/async code, use `.map(response -> response.getItem())` to unwrap the entity from the `Mono`
3751+
- Java SDK returns null from `getItem()` by default for created/upserted items — enable `contentResponseOnWriteEnabled(true)` to get documents back after writes
36983752
- Can be set at client level (all operations) or per-request
3699-
- Spring Data Cosmos handles this automatically
3700-
- Disable for high-throughput scenarios where response content is not needed
3753+
- Spring Data Cosmos handles both unwrapping and content response automatically
3754+
- Disable content response for high-throughput scenarios where response content is not needed
37013755

37023756
Reference: [Azure Cosmos DB Java SDK best practices](https://learn.microsoft.com/azure/cosmos-db/nosql/best-practice-java)
37033757

skills/cosmosdb-best-practices/rules/sdk-java-content-response.md

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,64 @@
11
---
2-
title: Enable content response on write operations in Java SDK
2+
title: Unwrap CosmosItemResponse and enable content response in Java SDK
33
impact: MEDIUM
4-
impactDescription: ensures created/updated documents are returned from write operations
5-
tags: sdk, java, content-response, create, upsert
4+
impactDescription: prevents type errors from missing getItem() on reads and null content on writes
5+
tags: sdk, java, content-response, readItem, create, upsert, getItem
66
---
77

8-
## Enable Content Response on Write Operations (Java)
8+
## Unwrap CosmosItemResponse with getItem() (Java)
9+
10+
All Cosmos DB Java SDK point-read and write operations (`readItem`, `createItem`, `upsertItem`, `replaceItem`) return `CosmosItemResponse<T>`, **not** `T` directly. You must call `.getItem()` to extract the entity. Treating the response wrapper as the entity causes compilation errors or incorrect behavior.
11+
12+
### Always unwrap readItem() with getItem()
13+
14+
`readItem()` always returns `CosmosItemResponse<T>`. You must call `.getItem()` to get the actual document.
15+
16+
**Incorrect — treating CosmosItemResponse as the entity:**
17+
18+
```java
19+
// ❌ WRONG: readItem returns CosmosItemResponse<Player>, NOT Player
20+
public Player getPlayer(String playerId) {
21+
Player player = container.readItem(
22+
playerId, new PartitionKey(playerId), Player.class); // ❌ Compilation error!
23+
return player;
24+
}
25+
```
26+
27+
```java
28+
// ❌ WRONG (async): Mono<CosmosItemResponse<Player>> is not Mono<Player>
29+
public Mono<Player> getPlayer(String playerId) {
30+
return container.readItem(
31+
playerId, new PartitionKey(playerId), Player.class); // ❌ Type mismatch!
32+
}
33+
```
34+
35+
**Correct — unwrap with getItem():**
36+
37+
```java
38+
// ✅ CORRECT: Call getItem() to extract the entity from the response
39+
public Player getPlayer(String playerId) {
40+
CosmosItemResponse<Player> response = container.readItem(
41+
playerId, new PartitionKey(playerId), Player.class);
42+
return response.getItem(); // ✅ Returns the Player entity
43+
}
44+
```
45+
46+
```java
47+
// ✅ CORRECT (async): Map the response to extract the entity
48+
public Mono<Player> getPlayer(String playerId) {
49+
return container.readItem(
50+
playerId, new PartitionKey(playerId), Player.class)
51+
.map(response -> response.getItem()); // ✅ Unwrap to Player
52+
}
53+
```
54+
55+
> **Why this matters:** `CosmosItemResponse<T>` is a wrapper that holds the entity (`getItem()`),
56+
> request charge (`getRequestCharge()`), ETag (`getETag()`), headers, and diagnostics.
57+
> Assigning the response directly to a variable of type `T` is a compile-time error in
58+
> synchronous code and a type-mismatch error in reactive chains. This affects `readItem`,
59+
> `createItem`, `upsertItem`, and `replaceItem` — all return `CosmosItemResponse<T>`.
60+
61+
### Enable Content Response on Write Operations
962

1063
By default, the Java Cosmos DB SDK does **not** return the document content after create/upsert operations. The response contains only metadata (headers, diagnostics) but the `getItem()` method returns null. You must explicitly enable content response if you need the created document.
1164

@@ -105,10 +158,11 @@ for (Order order : ordersToInsert) {
105158
Enabling content response does NOT increase RU cost - the document is already fetched server-side for the write operation. It only affects the response payload size over the network.
106159

107160
**Key Points:**
108-
- Java SDK returns null by default for created/upserted items
109-
- Enable `contentResponseOnWriteEnabled(true)` to get documents back
161+
- `readItem()`, `createItem()`, `upsertItem()`, and `replaceItem()` all return `CosmosItemResponse<T>` — always call `.getItem()` to get `T`
162+
- In reactive/async code, use `.map(response -> response.getItem())` to unwrap the entity from the `Mono`
163+
- Java SDK returns null from `getItem()` by default for created/upserted items — enable `contentResponseOnWriteEnabled(true)` to get documents back after writes
110164
- Can be set at client level (all operations) or per-request
111-
- Spring Data Cosmos handles this automatically
112-
- Disable for high-throughput scenarios where response content is not needed
165+
- Spring Data Cosmos handles both unwrapping and content response automatically
166+
- Disable content response for high-throughput scenarios where response content is not needed
113167

114168
Reference: [Azure Cosmos DB Java SDK best practices](https://learn.microsoft.com/azure/cosmos-db/nosql/best-practice-java)

0 commit comments

Comments
 (0)