Skip to content

Commit 40ca5f2

Browse files
committed
Implement return values for enhanced PutItem
This commit introduces DynamoDbTable#putItemWithResponse() that allows customers to specify additional parameters on the request such as ReturnValues to get additional information the service response. Relates to #1918
1 parent a459cfe commit 40ca5f2

20 files changed

+1565
-12
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "DynamoDB Enhanced Client",
3+
"contributor": "",
4+
"type": "feature",
5+
"description": "This commit introduces DynamoDbTable#putItemWithResponse() that allows customers to specify additional parameters on the request such as ReturnValues to get additional information the service response."
6+
}

services-custom/dynamodb-enhanced/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@
138138
<artifactId>utils</artifactId>
139139
<version>${awsjavasdk.version}</version>
140140
</dependency>
141+
<dependency>
142+
<groupId>software.amazon.awssdk</groupId>
143+
<artifactId>service-test-utils</artifactId>
144+
<version>${awsjavasdk.version}</version>
145+
<scope>test</scope>
146+
</dependency>
141147
<dependency>
142148
<groupId>junit</groupId>
143149
<artifactId>junit</artifactId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.enhanced.dynamodb;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey;
20+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey;
21+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondaryPartitionKey;
22+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondarySortKey;
23+
24+
import java.util.Objects;
25+
import org.junit.AfterClass;
26+
import org.junit.BeforeClass;
27+
import org.junit.Test;
28+
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
29+
import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedLocalSecondaryIndex;
30+
import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest;
31+
import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedResponse;
32+
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
33+
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
34+
import software.amazon.awssdk.services.dynamodb.model.Projection;
35+
import software.amazon.awssdk.services.dynamodb.model.ProjectionType;
36+
import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics;
37+
38+
public class AsyncPutItemWithResponseIntegrationTest extends DynamoDbEnhancedIntegrationTestBase {
39+
private static class Record {
40+
private Integer id;
41+
private Integer id2;
42+
private String stringAttr1;
43+
44+
private Integer getId() {
45+
return id;
46+
}
47+
48+
private Record setId(Integer id) {
49+
this.id = id;
50+
return this;
51+
}
52+
53+
private Integer getId2() {
54+
return id2;
55+
}
56+
57+
private Record setId2(Integer id2) {
58+
this.id2 = id2;
59+
return this;
60+
}
61+
62+
private String getStringAttr1() {
63+
return stringAttr1;
64+
}
65+
66+
private Record setStringAttr1(String stringAttr1) {
67+
this.stringAttr1 = stringAttr1;
68+
return this;
69+
}
70+
71+
@Override
72+
public boolean equals(Object o) {
73+
if (this == o) {
74+
return true;
75+
}
76+
if (o == null || getClass() != o.getClass()) {
77+
return false;
78+
}
79+
Record record = (Record) o;
80+
return Objects.equals(id, record.id)
81+
&& Objects.equals(id2, record.id2)
82+
&& Objects.equals(stringAttr1, record.stringAttr1);
83+
}
84+
85+
@Override
86+
public int hashCode() {
87+
return Objects.hash(id, id2, stringAttr1);
88+
}
89+
}
90+
91+
private static final String TABLE_NAME = createTestTableName();
92+
93+
private static final TableSchema<Record> TABLE_SCHEMA =
94+
StaticTableSchema.builder(Record.class)
95+
.newItemSupplier(Record::new)
96+
.addAttribute(Integer.class, a -> a.name("id_1")
97+
.getter(Record::getId)
98+
.setter(Record::setId)
99+
.tags(primaryPartitionKey(), secondaryPartitionKey("index1")))
100+
.addAttribute(Integer.class, a -> a.name("id_2")
101+
.getter(Record::getId2)
102+
.setter(Record::setId2)
103+
.tags(primarySortKey(), secondarySortKey("index1")))
104+
.addAttribute(String.class, a -> a.name("stringAttr1")
105+
.getter(Record::getStringAttr1)
106+
.setter(Record::setStringAttr1))
107+
.build();
108+
109+
private static final EnhancedLocalSecondaryIndex LOCAL_SECONDARY_INDEX = EnhancedLocalSecondaryIndex.builder()
110+
.indexName("index1")
111+
.projection(Projection.builder()
112+
.projectionType(ProjectionType.ALL)
113+
.build())
114+
.build();
115+
116+
private static DynamoDbClient dynamoDbClient;
117+
private static DynamoDbAsyncClient asyncDynamoDbClient;
118+
private static DynamoDbEnhancedAsyncClient enhancedClient;
119+
120+
private static DynamoDbAsyncTable<Record> mappedTable;
121+
122+
@BeforeClass
123+
public static void setup() {
124+
dynamoDbClient = createDynamoDbClient();
125+
asyncDynamoDbClient = createAsyncDynamoDbClient();
126+
enhancedClient = DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(asyncDynamoDbClient).build();
127+
128+
mappedTable = enhancedClient.table(TABLE_NAME, TABLE_SCHEMA);
129+
mappedTable.createTable(r -> r.localSecondaryIndices(LOCAL_SECONDARY_INDEX)).join();
130+
131+
dynamoDbClient.waiter().waitUntilTableExists(r -> r.tableName(TABLE_NAME));
132+
}
133+
134+
@AfterClass
135+
public static void teardown() {
136+
try {
137+
dynamoDbClient.deleteTable(r -> r.tableName(TABLE_NAME));
138+
} finally {
139+
dynamoDbClient.close();
140+
}
141+
asyncDynamoDbClient.close();
142+
}
143+
144+
@Test
145+
public void putItem_returnItemCollectionMetrics_set_itemCollectionMetricsNull() {
146+
Record record = new Record().setId(1).setId2(10);
147+
PutItemEnhancedRequest<Record> request = PutItemEnhancedRequest.builder(Record.class)
148+
.item(record)
149+
.build();
150+
151+
PutItemEnhancedResponse<Record> response = mappedTable.putItemWithResponse(request).join();
152+
153+
assertThat(response.itemCollectionMetrics()).isNull();
154+
}
155+
156+
@Test
157+
public void putItem_returnItemCollectionMetrics_set_itemCollectionMetricsNotNull() {
158+
Record record = new Record().setId(1).setId2(10);
159+
PutItemEnhancedRequest<Record> request = PutItemEnhancedRequest.builder(Record.class)
160+
.item(record)
161+
.returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE)
162+
.build();
163+
164+
PutItemEnhancedResponse<Record> response = mappedTable.putItemWithResponse(request).join();
165+
166+
assertThat(response.itemCollectionMetrics()).isNotNull();
167+
}
168+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.enhanced.dynamodb;
17+
18+
import java.util.UUID;
19+
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
20+
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
21+
import software.amazon.awssdk.testutils.service.AwsIntegrationTestBase;
22+
23+
public abstract class DynamoDbEnhancedIntegrationTestBase extends AwsIntegrationTestBase {
24+
protected static String createTestTableName() {
25+
return UUID.randomUUID() + "-ddb-enhanced-integ-test";
26+
}
27+
28+
protected static DynamoDbClient createDynamoDbClient() {
29+
return DynamoDbClient.builder()
30+
.credentialsProvider(getCredentialsProvider())
31+
.build();
32+
}
33+
34+
protected static DynamoDbAsyncClient createAsyncDynamoDbClient() {
35+
return DynamoDbAsyncClient.builder()
36+
.credentialsProvider(getCredentialsProvider())
37+
.build();
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.enhanced.dynamodb;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey;
20+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey;
21+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondaryPartitionKey;
22+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondarySortKey;
23+
24+
import java.util.Objects;
25+
import org.junit.AfterClass;
26+
import org.junit.BeforeClass;
27+
import org.junit.Test;
28+
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
29+
import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedLocalSecondaryIndex;
30+
import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest;
31+
import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedResponse;
32+
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
33+
import software.amazon.awssdk.services.dynamodb.model.Projection;
34+
import software.amazon.awssdk.services.dynamodb.model.ProjectionType;
35+
import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics;
36+
37+
public class PutItemWithResponseIntegrationTest extends DynamoDbEnhancedIntegrationTestBase {
38+
private static class Record {
39+
private Integer id;
40+
private Integer id2;
41+
private String stringAttr1;
42+
43+
private Integer getId() {
44+
return id;
45+
}
46+
47+
private Record setId(Integer id) {
48+
this.id = id;
49+
return this;
50+
}
51+
52+
private Integer getId2() {
53+
return id2;
54+
}
55+
56+
private Record setId2(Integer id2) {
57+
this.id2 = id2;
58+
return this;
59+
}
60+
61+
private String getStringAttr1() {
62+
return stringAttr1;
63+
}
64+
65+
private Record setStringAttr1(String stringAttr1) {
66+
this.stringAttr1 = stringAttr1;
67+
return this;
68+
}
69+
70+
@Override
71+
public boolean equals(Object o) {
72+
if (this == o) {
73+
return true;
74+
}
75+
if (o == null || getClass() != o.getClass()) {
76+
return false;
77+
}
78+
Record record = (Record) o;
79+
return Objects.equals(id, record.id)
80+
&& Objects.equals(id2, record.id2)
81+
&& Objects.equals(stringAttr1, record.stringAttr1);
82+
}
83+
84+
@Override
85+
public int hashCode() {
86+
return Objects.hash(id, id2, stringAttr1);
87+
}
88+
}
89+
90+
private static final String TABLE_NAME = createTestTableName();
91+
92+
private static final TableSchema<Record> TABLE_SCHEMA =
93+
StaticTableSchema.builder(Record.class)
94+
.newItemSupplier(Record::new)
95+
.addAttribute(Integer.class, a -> a.name("id_1")
96+
.getter(Record::getId)
97+
.setter(Record::setId)
98+
.tags(primaryPartitionKey(), secondaryPartitionKey("index1")))
99+
.addAttribute(Integer.class, a -> a.name("id_2")
100+
.getter(Record::getId2)
101+
.setter(Record::setId2)
102+
.tags(primarySortKey(), secondarySortKey("index1")))
103+
.addAttribute(String.class, a -> a.name("stringAttr1")
104+
.getter(Record::getStringAttr1)
105+
.setter(Record::setStringAttr1))
106+
.build();
107+
108+
private static final EnhancedLocalSecondaryIndex LOCAL_SECONDARY_INDEX = EnhancedLocalSecondaryIndex.builder()
109+
.indexName("index1")
110+
.projection(Projection.builder()
111+
.projectionType(ProjectionType.ALL)
112+
.build())
113+
.build();
114+
115+
private static DynamoDbClient dynamoDbClient;
116+
private static DynamoDbEnhancedClient enhancedClient;
117+
private static DynamoDbTable<Record> mappedTable;
118+
119+
@BeforeClass
120+
public static void setup() {
121+
dynamoDbClient = createDynamoDbClient();
122+
enhancedClient = DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build();
123+
mappedTable = enhancedClient.table(TABLE_NAME, TABLE_SCHEMA);
124+
mappedTable.createTable(r -> r.localSecondaryIndices(LOCAL_SECONDARY_INDEX));
125+
dynamoDbClient.waiter().waitUntilTableExists(r -> r.tableName(TABLE_NAME));
126+
}
127+
128+
@AfterClass
129+
public static void teardown() {
130+
try {
131+
dynamoDbClient.deleteTable(r -> r.tableName(TABLE_NAME));
132+
} finally {
133+
dynamoDbClient.close();
134+
}
135+
}
136+
137+
@Test
138+
public void putItem_returnItemCollectionMetrics_set_itemCollectionMetricsNull() {
139+
Record record = new Record().setId(1).setId2(10);
140+
PutItemEnhancedRequest<Record> request = PutItemEnhancedRequest.builder(Record.class)
141+
.item(record)
142+
.build();
143+
144+
PutItemEnhancedResponse<Record> response = mappedTable.putItemWithResponse(request);
145+
146+
assertThat(response.itemCollectionMetrics()).isNull();
147+
}
148+
149+
@Test
150+
public void putItem_returnItemCollectionMetrics_set_itemCollectionMetricsNotNull() {
151+
Record record = new Record().setId(1).setId2(10);
152+
PutItemEnhancedRequest<Record> request = PutItemEnhancedRequest.builder(Record.class)
153+
.item(record)
154+
.returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE)
155+
.build();
156+
157+
PutItemEnhancedResponse<Record> response = mappedTable.putItemWithResponse(request);
158+
159+
assertThat(response.itemCollectionMetrics()).isNotNull();
160+
}
161+
}

0 commit comments

Comments
 (0)