From b4cf2d0057ef0ea279cf4540c13ed372d862a398 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:59:37 -0700 Subject: [PATCH 1/5] add test coverage --- .../mapper/dynamodb/shape/ShapeItems.java | 406 ++++++++++++++++ .../dynamodb/shape/ShapeRequestTest.java | 460 ++++++++++++++++++ .../dynamodb/shape/ShapeResponseTest.java | 119 +++++ .../mapper/dynamodb/shape/ShapeSupport.java | 109 +++++ .../resources/batch_get_item_fixture.json | 3 + .../resources/batch_write_item_fixture.json | 4 + .../test/resources/delete_item_fixture.json | 6 + .../src/test/resources/get_item_fixture.json | 4 + .../src/test/resources/put_item_fixture.json | 32 ++ .../src/test/resources/query_fixture.json | 9 + .../src/test/resources/scan_fixture.json | 8 + .../resources/transaction_load_fixture.json | 3 + .../resources/transaction_write_fixture.json | 5 + .../resources/unmarshall_item_fixture.json | 17 + .../test/resources/update_item_fixture.json | 8 + 15 files changed, 1193 insertions(+) create mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeItems.java create mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java create mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java create mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java create mode 100644 services-custom/dynamodb-mapper/src/test/resources/batch_get_item_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/batch_write_item_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/delete_item_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/get_item_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/put_item_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/query_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/scan_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/transaction_load_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/transaction_write_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/unmarshall_item_fixture.json create mode 100644 services-custom/dynamodb-mapper/src/test/resources/update_item_fixture.json diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeItems.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeItems.java new file mode 100644 index 000000000000..3bd9d1e4988f --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeItems.java @@ -0,0 +1,406 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package software.amazon.awssdk.mapper.dynamodb.shape; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBAttribute; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBDocument; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBFlattened; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBNativeBoolean; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBRangeKey; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConvertedEnum; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBVersionAttribute; + +// Mapper-annotated test POJOs shared by ShapeRequestTest and ShapeResponseTest. +final class ShapeItems { + + private ShapeItems() { + } + + // Hash key plus one string attribute; the grammar workhorse. + @DynamoDBTable(tableName = "M_String") + public static class StringItem { + private String id; + private String value; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDBAttribute + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + + // Hash + range key for composite-key and range-condition cases. + @DynamoDBTable(tableName = "M_Range") + public static class RangeItem { + private String id; + private String range; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDBRangeKey + public String getRange() { + return range; + } + + public void setRange(String range) { + this.range = range; + } + } + + // Version-attributed, for the auto-generated version guard. + @DynamoDBTable(tableName = "M_Versioned") + public static class VersionedItem { + private String id; + private Long version; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDBVersionAttribute + public Long getVersion() { + return version; + } + + public void setVersion(Long version) { + this.version = version; + } + } + + // Nested @DynamoDBDocument rendered as an M. + @DynamoDBDocument + public static class Address { + private String city; + private Long zip; + + @DynamoDBAttribute + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + @DynamoDBAttribute + public Long getZip() { + return zip; + } + + public void setZip(Long zip) { + this.zip = zip; + } + } + + public enum Color { + RED, GREEN, BLUE + } + + // One field per value encoding; a case sets one field and saves with PUT so each fixture isolates a single encoding. + @DynamoDBTable(tableName = "M_AllTypes") + public static class AllTypesItem { + private String id; + private Long number; + private Double doubleValue; + private Boolean numericBool; + private Boolean nativeBool; + private Set stringSet; + private Set numberSet; + private List list; + private Map map; + private Address document; + private Color enumValue; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public AllTypesItem withId(String id) { + this.id = id; + return this; + } + + @DynamoDBAttribute + public Long getNumber() { + return number; + } + + public void setNumber(Long number) { + this.number = number; + } + + public AllTypesItem withNumber(Long number) { + this.number = number; + return this; + } + + @DynamoDBAttribute(attributeName = "double") + public Double getDoubleValue() { + return doubleValue; + } + + public void setDoubleValue(Double doubleValue) { + this.doubleValue = doubleValue; + } + + public AllTypesItem withDouble(Double doubleValue) { + this.doubleValue = doubleValue; + return this; + } + + // Plain Boolean, encoded as N 0/1. + @DynamoDBAttribute + public Boolean getNumericBool() { + return numericBool; + } + + public void setNumericBool(Boolean numericBool) { + this.numericBool = numericBool; + } + + public AllTypesItem withNumericBool(Boolean numericBool) { + this.numericBool = numericBool; + return this; + } + + // Encoded as a native BOOL. + @DynamoDBNativeBoolean + @DynamoDBAttribute + public Boolean getNativeBool() { + return nativeBool; + } + + public void setNativeBool(Boolean nativeBool) { + this.nativeBool = nativeBool; + } + + public AllTypesItem withNativeBool(Boolean nativeBool) { + this.nativeBool = nativeBool; + return this; + } + + @DynamoDBAttribute + public Set getStringSet() { + return stringSet; + } + + public void setStringSet(Set stringSet) { + this.stringSet = stringSet; + } + + public AllTypesItem withStringSet(Set stringSet) { + this.stringSet = stringSet; + return this; + } + + @DynamoDBAttribute + public Set getNumberSet() { + return numberSet; + } + + public void setNumberSet(Set numberSet) { + this.numberSet = numberSet; + } + + public AllTypesItem withNumberSet(Set numberSet) { + this.numberSet = numberSet; + return this; + } + + @DynamoDBAttribute + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + public AllTypesItem withList(List list) { + this.list = list; + return this; + } + + @DynamoDBAttribute + public Map getMap() { + return map; + } + + public void setMap(Map map) { + this.map = map; + } + + public AllTypesItem withMap(Map map) { + this.map = map; + return this; + } + + @DynamoDBAttribute + public Address getDocument() { + return document; + } + + public void setDocument(Address document) { + this.document = document; + } + + public AllTypesItem withDocument(Address document) { + this.document = document; + return this; + } + + @DynamoDBTypeConvertedEnum + @DynamoDBAttribute(attributeName = "enum") + public Color getEnumValue() { + return enumValue; + } + + public void setEnumValue(Color enumValue) { + this.enumValue = enumValue; + } + + public AllTypesItem withEnumValue(Color enumValue) { + this.enumValue = enumValue; + return this; + } + } + + // Default Date maps to an ISO-8601 S; the epoch and pattern variants have their own annotations. + @DynamoDBTable(tableName = "M_Dated") + public static class DatedItem { + private String id; + private Date createdAt; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDBAttribute + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + } + + // A nested bean whose single field is flattened into the parent item as a sibling attribute. + @DynamoDBDocument + public static class Name { + private String first; + + @DynamoDBAttribute + public String getFirst() { + return first; + } + + public void setFirst(String first) { + this.first = first; + } + } + + @DynamoDBTable(tableName = "M_Flattened") + public static class FlattenedItem { + private String id; + private Name name; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDBFlattened(attributes = @DynamoDBAttribute(mappedBy = "first", attributeName = "firstName")) + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + } + + // Hash key and table declared on the base; the subclass inherits both and only adds one attribute. + @DynamoDBTable(tableName = "M_Inherited") + public static class BaseKeyed { + private String id; + + @DynamoDBHashKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } + + public static class InheritedItem extends BaseKeyed { + private String label; + + @DynamoDBAttribute + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + } +} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java new file mode 100644 index 000000000000..1667eb41a42b --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java @@ -0,0 +1,460 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package software.amazon.awssdk.mapper.dynamodb.shape; + +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.HASH_KEY; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.n; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.s; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.verify; + +import com.amazonaws.AmazonServiceException; +import com.amazonaws.Request; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; +import com.amazonaws.handlers.RequestHandler2; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; +import com.amazonaws.services.dynamodbv2.model.Condition; +import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; +import com.amazonaws.services.dynamodbv2.model.Select; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBDeleteExpression; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.SaveBehavior; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBQueryExpression; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBSaveExpression; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBScanExpression; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBTransactionWriteExpression; +import software.amazon.awssdk.mapper.dynamodb.TransactionLoadRequest; +import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.Address; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.AllTypesItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.Color; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.DatedItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.FlattenedItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.InheritedItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.Name; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.RangeItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.StringItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.VersionedItem; +import software.amazon.awssdk.utils.IoUtils; + +/** Captures each mapper call's marshalled request (X-Amz-Target + JSON body) and asserts it against a committed fixture. */ +@RunWith(Parameterized.class) +public class ShapeRequestTest { + + private static final String TARGET_HEADER = "X-Amz-Target"; + + /** The DynamoDB operation a case targets, and the fixture file it asserts against. */ + enum Operation { + PUT_ITEM("put_item_fixture.json"), + UPDATE_ITEM("update_item_fixture.json"), + DELETE_ITEM("delete_item_fixture.json"), + GET_ITEM("get_item_fixture.json"), + QUERY("query_fixture.json"), + SCAN("scan_fixture.json"), + BATCH_WRITE_ITEM("batch_write_item_fixture.json"), + BATCH_GET_ITEM("batch_get_item_fixture.json"), + TRANSACT_WRITE_ITEMS("transaction_write_fixture.json"), + TRANSACT_GET_ITEMS("transaction_load_fixture.json"); + + final String fixture; + + Operation(String fixture) { + this.fixture = fixture; + } + } + + interface MapperAction { + void run(DynamoDBMapper mapper); + } + + static final class Case { + final Operation operation; + final String name; + final MapperAction action; + + Case(Operation operation, String name, MapperAction action) { + this.operation = operation; + this.name = name; + this.action = action; + } + + @Override + public String toString() { + return operation.fixture.replace("_fixture.json", "") + ":" + name; + } + } + + @Parameters(name = "{0}") + public static List cases() { + List c = new ArrayList<>(); + + // PutItem value matrix: one field per case, saved with PUT so each fixture isolates a single encoding. + add(c, "string/normal", m -> m.save(stringItem("hello"), put())); + add(c, "string/unicode", m -> m.save(stringItem("héllo-世界-😀"), put())); + add(c, "string/whitespace", m -> m.save(stringItem(" pad \t\n"), put())); + add(c, "number/positive", m -> m.save(at().withNumber(42L), put())); + add(c, "number/zero", m -> m.save(at().withNumber(0L), put())); + add(c, "number/negative", m -> m.save(at().withNumber(-7L), put())); + add(c, "number/max-long", m -> m.save(at().withNumber(Long.MAX_VALUE), put())); + add(c, "number/min-long", m -> m.save(at().withNumber(Long.MIN_VALUE), put())); + add(c, "double/fractional", m -> m.save(at().withDouble(1.5d), put())); + add(c, "double/whole", m -> m.save(at().withDouble(1.0d), put())); + add(c, "double/negative", m -> m.save(at().withDouble(-0.25d), put())); + add(c, "bool-numeric/true", m -> m.save(at().withNumericBool(true), put())); + add(c, "bool-numeric/false", m -> m.save(at().withNumericBool(false), put())); + add(c, "bool-native/true", m -> m.save(at().withNativeBool(true), put())); + add(c, "bool-native/false", m -> m.save(at().withNativeBool(false), put())); + add(c, "string-set/single", m -> m.save(at().withStringSet(set("a")), put())); + add(c, "string-set/multi", m -> m.save(at().withStringSet(set("c", "a", "b")), put())); + add(c, "number-set/single", m -> m.save(at().withNumberSet(set(1L)), put())); + add(c, "number-set/multi", m -> m.save(at().withNumberSet(set(3L, 1L, 2L)), put())); + add(c, "list/single", m -> m.save(at().withList(list("only")), put())); + add(c, "list/multi", m -> m.save(at().withList(list("first", "second", "third")), put())); + add(c, "map/single", m -> m.save(at().withMap(map("k", "v")), put())); + add(c, "map/multi", m -> m.save(at().withMap(map("b", "2", "a", "1")), put())); + // Single-attribute document: a multi-field @DynamoDBDocument marshals in reflection order, which varies across + // JVMs and can't be byte-pinned. One field proves the M encoding without ordering ambiguity. + add(c, "document/populated", m -> m.save(at().withDocument(city("Seattle")), put())); + add(c, "enum/value", m -> m.save(at().withEnumValue(Color.GREEN), put())); + + // Single-field flattened doc: the nested Name.first is hoisted to a sibling "firstName" attribute. + c.add(new Case(Operation.PUT_ITEM, "flattened", m -> m.save(flattenedItem("Ada"), put()))); + // Hash key declared on a base class still marshals into the key envelope. + c.add(new Case(Operation.PUT_ITEM, "inherited-key", m -> m.save(inheritedItem("tag"), put()))); + // Default Date with no epoch/pattern annotation marshals as an ISO-8601 S. Fixed instant for determinism. + c.add(new Case(Operation.PUT_ITEM, "date-iso8601", + m -> m.save(datedItem(new Date(1_600_000_000_000L)), put()))); + + c.add(new Case(Operation.UPDATE_ITEM, "save-default-update", m -> m.save(stringItem("hello")))); + c.add(new Case(Operation.UPDATE_ITEM, "versioned-first-save", m -> m.save(versionedItem()))); + + c.add(new Case(Operation.DELETE_ITEM, "simple", m -> m.delete(stringItem("hello")))); + c.add(new Case(Operation.DELETE_ITEM, "versioned", m -> m.delete(versionedItemWithVersion()))); + + c.add(new Case(Operation.GET_ITEM, "by-key", m -> m.load(StringItem.class, HASH_KEY))); + + c.add(new Case(Operation.QUERY, "hash-key-equals", m -> { + StringItem key = new StringItem(); + key.setId(HASH_KEY); + m.query(StringItem.class, new DynamoDBQueryExpression().withHashKeyValues(key)); + })); + + c.add(new Case(Operation.SCAN, "unfiltered", m -> m.scan(StringItem.class, new DynamoDBScanExpression()))); + + c.add(new Case(Operation.BATCH_WRITE_ITEM, "two-puts", + m -> m.batchWrite(Arrays.asList(stringItem("a"), stringItem("b")), Collections.emptyList()))); + + c.add(new Case(Operation.BATCH_GET_ITEM, "two-keys", + m -> m.batchLoad(Arrays.asList(keyOnly("a"), keyOnly("b"))))); + + // CLOBBER vs PUT diverge only on a versioned item: PUT keeps the Expected version guard, CLOBBER suppresses it. + c.add(new Case(Operation.PUT_ITEM, "clobber-suppresses-version-check", + m -> m.save(versionedItem(), new DynamoDBMapperConfig(SaveBehavior.CLOBBER)))); + c.add(new Case(Operation.PUT_ITEM, "put-keeps-version-check", + m -> m.save(versionedItem(), new DynamoDBMapperConfig(SaveBehavior.PUT)))); + c.add(new Case(Operation.UPDATE_ITEM, "append-set-behavior", + m -> m.save(at().withStringSet(set("a", "b")), new DynamoDBMapperConfig(SaveBehavior.APPEND_SET)))); + + // UPDATE emits Action:DELETE for a null attribute; SKIP_NULL omits it. + c.add(new Case(Operation.UPDATE_ITEM, "null-attr-delete", + m -> m.save(stringItem(null), new DynamoDBMapperConfig(SaveBehavior.UPDATE)))); + c.add(new Case(Operation.UPDATE_ITEM, "null-attr-skip", + m -> m.save(stringItem(null), new DynamoDBMapperConfig(SaveBehavior.UPDATE_SKIP_NULL_ATTRIBUTES)))); + + c.add(new Case(Operation.GET_ITEM, "composite-key", m -> m.load(RangeItem.class, HASH_KEY, "r"))); + + c.add(new Case(Operation.UPDATE_ITEM, "save-with-expected-expression", + m -> m.save(stringItem("hello"), new DynamoDBSaveExpression() + .withExpectedEntry("value", new ExpectedAttributeValue().withExists(false))))); + + c.add(new Case(Operation.DELETE_ITEM, "delete-with-expected-expression", + m -> m.delete(stringItem("hello"), new DynamoDBDeleteExpression() + .withExpectedEntry("value", new ExpectedAttributeValue().withValue(s("hello")))))); + c.add(new Case(Operation.DELETE_ITEM, "delete-with-condition-expression", + m -> m.delete(stringItem("hello"), new DynamoDBDeleteExpression() + .withConditionExpression("attribute_exists(#v)") + .withExpressionAttributeNames(Collections.singletonMap("#v", "value"))))); + + c.add(new Case(Operation.QUERY, "range-condition-limit-desc", m -> { + RangeItem key = new RangeItem(); + key.setId(HASH_KEY); + Condition rangeCond = new Condition() + .withComparisonOperator(ComparisonOperator.GT) + .withAttributeValueList(n("5")); + m.query(RangeItem.class, new DynamoDBQueryExpression() + .withHashKeyValues(key) + .withRangeKeyCondition("range", rangeCond) + .withLimit(10) + .withScanIndexForward(false)); + })); + c.add(new Case(Operation.QUERY, "consistent-read-select", m -> { + StringItem key = new StringItem(); + key.setId(HASH_KEY); + m.query(StringItem.class, new DynamoDBQueryExpression() + .withHashKeyValues(key) + .withConsistentRead(true) + .withSelect(Select.ALL_ATTRIBUTES)); + })); + c.add(new Case(Operation.QUERY, "query-filter", m -> { + StringItem key = new StringItem(); + key.setId(HASH_KEY); + m.query(StringItem.class, new DynamoDBQueryExpression() + .withHashKeyValues(key) + .withQueryFilterEntry("value", new Condition() + .withComparisonOperator(ComparisonOperator.EQ) + .withAttributeValueList(s("hello")))); + })); + c.add(new Case(Operation.QUERY, "exclusive-start-key", m -> { + StringItem key = new StringItem(); + key.setId(HASH_KEY); + Map start = new LinkedHashMap<>(); + start.put("id", s(HASH_KEY)); + m.query(StringItem.class, new DynamoDBQueryExpression() + .withHashKeyValues(key) + .withExclusiveStartKey(start)); + })); + c.add(new Case(Operation.QUERY, "projection-expression", m -> { + StringItem key = new StringItem(); + key.setId(HASH_KEY); + m.query(StringItem.class, new DynamoDBQueryExpression() + .withHashKeyValues(key) + .withProjectionExpression("#v") + .withExpressionAttributeNames(Collections.singletonMap("#v", "value"))); + })); + // keyConditionExpression is mutually exclusive with hashKeyValues; the mapper throws if both are set. + c.add(new Case(Operation.QUERY, "key-condition-expression", + m -> m.query(StringItem.class, new DynamoDBQueryExpression() + .withKeyConditionExpression("#i = :v") + .withExpressionAttributeNames(Collections.singletonMap("#i", "id")) + .withExpressionAttributeValues(Collections.singletonMap(":v", s(HASH_KEY)))))); + + c.add(new Case(Operation.SCAN, "filtered-limited", m -> m.scan(StringItem.class, + new DynamoDBScanExpression() + .withFilterConditionEntry("value", new Condition() + .withComparisonOperator(ComparisonOperator.EQ) + .withAttributeValueList(s("hello"))) + .withLimit(25)))); + c.add(new Case(Operation.SCAN, "consistent-read", m -> m.scan(StringItem.class, + new DynamoDBScanExpression().withConsistentRead(true)))); + c.add(new Case(Operation.SCAN, "projection-expression", m -> m.scan(StringItem.class, + new DynamoDBScanExpression() + .withProjectionExpression("#v") + .withExpressionAttributeNames(Collections.singletonMap("#v", "value"))))); + c.add(new Case(Operation.SCAN, "filter-expression", m -> m.scan(StringItem.class, + new DynamoDBScanExpression() + .withFilterExpression("#v = :v") + .withExpressionAttributeNames(Collections.singletonMap("#v", "value")) + .withExpressionAttributeValues(Collections.singletonMap(":v", s("hello")))))); + c.add(new Case(Operation.SCAN, "segment", m -> m.scan(StringItem.class, + new DynamoDBScanExpression().withTotalSegments(4).withSegment(1)))); + + c.add(new Case(Operation.BATCH_WRITE_ITEM, "mixed-put-delete", + m -> m.batchWrite(Arrays.asList(stringItem("p")), Arrays.asList(keyOnly("d"))))); + + // Fixed idempotency token: an unset one makes the core SDK auto-fill ClientRequestToken with a random UUID. + c.add(new Case(Operation.TRANSACT_WRITE_ITEMS, "put-update-delete", m -> { + TransactionWriteRequest req = new TransactionWriteRequest() + .addPut(stringItem("p")) + .addUpdate(stringItem("u")) + .addDelete(keyOnly("d")) + .withIdempotencyToken("fixed-token"); + m.transactionWrite(req); + })); + c.add(new Case(Operation.TRANSACT_WRITE_ITEMS, "condition-check", m -> { + TransactionWriteRequest req = new TransactionWriteRequest() + .addConditionCheck(keyOnly("c"), new DynamoDBTransactionWriteExpression() + .withConditionExpression("attribute_exists(#i)") + .withExpressionAttributeNames(Collections.singletonMap("#i", "id"))) + .withIdempotencyToken("fixed-token"); + m.transactionWrite(req); + })); + // Versioned put with no user expression: the mapper auto-generates the version condition. + c.add(new Case(Operation.TRANSACT_WRITE_ITEMS, "versioned-auto-condition", m -> { + TransactionWriteRequest req = new TransactionWriteRequest() + .addPut(versionedItem()) + .withIdempotencyToken("fixed-token"); + m.transactionWrite(req); + })); + + c.add(new Case(Operation.TRANSACT_GET_ITEMS, "two-loads", m -> { + TransactionLoadRequest req = new TransactionLoadRequest() + .addLoad(keyOnly("a")) + .addLoad(keyOnly("b")); + m.transactionLoad(req); + })); + + return c; + } + + @Parameter + public Case testCase; + + @Test + public void matchesFixture() { + verify(testCase.operation.fixture, testCase.name, captureRequest(testCase.action)); + } + + // Captures the marshalled request as "target\nbody"; the v2 port swaps this for an ExecutionInterceptor. + private static String captureRequest(MapperAction action) { + String[] captured = new String[1]; + RequestHandler2 handler = new RequestHandler2() { + @Override + public void beforeRequest(Request request) { + String target = request.getHeaders().get(TARGET_HEADER); + captured[0] = target + "\n" + readContent(request.getContent()); + throw new StopSignal(); + } + }; + AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("akid", "skid"))) + .withEndpointConfiguration(new EndpointConfiguration("http://localhost:8000", "us-east-1")) + .withRequestHandlers(handler) + .build(); + DynamoDBMapper mapper = new DynamoDBMapper(client); + try { + action.run(mapper); + } catch (StopSignal expected) { + // request captured; network intentionally aborted + } catch (AmazonServiceException e) { + throw new IllegalStateException("Request reached the network instead of being captured", e); + } + if (captured[0] == null) { + throw new IllegalStateException("No DynamoDB request was marshalled by the action"); + } + return captured[0]; + } + + private static final class StopSignal extends RuntimeException { + StopSignal() { + super(null, null, false, false); + } + } + + private static String readContent(InputStream content) { + if (content == null) { + throw new IllegalStateException("Marshalled request had no body"); + } + try { + return new String(IoUtils.toByteArray(content), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static void add(List c, String name, MapperAction action) { + c.add(new Case(Operation.PUT_ITEM, name, action)); + } + + private static DynamoDBMapperConfig put() { + return new DynamoDBMapperConfig(SaveBehavior.PUT); + } + + private static AllTypesItem at() { + return new AllTypesItem().withId(HASH_KEY); + } + + private static StringItem stringItem(String v) { + StringItem i = new StringItem(); + i.setId(HASH_KEY); + i.setValue(v); + return i; + } + + private static StringItem keyOnly(String id) { + StringItem i = new StringItem(); + i.setId(id); + return i; + } + + private static VersionedItem versionedItem() { + VersionedItem i = new VersionedItem(); + i.setId(HASH_KEY); + return i; + } + + private static VersionedItem versionedItemWithVersion() { + VersionedItem i = versionedItem(); + i.setVersion(3L); + return i; + } + + private static Address city(String city) { + Address a = new Address(); + a.setCity(city); + return a; + } + + private static FlattenedItem flattenedItem(String first) { + Name name = new Name(); + name.setFirst(first); + FlattenedItem i = new FlattenedItem(); + i.setId(HASH_KEY); + i.setName(name); + return i; + } + + private static InheritedItem inheritedItem(String label) { + InheritedItem i = new InheritedItem(); + i.setId(HASH_KEY); + i.setLabel(label); + return i; + } + + private static DatedItem datedItem(Date createdAt) { + DatedItem i = new DatedItem(); + i.setId(HASH_KEY); + i.setCreatedAt(createdAt); + return i; + } + + @SafeVarargs + private static java.util.Set set(T... v) { + return new LinkedHashSet<>(Arrays.asList(v)); + } + + private static List list(String... v) { + return new ArrayList<>(Arrays.asList(v)); + } + + private static Map map(String... kv) { + Map map = new LinkedHashMap<>(); + for (int j = 0; j < kv.length; j += 2) { + map.put(kv[j], kv[j + 1]); + } + return map; + } +} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java new file mode 100644 index 000000000000..fde3ea236e16 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java @@ -0,0 +1,119 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package software.amazon.awssdk.mapper.dynamodb.shape; + +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.HASH_KEY; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.bool; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.entry; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.item; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.l; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.m; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.n; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.ns; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.s; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.ss; +import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.verify; + +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.AllTypesItem; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.StringItem; + +// Reconstructs POJOs from canned attribute maps via marshallIntoObject and asserts the result against a fixture. +@RunWith(Parameterized.class) +public class ShapeResponseTest { + + private static final String FIXTURE = "unmarshall_item_fixture.json"; + private static final DynamoDBMapper MAPPER = new DynamoDBMapper((com.amazonaws.services.dynamodbv2.AmazonDynamoDB) null); + + // NON_NULL keeps the fixture to the reconstructed attributes; alphabetical sort pins the reflection-ordered fields. + private static final ObjectMapper READ_JSON = new ObjectMapper() + .enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS) + .enable(SerializationFeature.INDENT_OUTPUT) + .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY) + .setSerializationInclusion(Include.NON_NULL); + + static final class Case { + final String name; + final Class type; + final Map attributes; + + Case(String name, Class type, Map attributes) { + this.name = name; + this.type = type; + this.attributes = attributes; + } + + @Override + public String toString() { + return "unmarshall:" + name; + } + } + + @Parameters(name = "{0}") + public static List cases() { + List c = new ArrayList<>(); + + c.add(new Case("string", StringItem.class, item("value", s("hello")))); + c.add(new Case("string-unicode", StringItem.class, item("value", s("héllo-世界-😀")))); + c.add(new Case("number", AllTypesItem.class, item("number", n("42")))); + c.add(new Case("number-negative", AllTypesItem.class, item("number", n("-7")))); + c.add(new Case("double", AllTypesItem.class, item("double", n("1.5")))); + c.add(new Case("bool-numeric-true", AllTypesItem.class, item("numericBool", n("1")))); + c.add(new Case("bool-numeric-false", AllTypesItem.class, item("numericBool", n("0")))); + c.add(new Case("bool-native-true", AllTypesItem.class, item("nativeBool", bool(true)))); + c.add(new Case("bool-native-false", AllTypesItem.class, item("nativeBool", bool(false)))); + c.add(new Case("string-set", AllTypesItem.class, item("stringSet", ss("a", "b", "c")))); + c.add(new Case("number-set", AllTypesItem.class, item("numberSet", ns("1", "2", "3")))); + c.add(new Case("list", AllTypesItem.class, item("list", l(s("first"), s("second"))))); + c.add(new Case("map", AllTypesItem.class, item("map", m(entry("a", s("1")), entry("b", s("2")))))); + c.add(new Case("document", AllTypesItem.class, + item("document", m(entry("city", s("Seattle")), entry("zip", n("98101")))))); + c.add(new Case("enum", AllTypesItem.class, item("enum", s("GREEN")))); + + return c; + } + + @Parameter + public Case testCase; + + @Test + public void matchesFixture() { + verify(FIXTURE, testCase.name, reconstruct(testCase.type, testCase.attributes)); + } + + private static String reconstruct(Class type, Map attributes) { + T object = MAPPER.marshallIntoObject(type, attributes, DynamoDBMapperConfig.DEFAULT); + try { + return READ_JSON.writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new IllegalStateException("Failed to serialize reconstructed " + type.getSimpleName(), e); + } + } +} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java new file mode 100644 index 000000000000..0cff63c122fa --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java @@ -0,0 +1,109 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package software.amazon.awssdk.mapper.dynamodb.shape; + +import static org.junit.Assert.assertEquals; + +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import software.amazon.awssdk.utils.IoUtils; + +// Fixture assertion and AttributeValue builders shared by ShapeRequestTest and ShapeResponseTest. +final class ShapeSupport { + + static final String HASH_KEY = "k"; + + private static final ObjectMapper JSON = new ObjectMapper(); + private static final TypeReference> ENTRIES = new TypeReference>() { + }; + private static final Map> CACHE = new ConcurrentHashMap<>(); + + private ShapeSupport() { + } + + // Asserts actual equals the committed fixture entry name in fixtureFile. + static void verify(String fixtureFile, String name, String actual) { + String expected = loadFixture(fixtureFile).get(name); + if (expected == null) { + throw new IllegalStateException("No fixture entry '" + name + "' in " + fixtureFile); + } + assertEquals("Shape drifted for " + fixtureFile + ":" + name, expected, actual); + } + + private static Map loadFixture(String fixtureFile) { + return CACHE.computeIfAbsent(fixtureFile, file -> { + try (InputStream in = ShapeSupport.class.getClassLoader().getResourceAsStream(file)) { + if (in == null) { + throw new IllegalStateException("Missing fixture " + file); + } + return JSON.readValue(IoUtils.toUtf8String(in), ENTRIES); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + // A key/response map of hash key id=k plus one named attribute. + static Map item(String attr, AttributeValue value) { + Map map = new LinkedHashMap<>(); + map.put("id", s(HASH_KEY)); + map.put(attr, value); + return map; + } + + static AttributeValue s(String v) { + return new AttributeValue().withS(v); + } + + static AttributeValue n(String v) { + return new AttributeValue().withN(v); + } + + static AttributeValue bool(boolean v) { + return new AttributeValue().withBOOL(v); + } + + static AttributeValue ss(String... v) { + return new AttributeValue().withSS(v); + } + + static AttributeValue ns(String... v) { + return new AttributeValue().withNS(v); + } + + static AttributeValue l(AttributeValue... v) { + return new AttributeValue().withL(v); + } + + @SafeVarargs + static AttributeValue m(Map.Entry... entries) { + Map map = new LinkedHashMap<>(); + for (Map.Entry e : entries) { + map.put(e.getKey(), e.getValue()); + } + return new AttributeValue().withM(map); + } + + static Map.Entry entry(String k, AttributeValue v) { + return new java.util.AbstractMap.SimpleEntry<>(k, v); + } +} diff --git a/services-custom/dynamodb-mapper/src/test/resources/batch_get_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/batch_get_item_fixture.json new file mode 100644 index 000000000000..c1dfa634c5c5 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/batch_get_item_fixture.json @@ -0,0 +1,3 @@ +{ + "two-keys" : "DynamoDB_20120810.BatchGetItem\n{\"RequestItems\":{\"M_String\":{\"Keys\":[{\"id\":{\"S\":\"a\"}},{\"id\":{\"S\":\"b\"}}],\"ConsistentRead\":false}}}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/batch_write_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/batch_write_item_fixture.json new file mode 100644 index 000000000000..3dfd5f5d5a99 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/batch_write_item_fixture.json @@ -0,0 +1,4 @@ +{ + "mixed-put-delete" : "DynamoDB_20120810.BatchWriteItem\n{\"RequestItems\":{\"M_String\":[{\"PutRequest\":{\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\"p\"}}}},{\"DeleteRequest\":{\"Key\":{\"id\":{\"S\":\"d\"}}}}]}}", + "two-puts" : "DynamoDB_20120810.BatchWriteItem\n{\"RequestItems\":{\"M_String\":[{\"PutRequest\":{\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\"a\"}}}},{\"PutRequest\":{\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\"b\"}}}}]}}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/delete_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/delete_item_fixture.json new file mode 100644 index 000000000000..9f1c03e15a1a --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/delete_item_fixture.json @@ -0,0 +1,6 @@ +{ + "delete-with-condition-expression" : "DynamoDB_20120810.DeleteItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"ConditionExpression\":\"attribute_exists(#v)\",\"ExpressionAttributeNames\":{\"#v\":\"value\"}}", + "delete-with-expected-expression" : "DynamoDB_20120810.DeleteItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"Expected\":{\"value\":{\"Value\":{\"S\":\"hello\"}}}}", + "simple" : "DynamoDB_20120810.DeleteItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"Expected\":{}}", + "versioned" : "DynamoDB_20120810.DeleteItem\n{\"TableName\":\"M_Versioned\",\"Key\":{\"id\":{\"S\":\"k\"}},\"Expected\":{\"version\":{\"Value\":{\"N\":\"3\"},\"Exists\":true}}}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/get_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/get_item_fixture.json new file mode 100644 index 000000000000..b9b75c993be9 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/get_item_fixture.json @@ -0,0 +1,4 @@ +{ + "by-key" : "DynamoDB_20120810.GetItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"ConsistentRead\":false}", + "composite-key" : "DynamoDB_20120810.GetItem\n{\"TableName\":\"M_Range\",\"Key\":{\"id\":{\"S\":\"k\"},\"range\":{\"S\":\"r\"}},\"ConsistentRead\":false}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/put_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/put_item_fixture.json new file mode 100644 index 000000000000..1b1f236736c6 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/put_item_fixture.json @@ -0,0 +1,32 @@ +{ + "bool-native/false" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"nativeBool\":{\"BOOL\":false}}}", + "bool-native/true" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"nativeBool\":{\"BOOL\":true}}}", + "bool-numeric/false" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"numericBool\":{\"N\":\"0\"},\"id\":{\"S\":\"k\"}}}", + "bool-numeric/true" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"numericBool\":{\"N\":\"1\"},\"id\":{\"S\":\"k\"}}}", + "clobber-suppresses-version-check" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_Versioned\",\"Item\":{\"id\":{\"S\":\"k\"},\"version\":{\"N\":\"1\"}}}", + "date-iso8601" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_Dated\",\"Item\":{\"createdAt\":{\"S\":\"2020-09-13T12:26:40.000Z\"},\"id\":{\"S\":\"k\"}}}", + "document/populated" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"document\":{\"M\":{\"city\":{\"S\":\"Seattle\"}}},\"id\":{\"S\":\"k\"}}}", + "double/fractional" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"double\":{\"N\":\"1.5\"},\"id\":{\"S\":\"k\"}}}", + "double/negative" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"double\":{\"N\":\"-0.25\"},\"id\":{\"S\":\"k\"}}}", + "double/whole" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"double\":{\"N\":\"1.0\"},\"id\":{\"S\":\"k\"}}}", + "enum/value" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"enum\":{\"S\":\"GREEN\"}}}", + "flattened" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_Flattened\",\"Item\":{\"firstName\":{\"S\":\"Ada\"},\"id\":{\"S\":\"k\"}}}", + "inherited-key" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_Inherited\",\"Item\":{\"label\":{\"S\":\"tag\"},\"id\":{\"S\":\"k\"}}}", + "list/multi" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"list\":{\"L\":[{\"S\":\"first\"},{\"S\":\"second\"},{\"S\":\"third\"}]}}}", + "list/single" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"list\":{\"L\":[{\"S\":\"only\"}]}}}", + "map/multi" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"map\":{\"M\":{\"b\":{\"S\":\"2\"},\"a\":{\"S\":\"1\"}}}}}", + "map/single" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"map\":{\"M\":{\"k\":{\"S\":\"v\"}}}}}", + "number-set/multi" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"numberSet\":{\"NS\":[\"3\",\"1\",\"2\"]}}}", + "number-set/single" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"id\":{\"S\":\"k\"},\"numberSet\":{\"NS\":[\"1\"]}}}", + "number/max-long" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"number\":{\"N\":\"9223372036854775807\"},\"id\":{\"S\":\"k\"}}}", + "number/min-long" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"number\":{\"N\":\"-9223372036854775808\"},\"id\":{\"S\":\"k\"}}}", + "number/negative" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"number\":{\"N\":\"-7\"},\"id\":{\"S\":\"k\"}}}", + "number/positive" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"number\":{\"N\":\"42\"},\"id\":{\"S\":\"k\"}}}", + "number/zero" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"number\":{\"N\":\"0\"},\"id\":{\"S\":\"k\"}}}", + "put-keeps-version-check" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_Versioned\",\"Item\":{\"id\":{\"S\":\"k\"},\"version\":{\"N\":\"1\"}},\"Expected\":{\"version\":{\"Exists\":false}}}", + "string-set/multi" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"stringSet\":{\"SS\":[\"c\",\"a\",\"b\"]},\"id\":{\"S\":\"k\"}}}", + "string-set/single" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_AllTypes\",\"Item\":{\"stringSet\":{\"SS\":[\"a\"]},\"id\":{\"S\":\"k\"}}}", + "string/normal" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_String\",\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\"hello\"}}}", + "string/unicode" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_String\",\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\"héllo-世界-\\uD83D\\uDE00\"}}}", + "string/whitespace" : "DynamoDB_20120810.PutItem\n{\"TableName\":\"M_String\",\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\" pad \\t\\n\"}}}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/query_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/query_fixture.json new file mode 100644 index 000000000000..24fa8a521ecb --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/query_fixture.json @@ -0,0 +1,9 @@ +{ + "consistent-read-select" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_String\",\"Select\":\"ALL_ATTRIBUTES\",\"ConsistentRead\":true,\"KeyConditions\":{\"id\":{\"AttributeValueList\":[{\"S\":\"k\"}],\"ComparisonOperator\":\"EQ\"}},\"ScanIndexForward\":true}", + "exclusive-start-key" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_String\",\"ConsistentRead\":true,\"KeyConditions\":{\"id\":{\"AttributeValueList\":[{\"S\":\"k\"}],\"ComparisonOperator\":\"EQ\"}},\"ScanIndexForward\":true,\"ExclusiveStartKey\":{\"id\":{\"S\":\"k\"}}}", + "hash-key-equals" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_String\",\"ConsistentRead\":true,\"KeyConditions\":{\"id\":{\"AttributeValueList\":[{\"S\":\"k\"}],\"ComparisonOperator\":\"EQ\"}},\"ScanIndexForward\":true}", + "key-condition-expression" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_String\",\"ConsistentRead\":true,\"ScanIndexForward\":true,\"KeyConditionExpression\":\"#i = :v\",\"ExpressionAttributeNames\":{\"#i\":\"id\"},\"ExpressionAttributeValues\":{\":v\":{\"S\":\"k\"}}}", + "projection-expression" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_String\",\"ConsistentRead\":true,\"KeyConditions\":{\"id\":{\"AttributeValueList\":[{\"S\":\"k\"}],\"ComparisonOperator\":\"EQ\"}},\"ScanIndexForward\":true,\"ProjectionExpression\":\"#v\",\"ExpressionAttributeNames\":{\"#v\":\"value\"}}", + "query-filter" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_String\",\"ConsistentRead\":true,\"KeyConditions\":{\"id\":{\"AttributeValueList\":[{\"S\":\"k\"}],\"ComparisonOperator\":\"EQ\"}},\"QueryFilter\":{\"value\":{\"AttributeValueList\":[{\"S\":\"hello\"}],\"ComparisonOperator\":\"EQ\"}},\"ScanIndexForward\":true}", + "range-condition-limit-desc" : "DynamoDB_20120810.Query\n{\"TableName\":\"M_Range\",\"Limit\":10,\"ConsistentRead\":true,\"KeyConditions\":{\"range\":{\"AttributeValueList\":[{\"N\":\"5\"}],\"ComparisonOperator\":\"GT\"},\"id\":{\"AttributeValueList\":[{\"S\":\"k\"}],\"ComparisonOperator\":\"EQ\"}},\"ScanIndexForward\":false}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/scan_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/scan_fixture.json new file mode 100644 index 000000000000..cfaee2ce4260 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/scan_fixture.json @@ -0,0 +1,8 @@ +{ + "consistent-read" : "DynamoDB_20120810.Scan\n{\"TableName\":\"M_String\",\"ConsistentRead\":true}", + "filter-expression" : "DynamoDB_20120810.Scan\n{\"TableName\":\"M_String\",\"FilterExpression\":\"#v = :v\",\"ExpressionAttributeNames\":{\"#v\":\"value\"},\"ExpressionAttributeValues\":{\":v\":{\"S\":\"hello\"}}}", + "filtered-limited" : "DynamoDB_20120810.Scan\n{\"TableName\":\"M_String\",\"Limit\":25,\"ScanFilter\":{\"value\":{\"AttributeValueList\":[{\"S\":\"hello\"}],\"ComparisonOperator\":\"EQ\"}}}", + "projection-expression" : "DynamoDB_20120810.Scan\n{\"TableName\":\"M_String\",\"ProjectionExpression\":\"#v\",\"ExpressionAttributeNames\":{\"#v\":\"value\"}}", + "segment" : "DynamoDB_20120810.Scan\n{\"TableName\":\"M_String\",\"TotalSegments\":4,\"Segment\":1}", + "unfiltered" : "DynamoDB_20120810.Scan\n{\"TableName\":\"M_String\"}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/transaction_load_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/transaction_load_fixture.json new file mode 100644 index 000000000000..4b9c93ccce19 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/transaction_load_fixture.json @@ -0,0 +1,3 @@ +{ + "two-loads" : "DynamoDB_20120810.TransactGetItems\n{\"TransactItems\":[{\"Get\":{\"Key\":{\"id\":{\"S\":\"a\"}},\"TableName\":\"M_String\"}},{\"Get\":{\"Key\":{\"id\":{\"S\":\"b\"}},\"TableName\":\"M_String\"}}]}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/transaction_write_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/transaction_write_fixture.json new file mode 100644 index 000000000000..aa716bac9a6d --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/transaction_write_fixture.json @@ -0,0 +1,5 @@ +{ + "condition-check" : "DynamoDB_20120810.TransactWriteItems\n{\"TransactItems\":[{\"ConditionCheck\":{\"Key\":{\"id\":{\"S\":\"c\"}},\"TableName\":\"M_String\",\"ConditionExpression\":\"attribute_exists(#i)\",\"ExpressionAttributeNames\":{\"#i\":\"id\"}}}],\"ClientRequestToken\":\"fixed-token\"}", + "put-update-delete" : "DynamoDB_20120810.TransactWriteItems\n{\"TransactItems\":[{\"Put\":{\"Item\":{\"id\":{\"S\":\"k\"},\"value\":{\"S\":\"p\"}},\"TableName\":\"M_String\"}},{\"Update\":{\"Key\":{\"id\":{\"S\":\"k\"}},\"UpdateExpression\":\"SET #68a00 = :68a00\",\"TableName\":\"M_String\",\"ExpressionAttributeNames\":{\"#68a00\":\"value\"},\"ExpressionAttributeValues\":{\":68a00\":{\"S\":\"u\"}}}},{\"Delete\":{\"Key\":{\"id\":{\"S\":\"d\"}},\"TableName\":\"M_String\"}}],\"ClientRequestToken\":\"fixed-token\"}", + "versioned-auto-condition" : "DynamoDB_20120810.TransactWriteItems\n{\"TransactItems\":[{\"Put\":{\"Item\":{\"id\":{\"S\":\"k\"},\"version\":{\"N\":\"1\"}},\"TableName\":\"M_Versioned\",\"ConditionExpression\":\"attribute_not_exists(#versionAttributeName1)\",\"ExpressionAttributeNames\":{\"#versionAttributeName1\":\"version\"}}}],\"ClientRequestToken\":\"fixed-token\"}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/unmarshall_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/unmarshall_item_fixture.json new file mode 100644 index 000000000000..88122efe623a --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/unmarshall_item_fixture.json @@ -0,0 +1,17 @@ +{ + "bool-native-false" : "{\n \"id\" : \"k\",\n \"nativeBool\" : false\n}", + "bool-native-true" : "{\n \"id\" : \"k\",\n \"nativeBool\" : true\n}", + "bool-numeric-false" : "{\n \"id\" : \"k\",\n \"numericBool\" : false\n}", + "bool-numeric-true" : "{\n \"id\" : \"k\",\n \"numericBool\" : true\n}", + "document" : "{\n \"document\" : {\n \"city\" : \"Seattle\",\n \"zip\" : 98101\n },\n \"id\" : \"k\"\n}", + "double" : "{\n \"doubleValue\" : 1.5,\n \"id\" : \"k\"\n}", + "enum" : "{\n \"enumValue\" : \"GREEN\",\n \"id\" : \"k\"\n}", + "list" : "{\n \"id\" : \"k\",\n \"list\" : [ \"first\", \"second\" ]\n}", + "map" : "{\n \"id\" : \"k\",\n \"map\" : {\n \"a\" : \"1\",\n \"b\" : \"2\"\n }\n}", + "number" : "{\n \"id\" : \"k\",\n \"number\" : 42\n}", + "number-negative" : "{\n \"id\" : \"k\",\n \"number\" : -7\n}", + "number-set" : "{\n \"id\" : \"k\",\n \"numberSet\" : [ 1, 2, 3 ]\n}", + "string" : "{\n \"id\" : \"k\",\n \"value\" : \"hello\"\n}", + "string-set" : "{\n \"id\" : \"k\",\n \"stringSet\" : [ \"a\", \"b\", \"c\" ]\n}", + "string-unicode" : "{\n \"id\" : \"k\",\n \"value\" : \"héllo-世界-\uD83D\uDE00\"\n}" +} \ No newline at end of file diff --git a/services-custom/dynamodb-mapper/src/test/resources/update_item_fixture.json b/services-custom/dynamodb-mapper/src/test/resources/update_item_fixture.json new file mode 100644 index 000000000000..9ac22408e896 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/resources/update_item_fixture.json @@ -0,0 +1,8 @@ +{ + "append-set-behavior" : "DynamoDB_20120810.UpdateItem\n{\"TableName\":\"M_AllTypes\",\"Key\":{\"id\":{\"S\":\"k\"}},\"AttributeUpdates\":{\"stringSet\":{\"Value\":{\"SS\":[\"a\",\"b\"]},\"Action\":\"ADD\"}},\"ReturnValues\":\"ALL_NEW\"}", + "null-attr-delete" : "DynamoDB_20120810.UpdateItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"AttributeUpdates\":{\"value\":{\"Action\":\"DELETE\"}},\"ReturnValues\":\"ALL_NEW\"}", + "null-attr-skip" : "DynamoDB_20120810.UpdateItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"AttributeUpdates\":{},\"ReturnValues\":\"ALL_NEW\"}", + "save-default-update" : "DynamoDB_20120810.UpdateItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"AttributeUpdates\":{\"value\":{\"Value\":{\"S\":\"hello\"},\"Action\":\"PUT\"}},\"ReturnValues\":\"ALL_NEW\"}", + "save-with-expected-expression" : "DynamoDB_20120810.UpdateItem\n{\"TableName\":\"M_String\",\"Key\":{\"id\":{\"S\":\"k\"}},\"AttributeUpdates\":{\"value\":{\"Value\":{\"S\":\"hello\"},\"Action\":\"PUT\"}},\"Expected\":{\"value\":{\"Exists\":false}},\"ReturnValues\":\"ALL_NEW\"}", + "versioned-first-save" : "DynamoDB_20120810.UpdateItem\n{\"TableName\":\"M_Versioned\",\"Key\":{\"id\":{\"S\":\"k\"}},\"AttributeUpdates\":{\"version\":{\"Value\":{\"N\":\"1\"},\"Action\":\"PUT\"}},\"Expected\":{\"version\":{\"Exists\":false}},\"ReturnValues\":\"ALL_NEW\"}" +} \ No newline at end of file From e44c66c9ccd86d4a3363ed8d4456447cedc95ba7 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Sun, 9 Aug 2026 23:11:09 -0700 Subject: [PATCH 2/5] Porting operations and test to v2 --- services-custom/dynamodb-mapper/pom.xml | 45 +- .../mapper/dynamodb/BatchLoadContext.java | 29 +- .../dynamodb/DynamoDBDeleteExpression.java | 9 +- .../mapper/dynamodb/DynamoDBHashKey.java | 2 +- .../awssdk/mapper/dynamodb/DynamoDBKeyed.java | 2 +- .../mapper/dynamodb/DynamoDBMapper.java | 643 +++++++++--------- .../mapper/dynamodb/DynamoDBMapperConfig.java | 10 +- .../dynamodb/DynamoDBMapperFieldModel.java | 58 +- .../dynamodb/DynamoDBMapperTableModel.java | 14 +- .../dynamodb/DynamoDBQueryExpression.java | 13 +- .../mapper/dynamodb/DynamoDBRangeKey.java | 2 +- .../dynamodb/DynamoDBScanExpression.java | 15 +- .../mapper/dynamodb/DynamoDBTableMapper.java | 51 +- .../awssdk/mapper/dynamodb/PaginatedList.java | 8 +- .../dynamodb/PaginatedParallelScanList.java | 12 +- .../mapper/dynamodb/PaginatedQueryList.java | 28 +- .../mapper/dynamodb/PaginatedScanList.java | 28 +- .../mapper/dynamodb/ParallelScanTask.java | 77 +-- .../mapper/dynamodb/QueryResultPage.java | 2 +- .../mapper/dynamodb/ScanResultPage.java | 2 +- .../dynamodb/StandardAnnotationMaps.java | 6 +- .../dynamodb/TransactionWriteRequest.java | 2 +- .../mapper/dynamodb/AsyncServiceTest.java | 246 ------- .../dynamodb/BatchLoadRetryStrategyTest.java | 163 +++-- .../awssdk/mapper/dynamodb/BatchLoadTest.java | 14 +- .../dynamodb/BatchWriteRetryStrategyTest.java | 113 +-- .../dynamodb/ConvenientMapSetterTest.java | 92 --- ...amoDBMapperExpressionsIntegrationTest.java | 170 +++-- .../awssdk/mapper/dynamodb/LocalDynamoDB.java | 61 +- .../dynamodb/LocalDynamoDBTestBase.java | 20 +- .../dynamodb/PaginatedScanTaskTest.java | 29 +- .../mapper/dynamodb/RequestProgressTest.java | 211 ------ .../mapper/dynamodb/SecondaryIndexesTest.java | 456 ------------- .../awssdk/mapper/dynamodb/ServiceTest.java | 409 ----------- .../dynamodb/StandardModelFactoriesTest.java | 2 +- .../mapper/dynamodb/TestObjectCreator.java | 132 ++-- .../dynamodb/TransactionLoadUnitTest.java | 6 +- .../TransactionWriteTableMapperUnitTest.java | 6 +- .../dynamodb/TransactionWriteUnitTest.java | 73 +- .../dynamodb/TransactionsUnitTestBase.java | 10 +- ...eConditionExpressionGeneratorUnitTest.java | 2 +- .../AutoGeneratedKeysIntegrationTest.java | 99 +-- .../dynamodb/mapper/BatchWriteTest.java | 10 +- .../BinaryAttributesIntegrationTest.java | 25 +- .../mapper/CrossSDKIntegrationTest.java | 253 ------- .../DynamoDBTypeConvertedEpochDateTest.java | 50 +- .../EmptyBinaryByteArrayAttributesTest.java | 50 +- .../EmptyBinaryByteBufferAttributesTest.java | 45 +- ...EmptyBinarySetByteArrayAttributesTest.java | 53 +- ...mptyBinarySetByteBufferAttributesTest.java | 45 +- .../ExceptionHandlingIntegrationTest.java | 24 +- ...ndexRangeKeyAttributesIntegrationTest.java | 98 +-- .../mapper/KeyOnlyPutIntegrationTest.java | 14 +- .../mapper/MapperQueryExpressionTest.java | 221 +++--- .../MapperSaveConfigIntegrationTest.java | 109 +-- .../mapper/MapperSaveConfigTestBase.java | 81 ++- .../NumericSetAttributesIntegrationTest.java | 46 +- .../dynamodb/mapper/QueryIntegrationTest.java | 26 +- .../RangeKeyAttributesIntegrationTest.java | 38 +- .../ScalarAttributeIntegrationTest.java | 2 +- ...impleNumericAttributesIntegrationTest.java | 90 +-- ...SimpleStringAttributesIntegrationTest.java | 20 +- .../StringSetAttributesIntegrationTest.java | 22 +- .../mapper/TableMapperIntegrationTest.java | 2 +- .../mapper/TransactionLoadExpressionTest.java | 6 +- .../mapper/TransactionLoadMixedTest.java | 4 +- .../TransactionLoadTableMapperTest.java | 2 +- ...ansactionWriteConditionExpressionTest.java | 36 +- .../TransactionWriteMiscellaneousTest.java | 78 ++- .../mapper/TransactionWriteMixedTest.java | 13 +- .../mapper/TransactionWriteSanityTest.java | 2 +- .../TransactionWriteTableMapperTest.java | 18 +- .../TransactionWriteVersionAttributeTest.java | 4 +- .../dynamodb/mapper/TransactionsTestBase.java | 7 +- .../mapper/TypeConvertedJsonTest.java | 24 +- .../dynamodb/mapper/TypedIntegrationTest.java | 6 +- .../mapper/V2CompatibleBooleansTest.java | 81 +-- ...VersionAttributeUpdateIntegrationTest.java | 41 +- .../pojos/AllSupportedAnnotationsClass.java | 2 +- .../pojos/CrossSDKVerificationClass.java | 437 ------------ .../dynamodb/shape/ShapeRequestTest.java | 98 +-- .../dynamodb/shape/ShapeResponseTest.java | 5 +- .../mapper/dynamodb/shape/ShapeSupport.java | 16 +- .../mapper/dynamodb/test/AWSTestBase.java | 62 +- .../mapper/dynamodb/test/retry/RetryRule.java | 4 +- .../util/DynamoDBIntegrationTestBase.java | 206 +++--- .../dynamodb/test/util/DynamoDBTestBase.java | 46 +- .../test/util/DynamoDBUnitTestBase.java | 11 +- .../dynamodb/test/util/InputStreamUtils.java | 4 +- ...ressListenerWithEventCodeVerification.java | 48 -- .../mapper/dynamodb/test/util/SdkAsserts.java | 29 +- .../mapper/dynamodb/utils/AttributeAdder.java | 4 +- .../dynamodb/utils/NullAttributeAdder.java | 2 +- 93 files changed, 1951 insertions(+), 4041 deletions(-) delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/AsyncServiceTest.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ConvenientMapSetterTest.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/RequestProgressTest.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/SecondaryIndexesTest.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ServiceTest.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/CrossSDKIntegrationTest.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/CrossSDKVerificationClass.java delete mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/ProgressListenerWithEventCodeVerification.java diff --git a/services-custom/dynamodb-mapper/pom.xml b/services-custom/dynamodb-mapper/pom.xml index aa87523f3cd7..7e7416899dc3 100644 --- a/services-custom/dynamodb-mapper/pom.xml +++ b/services-custom/dynamodb-mapper/pom.xml @@ -37,6 +37,45 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + + + software/amazon/awssdk/mapper/dynamodb/ConfigureS3LinksTest.java + software/amazon/awssdk/mapper/dynamodb/DynamoDBS3IntegrationTest.java + software/amazon/awssdk/mapper/dynamodb/DynamoDBS3IntegrationTestBase.java + software/amazon/awssdk/mapper/dynamodb/GenerateDeleteTableRequestTest.java + software/amazon/awssdk/mapper/dynamodb/GsiAlwaysUpdateTest.java + software/amazon/awssdk/mapper/dynamodb/LocalDynamoDB.java + software/amazon/awssdk/mapper/dynamodb/LocalDynamoDBTestBase.java + software/amazon/awssdk/mapper/dynamodb/S3ClientCacheIntegrationTest.java + software/amazon/awssdk/mapper/dynamodb/S3LinkIDTest.java + software/amazon/awssdk/mapper/dynamodb/S3LinkTest.java + software/amazon/awssdk/mapper/dynamodb/BatchLoadTest.java + software/amazon/awssdk/mapper/dynamodb/mapper/BatchWriteTest.java + + software/amazon/awssdk/mapper/dynamodb/JsonIntegrationTest.java + software/amazon/awssdk/mapper/dynamodb/mapper/GenerateCreateTableRequest2Test.java + software/amazon/awssdk/mapper/dynamodb/mapper/GenerateCreateTableRequestTest.java + software/amazon/awssdk/mapper/dynamodb/mapper/HashKeyOnlyTableWithGSITest.java + software/amazon/awssdk/mapper/dynamodb/mapper/MapperLoadingStrategyConfigTest.java + software/amazon/awssdk/mapper/dynamodb/mapper/ScanTest.java + software/amazon/awssdk/mapper/dynamodb/test/AWSIntegrationTestBase.java + software/amazon/awssdk/mapper/dynamodb/test/resources/DynamoDBTableResource.java + software/amazon/awssdk/mapper/dynamodb/test/resources/ResourceCentricBlockJUnit4ClassRunner.java + software/amazon/awssdk/mapper/dynamodb/test/resources/TestResourceUtils.java + software/amazon/awssdk/mapper/dynamodb/test/resources/tables/BasicTempTable.java + software/amazon/awssdk/mapper/dynamodb/test/resources/tables/TempTableWithBinaryKey.java + software/amazon/awssdk/mapper/dynamodb/test/resources/tables/TempTableWithSecondaryIndexes.java + + + + org.apache.maven.plugins maven-jar-plugin @@ -127,12 +166,6 @@ 1.10.19 test - - org.easymock - easymock - 3.6 - test - log4j log4j diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadContext.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadContext.java index 6dad003936ff..1439b5831a0f 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadContext.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadContext.java @@ -16,9 +16,9 @@ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemResult; -import com.amazonaws.util.ValidationUtils; +import java.util.Objects; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemResponse; /** @@ -28,13 +28,13 @@ */ public class BatchLoadContext { /** - * The BatchGetItemResult returned by the DynamoDB client. + * The BatchGetItemResponse returned by the DynamoDB client. */ - private BatchGetItemResult batchGetItemResult; + private BatchGetItemResponse batchGetItemResult; /** * The BatchGetItemRequest. */ - private final BatchGetItemRequest batchGetItemRequest; + private BatchGetItemRequest batchGetItemRequest; /** * The number of times the request has been retried. */ @@ -45,22 +45,22 @@ public class BatchLoadContext { * @param batchGetItemRequest see {@link BatchGetItemRequest}. * */ public BatchLoadContext(BatchGetItemRequest batchGetItemRequest) { - this.batchGetItemRequest = ValidationUtils.assertNotNull(batchGetItemRequest, "batchGetItemRequest"); + this.batchGetItemRequest = Objects.requireNonNull(batchGetItemRequest, "batchGetItemRequest"); this.batchGetItemResult = null; this.retriesAttempted = 0; } /** - * @return the BatchGetItemResult + * @return the BatchGetItemResponse */ - public BatchGetItemResult getBatchGetItemResult() { + public BatchGetItemResponse getBatchGetItemResult() { return batchGetItemResult; } /** - * @return the BatchGetItemResult + * @return the BatchGetItemResponse */ - public void setBatchGetItemResult(BatchGetItemResult batchGetItemResult) { + public void setBatchGetItemResult(BatchGetItemResponse batchGetItemResult) { this.batchGetItemResult = batchGetItemResult; } @@ -72,6 +72,13 @@ public BatchGetItemRequest getBatchGetItemRequest() { return batchGetItemRequest; } + /** + * Updates the BatchGetItemRequest for the next retry attempt. + */ + public void setBatchGetItemRequest(BatchGetItemRequest batchGetItemRequest) { + this.batchGetItemRequest = batchGetItemRequest; + } + /** * Gets the retriesAttempted. * diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBDeleteExpression.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBDeleteExpression.java index 305660d97f3f..ecc9943289a7 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBDeleteExpression.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBDeleteExpression.java @@ -19,9 +19,9 @@ import java.util.Map; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; -import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; /** * Enables adding options to a delete operation. @@ -312,9 +312,6 @@ public DynamoDBDeleteExpression withExpressionAttributeValues( * @param value * The corresponding value of the entry to be added into * ExpressionAttributeValues. - * - * @see DeleteItemRequest#addExpressionAttributeValuesEntry(String, - * AttributeValue) */ public DynamoDBDeleteExpression addExpressionAttributeValuesEntry( String key, AttributeValue value) { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBHashKey.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBHashKey.java index 7ab27e5a1db6..9baa7a59c619 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBHashKey.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBHashKey.java @@ -28,7 +28,7 @@ * This annotation is required. */ @DynamoDB -@DynamoDBKeyed(com.amazonaws.services.dynamodbv2.model.KeyType.HASH) +@DynamoDBKeyed(software.amazon.awssdk.services.dynamodb.model.KeyType.HASH) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface DynamoDBHashKey { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBKeyed.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBKeyed.java index 6cbcfd8ad0a1..aa3887e22dbd 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBKeyed.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBKeyed.java @@ -14,7 +14,7 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.KeyType; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java index d94ccc23d86f..be2d94e0339e 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java @@ -14,63 +14,61 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.AmazonWebServiceRequest; -import com.amazonaws.SdkClientException; import com.amazonaws.auth.AWSCredentialsProvider; -import com.amazonaws.retry.RetryUtils; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.core.retry.RetryUtils; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.BatchLoadRetryStrategy; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.BatchWriteRetryStrategy; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.ConsistentReads; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.SaveBehavior; -import com.amazonaws.services.dynamodbv2.model.AttributeAction; +import software.amazon.awssdk.services.dynamodb.model.AttributeAction; import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemResult; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemResult; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.ConditionCheck; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemResponse; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.ConditionCheck; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.Delete; -import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteRequest; +import software.amazon.awssdk.services.dynamodb.model.Delete; +import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest; +import software.amazon.awssdk.services.dynamodb.model.DeleteRequest; import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; -import com.amazonaws.services.dynamodbv2.model.Get; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.ItemResponse; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.Get; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.ItemResponse; import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes; -import com.amazonaws.services.dynamodbv2.model.Put; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.PutItemResult; -import com.amazonaws.services.dynamodbv2.model.PutRequest; -import com.amazonaws.services.dynamodbv2.model.QueryRequest; -import com.amazonaws.services.dynamodbv2.model.QueryResult; -import com.amazonaws.services.dynamodbv2.model.ReturnValue; -import com.amazonaws.services.dynamodbv2.model.ReturnValuesOnConditionCheckFailure; +import software.amazon.awssdk.services.dynamodb.model.KeysAndAttributes; +import software.amazon.awssdk.services.dynamodb.model.Put; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.PutItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutRequest; +import software.amazon.awssdk.services.dynamodb.model.QueryRequest; +import software.amazon.awssdk.services.dynamodb.model.QueryResponse; +import software.amazon.awssdk.services.dynamodb.model.ReturnValue; +import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; -import com.amazonaws.services.dynamodbv2.model.ScanResult; -import com.amazonaws.services.dynamodbv2.model.Select; -import com.amazonaws.services.dynamodbv2.model.TransactGetItem; -import com.amazonaws.services.dynamodbv2.model.TransactGetItemsRequest; -import com.amazonaws.services.dynamodbv2.model.TransactGetItemsResult; -import com.amazonaws.services.dynamodbv2.model.TransactWriteItem; -import com.amazonaws.services.dynamodbv2.model.TransactWriteItemsRequest; -import com.amazonaws.services.dynamodbv2.model.Update; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; -import com.amazonaws.services.dynamodbv2.model.WriteRequest; +import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.awssdk.services.dynamodb.model.ScanResponse; +import software.amazon.awssdk.services.dynamodb.model.Select; +import software.amazon.awssdk.services.dynamodb.model.TransactGetItem; +import software.amazon.awssdk.services.dynamodb.model.TransactGetItemsRequest; +import software.amazon.awssdk.services.dynamodb.model.TransactGetItemsResponse; +import software.amazon.awssdk.services.dynamodb.model.TransactWriteItem; +import software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest; +import software.amazon.awssdk.services.dynamodb.model.Update; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; +import software.amazon.awssdk.services.dynamodb.model.WriteRequest; import com.amazonaws.services.s3.model.Region; -import com.amazonaws.util.VersionInfoUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -90,8 +88,8 @@ import java.util.Map.Entry; import java.util.Set; -import static com.amazonaws.services.dynamodbv2.model.KeyType.HASH; -import static com.amazonaws.services.dynamodbv2.model.KeyType.RANGE; +import static software.amazon.awssdk.services.dynamodb.model.KeyType.HASH; +import static software.amazon.awssdk.services.dynamodb.model.KeyType.RANGE; import static software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest.TransactionWriteOperation; import static software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest.TransactionWriteOperationType; @@ -208,7 +206,7 @@ */ public class DynamoDBMapper extends AbstractDynamoDBMapper { - private final AmazonDynamoDB db; + private final DynamoDbClient db; private final DynamoDBMapperModelFactory models; private final S3Link.Factory s3Links; @@ -229,16 +227,6 @@ public class DynamoDBMapper extends AbstractDynamoDBMapper { */ static final int BATCH_GET_MAX_RETRY_COUNT_ALL_KEYS = 5; - /** - * User agent for requests made using the {@link DynamoDBMapper}. - */ - private static final String USER_AGENT = - DynamoDBMapper.class.getName() + "/" + VersionInfoUtils.getVersion(); - private static final String USER_AGENT_BATCH_OPERATION = - DynamoDBMapper.class.getName() + "_batch_operation/" + VersionInfoUtils.getVersion(); - private static final String USER_AGENT_TRANSACTION_OPERATION = - DynamoDBMapper.class.getName() + "_transaction_operation/" + VersionInfoUtils.getVersion(); - private static final Log log = LogFactory.getLog(DynamoDBMapper.class); /** @@ -286,7 +274,7 @@ private static void failFastOnIncompatibleSubclass(Class clazz) { * The service object to use for all service calls. * @see DynamoDBMapperConfig#DEFAULT */ - public DynamoDBMapper(final AmazonDynamoDB dynamoDB) { + public DynamoDBMapper(final DynamoDbClient dynamoDB) { this(dynamoDB, DynamoDBMapperConfig.DEFAULT, null, null); } @@ -300,7 +288,7 @@ public DynamoDBMapper(final AmazonDynamoDB dynamoDB) { * be overridden on a per-operation basis. */ public DynamoDBMapper( - final AmazonDynamoDB dynamoDB, + final DynamoDbClient dynamoDB, final DynamoDBMapperConfig config) { this(dynamoDB, config, null, null); @@ -318,7 +306,7 @@ public DynamoDBMapper( * @see DynamoDBMapperConfig#DEFAULT */ public DynamoDBMapper( - final AmazonDynamoDB ddb, + final DynamoDbClient ddb, final AWSCredentialsProvider s3CredentialProvider) { this(ddb, DynamoDBMapperConfig.DEFAULT, s3CredentialProvider); @@ -338,7 +326,7 @@ public DynamoDBMapper( * deserializing an object. */ public DynamoDBMapper( - final AmazonDynamoDB dynamoDB, + final DynamoDbClient dynamoDB, final DynamoDBMapperConfig config, final AttributeTransformer transformer) { @@ -359,7 +347,7 @@ public DynamoDBMapper( * Relevant only if {@link S3Link} is involved. */ public DynamoDBMapper( - final AmazonDynamoDB dynamoDB, + final DynamoDbClient dynamoDB, final DynamoDBMapperConfig config, final AWSCredentialsProvider s3CredentialProvider) { @@ -394,7 +382,7 @@ private static AWSCredentialsProvider validate( * Relevant only if {@link S3Link} is involved. */ public DynamoDBMapper( - final AmazonDynamoDB dynamoDB, + final DynamoDbClient dynamoDB, final DynamoDBMapperConfig config, final AttributeTransformer transformer, final AWSCredentialsProvider s3CredentialsProvider) { @@ -425,19 +413,17 @@ public T load(T keyObject, DynamoDBMapperConfig config) { String tableName = getTableName(clazz, keyObject, config); - GetItemRequest rq = new GetItemRequest() - .withRequestMetricCollector(config.getRequestMetricCollector()); - Map key = model.convertKey(keyObject); - rq.setKey(key); - rq.setTableName(tableName); - rq.setConsistentRead(config.getConsistentReads() == ConsistentReads.CONSISTENT); - + GetItemRequest rq = GetItemRequest.builder() + .key(key) + .tableName(tableName) + .consistentRead(config.getConsistentReads() == ConsistentReads.CONSISTENT) + .build(); - GetItemResult item = db.getItem(applyUserAgent(rq)); - Map itemAttributes = item.getItem(); - if ( itemAttributes == null ) { + GetItemResponse item = db.getItem(rq); + Map itemAttributes = item.item(); + if ( itemAttributes == null || itemAttributes.isEmpty() ) { return null; } @@ -541,8 +527,8 @@ protected void onPrimaryKeyAttributeValue(String attributeName, AttributeValue keyAttributeValue) { /* Treat key values as common attribute value updates. */ getAttributeValueUpdates().put(attributeName, - new AttributeValueUpdate().withValue(keyAttributeValue) - .withAction("PUT")); + AttributeValueUpdate.builder().value(keyAttributeValue) + .action("PUT").build()); } /* Use default implementation of onNonKeyAttribute(...) */ @@ -578,13 +564,13 @@ protected void onNonKeyAttribute(String attributeName, * we do an "ADD" update instead of the default "PUT". */ if (getLocalSaveBehavior() == SaveBehavior.APPEND_SET) { - if (currentValue.getBS() != null - || currentValue.getNS() != null - || currentValue.getSS() != null) { + if (currentValue.hasBs() + || currentValue.hasNs() + || currentValue.hasSs()) { getAttributeValueUpdates().put( attributeName, - new AttributeValueUpdate().withValue( - currentValue).withAction("ADD")); + AttributeValueUpdate.builder().value( + currentValue).action("ADD").build()); return; } } @@ -607,34 +593,34 @@ protected void onNullNonKeyAttribute(String attributeName) { /* Delete attributes that are set as null in the object. */ getAttributeValueUpdates() .put(attributeName, - new AttributeValueUpdate() - .withAction("DELETE")); + AttributeValueUpdate.builder() + .action("DELETE").build()); } } @Override protected void executeLowLevelRequest() { - UpdateItemResult updateItemResult = doUpdateItem(); + UpdateItemResponse updateItemResult = doUpdateItem(); // The UpdateItem request is specified to return ALL_NEW // attributes of the affected item. So if the returned - // UpdateItemResult does not include any ReturnedAttributes, + // UpdateItemResponse does not include any ReturnedAttributes, // it indicates the UpdateItem failed silently (e.g. the // key-only-put nightmare - // https://forums.aws.amazon.com/thread.jspa?threadID=86798&tstart=25), // in which case we should re-send a PutItem // request instead. - if (updateItemResult.getAttributes() == null - || updateItemResult.getAttributes().isEmpty()) { + if (!updateItemResult.hasAttributes() + || updateItemResult.attributes().isEmpty()) { // Before we proceed with PutItem, we need to put all // the key attributes (prepared for the // UpdateItemRequest) into the AttributeValueUpdates // collection. for (String keyAttributeName : getPrimaryKeyAttributeValues().keySet()) { getAttributeValueUpdates().put(keyAttributeName, - new AttributeValueUpdate() - .withValue(getPrimaryKeyAttributeValues().get(keyAttributeName)) - .withAction("PUT")); + AttributeValueUpdate.builder() + .value(getPrimaryKeyAttributeValues().get(keyAttributeName)) + .action("PUT").build()); } doPutItem(); @@ -789,8 +775,8 @@ public void execute() { * The updated value of the given attribute. */ protected void onNonKeyAttribute(String attributeName, AttributeValue currentValue) { - updateValues.put(attributeName, new AttributeValueUpdate() - .withValue(currentValue).withAction("PUT")); + updateValues.put(attributeName, AttributeValueUpdate.builder() + .value(currentValue).action("PUT").build()); } /** @@ -858,23 +844,23 @@ protected List getInMemoryUpdates() { * of the new version of the item after the update. The handler will use * the returned attributes to detect silent failure on the server-side. */ - protected UpdateItemResult doUpdateItem() { - UpdateItemRequest req = new UpdateItemRequest() - .withTableName(getTableName()) - .withKey(getPrimaryKeyAttributeValues()) - .withAttributeUpdates( + protected UpdateItemResponse doUpdateItem() { + UpdateItemRequest req = UpdateItemRequest.builder() + .tableName(getTableName()) + .key(getPrimaryKeyAttributeValues()) + .attributeUpdates( transformAttributeUpdates( this.clazz, getTableName(), getPrimaryKeyAttributeValues(), getAttributeValueUpdates(), saveConfig)) - .withExpected(mergeExpectedAttributeValueConditions()) - .withConditionalOperator(userProvidedConditionOperator) - .withReturnValues(ReturnValue.ALL_NEW) - .withRequestMetricCollector(saveConfig.getRequestMetricCollector()); + .expected(mergeExpectedAttributeValueConditions()) + .conditionalOperator(userProvidedConditionOperator) + .returnValues(ReturnValue.ALL_NEW) + .build(); - return db.updateItem(applyUserAgent(req)); + return db.updateItem(req); } /** @@ -888,7 +874,7 @@ protected UpdateItemResult doUpdateItem() { * that we used to handle by the keyOnlyPut(...) hack. * */ - protected PutItemResult doPutItem() { + protected PutItemResponse doPutItem() { Map attributeValues = convertToItem(getAttributeValueUpdates()); attributeValues = transformAttributes( @@ -896,14 +882,14 @@ protected PutItemResult doPutItem() { this.clazz, getTableName(), saveConfig)); - PutItemRequest req = new PutItemRequest() - .withTableName(getTableName()) - .withItem(attributeValues) - .withExpected(mergeExpectedAttributeValueConditions()) - .withConditionalOperator(userProvidedConditionOperator) - .withRequestMetricCollector(saveConfig.getRequestMetricCollector()); + PutItemRequest req = PutItemRequest.builder() + .tableName(getTableName()) + .item(attributeValues) + .expected(mergeExpectedAttributeValueConditions()) + .conditionalOperator(userProvidedConditionOperator) + .build(); - return db.putItem(applyUserAgent(req)); + return db.putItem(req); } /** @@ -912,7 +898,7 @@ protected PutItemResult doPutItem() { */ private void onAutoGenerate(DynamoDBMapperFieldModel field) { AttributeValue value = field.convert(field.generate(field.get(object))); - updateValues.put(field.name(), new AttributeValueUpdate().withAction("PUT").withValue(value)); + updateValues.put(field.name(), AttributeValueUpdate.builder().action("PUT").value(value).build()); inMemoryUpdates.add(new ValueUpdate(field, value, object)); } @@ -929,7 +915,7 @@ private void onAutoGenerateAssignableKey(DynamoDBMapperFieldModel field) { final Object current = field.get(object); if (current == null) { internalExpectedValueAssertions.put(field.name(), - new ExpectedAttributeValue().withExists(false)); + ExpectedAttributeValue.builder().exists(false).build()); } else { internalExpectedValueAssertions.put(field.name(), - new ExpectedAttributeValue().withExists(true).withValue(field.convert(current))); + ExpectedAttributeValue.builder().exists(true).value(field.convert(current)).build()); } } @@ -966,8 +952,8 @@ private Map convertToItem(Map map = new HashMap(); for ( Entry entry : putValues.entrySet() ) { String attributeName = entry.getKey(); - AttributeValue attributeValue = entry.getValue().getValue(); - String attributeAction = entry.getValue().getAction(); + AttributeValue attributeValue = entry.getValue().value(); + String attributeAction = entry.getValue().actionAsString(); /* * AttributeValueUpdate allows nulls for its values, since they are @@ -1018,21 +1004,16 @@ private Map transformAttributeUpdates( AttributeValueUpdate update = updateValues.get(entry.getKey()); if (update != null) { - update.getValue() - .withB(entry.getValue().getB()) - .withBS(entry.getValue().getBS()) - .withN(entry.getValue().getN()) - .withNS(entry.getValue().getNS()) - .withS(entry.getValue().getS()) - .withSS(entry.getValue().getSS()) - .withM(entry.getValue().getM()) - .withL(entry.getValue().getL()) - .withNULL(entry.getValue().getNULL()) - .withBOOL(entry.getValue().getBOOL()); + // v2 model types are immutable; replace the update's value + // with the transformed AttributeValue rather than mutating. + updateValues.put(entry.getKey(), + update.toBuilder().value(entry.getValue()).build()); } else { updateValues.put(entry.getKey(), - new AttributeValueUpdate(entry.getValue(), - "PUT")); + AttributeValueUpdate.builder() + .value(entry.getValue()) + .action("PUT") + .build()); } } @@ -1062,61 +1043,59 @@ public void delete(T object, DynamoDBDeleteExpression deleteExpression, Dyna for ( final DynamoDBMapperFieldModel field : model.versions() ) { final AttributeValue current = field.getAndConvert(object); if (current == null) { - internalAssertions.put(field.name(), new ExpectedAttributeValue(false)); + internalAssertions.put(field.name(), ExpectedAttributeValue.builder().exists(false).build()); } else { - internalAssertions.put(field.name(), new ExpectedAttributeValue(true).withValue(current)); + internalAssertions.put(field.name(), ExpectedAttributeValue.builder().exists(true).value(current).build()); } break; } } - DeleteItemRequest req = new DeleteItemRequest().withKey(key) - .withTableName(tableName).withExpected(internalAssertions) - .withRequestMetricCollector(config.getRequestMetricCollector()); + DeleteItemRequest.Builder reqBuilder = DeleteItemRequest.builder() + .key(key) + .tableName(tableName) + .expected(internalAssertions); if (deleteExpression != null) { String conditionalExpression = deleteExpression.getConditionExpression(); if (conditionalExpression != null) { if (internalAssertions != null && !internalAssertions.isEmpty()) { - throw new SdkClientException( + throw SdkClientException.create( "Condition Expressions cannot be used if a versioned attribute is present"); } - req = req - .withConditionExpression(conditionalExpression) - .withExpressionAttributeNames( + reqBuilder = reqBuilder + .conditionExpression(conditionalExpression) + .expressionAttributeNames( deleteExpression.getExpressionAttributeNames()) - .withExpressionAttributeValues( + .expressionAttributeValues( deleteExpression.getExpressionAttributeValues()); } - req = req.withExpected( + reqBuilder = reqBuilder.expected( mergeExpectedAttributeValueConditions(internalAssertions, deleteExpression.getExpected(), deleteExpression.getConditionalOperator())) - .withConditionalOperator( + .conditionalOperator( deleteExpression.getConditionalOperator()); } - db.deleteItem(applyUserAgent(req)); + db.deleteItem(reqBuilder.build()); } @Override public void transactionWrite(TransactionWriteRequest transactionWriteRequest, DynamoDBMapperConfig config) { if (transactionWriteRequest == null || isNullOrEmpty(transactionWriteRequest.getTransactionWriteOperations())) { - throw new SdkClientException("Input request is null or empty"); + throw SdkClientException.create("Input request is null or empty"); } final DynamoDBMapperConfig finalConfig = mergeConfig(config); List writeOperations = transactionWriteRequest.getTransactionWriteOperations(); List inMemoryUpdates = new LinkedList(); - TransactWriteItemsRequest transactWriteItemsRequest = new TransactWriteItemsRequest(); List transactWriteItems = new ArrayList(); - transactWriteItemsRequest.setClientRequestToken(transactionWriteRequest.getIdempotencyToken()); - for (TransactionWriteOperation writeOperation : writeOperations) { transactWriteItems.add(generateTransactWriteItem(writeOperation, inMemoryUpdates, @@ -1124,9 +1103,12 @@ public void transactionWrite(TransactionWriteRequest transactionWriteRequest, Dy } - transactWriteItemsRequest.setTransactItems(transactWriteItems); + TransactWriteItemsRequest transactWriteItemsRequest = TransactWriteItemsRequest.builder() + .clientRequestToken(transactionWriteRequest.getIdempotencyToken()) + .transactItems(transactWriteItems) + .build(); - db.transactWriteItems(applyTransactionOperationUserAgent(transactWriteItemsRequest)); + db.transactWriteItems(transactWriteItemsRequest); // Update the inMemory values for autogenerated attributeValues after successful completion of transaction for (ValueUpdate update : inMemoryUpdates) { @@ -1159,32 +1141,31 @@ public List transactionLoad(TransactionLoadRequest transactionLoadReques final DynamoDBMapperTableModel model = getTableModel(clazz, finalConfig); Map key = model.convertKey(objectToLoad); - TransactGetItem transactGetItem = new TransactGetItem(); - Get getItem = new Get(); - getItem.setTableName(tableName); - getItem.setKey(key); + Get.Builder getItem = Get.builder() + .tableName(tableName) + .key(key); if (expressionForLoad != null) { - getItem.setExpressionAttributeNames(expressionForLoad.getExpressionAttributeNames()); - getItem.setProjectionExpression(expressionForLoad.getProjectionExpression()); + getItem.expressionAttributeNames(expressionForLoad.getExpressionAttributeNames()); + getItem.projectionExpression(expressionForLoad.getProjectionExpression()); } - transactGetItem.setGet(getItem); - transactGetItems.add(transactGetItem); + transactGetItems.add(TransactGetItem.builder().get(getItem.build()).build()); } - TransactGetItemsRequest transactGetItemsRequest = new TransactGetItemsRequest(); - transactGetItemsRequest.withTransactItems(transactGetItems); - TransactGetItemsResult transactGetItemsResult = db.transactGetItems(applyTransactionOperationUserAgent(transactGetItemsRequest)); - List responseItems = transactGetItemsResult.getResponses(); + TransactGetItemsRequest transactGetItemsRequest = TransactGetItemsRequest.builder() + .transactItems(transactGetItems) + .build(); + TransactGetItemsResponse transactGetItemsResult = db.transactGetItems(transactGetItemsRequest); + List responseItems = transactGetItemsResult.responses(); List resultObjects = new ArrayList(); for (int i = 0 ; i < responseItems.size(); i++) { - if (responseItems.get(i).getItem() == null) { + if (!responseItems.get(i).hasItem()) { resultObjects.add(null); } else { resultObjects.add( privateMarshallIntoObject( - toParameters(responseItems.get(i).getItem(), + toParameters(responseItems.get(i).item(), classList.get(i), tableNameList.get(i), finalConfig))); @@ -1233,7 +1214,9 @@ public List batchWrite(Iterable objectsToWrite, AttributeTransformer.Parameters parameters = toParameters(attributeValues, clazz, tableName, config); - requestItems.add(tableName, new WriteRequest(new PutRequest(transformAttributes(parameters)))); + requestItems.add(tableName, WriteRequest.builder() + .putRequest(PutRequest.builder().item(transformAttributes(parameters)).build()) + .build()); } for ( Object toDelete : objectsToDelete ) { @@ -1244,7 +1227,9 @@ public List batchWrite(Iterable objectsToWrite, Map key = model.convertKey(toDelete); - requestItems.add(tableName, new WriteRequest(new DeleteRequest(key))); + requestItems.add(tableName, WriteRequest.builder() + .deleteRequest(DeleteRequest.builder().key(key).build()) + .build()); } // Break into chunks of 25 items and make service requests to DynamoDB @@ -1325,7 +1310,7 @@ private FailedBatch doBatchWriteItemWithRetry( Map> batch, BatchWriteRetryStrategy batchWriteRetryStrategy) { - BatchWriteItemResult result = null; + BatchWriteItemResponse result = null; int retries = 0; int maxRetries = batchWriteRetryStrategy .getMaxRetryOnUnprocessedItems(Collections @@ -1336,15 +1321,14 @@ private FailedBatch doBatchWriteItemWithRetry( while (true) { try { - result = db.batchWriteItem(applyBatchOperationUserAgent( - new BatchWriteItemRequest().withRequestItems(pendingItems))); + result = db.batchWriteItem(BatchWriteItemRequest.builder().requestItems(pendingItems).build()); } catch (Exception e) { failedBatch = new FailedBatch(); failedBatch.setUnprocessedItems(pendingItems); failedBatch.setException(e); return failedBatch; } - pendingItems = result.getUnprocessedItems(); + pendingItems = result.unprocessedItems(); if (pendingItems.size() > 0) { @@ -1375,7 +1359,8 @@ public Map> batchLoad(Iterable itemsToGet return new HashMap>(); } - Map requestItems = new HashMap(); + Map>> keysByTableName = + new HashMap>>(); Map> classesByTableName = new HashMap>(); Map> resultSet = new HashMap>(); int count = 0; @@ -1387,30 +1372,41 @@ public Map> batchLoad(Iterable itemsToGet String tableName = getTableName(clazz, keyObject, config); classesByTableName.put(tableName, clazz); - if ( !requestItems.containsKey(tableName) ) { - requestItems.put( - tableName, - new KeysAndAttributes().withConsistentRead(consistentReads).withKeys( - new LinkedList>())); + if ( !keysByTableName.containsKey(tableName) ) { + keysByTableName.put(tableName, new LinkedList>()); } - requestItems.get(tableName).getKeys().add(model.convertKey(keyObject)); + keysByTableName.get(tableName).add(model.convertKey(keyObject)); // Reach the maximum number which can be handled in a single batchGet if ( ++count == 100 ) { - processBatchGetRequest(classesByTableName, requestItems, resultSet, config); - requestItems.clear(); + processBatchGetRequest(classesByTableName, buildKeysAndAttributes(keysByTableName, consistentReads), + resultSet, config); + keysByTableName.clear(); count = 0; } } if ( count > 0 ) { - processBatchGetRequest(classesByTableName, requestItems, resultSet, config); + processBatchGetRequest(classesByTableName, buildKeysAndAttributes(keysByTableName, consistentReads), + resultSet, config); } return resultSet; } + private static Map buildKeysAndAttributes( + Map>> keysByTableName, boolean consistentReads) { + Map requestItems = new HashMap(); + for (Map.Entry>> entry : keysByTableName.entrySet()) { + requestItems.put(entry.getKey(), KeysAndAttributes.builder() + .consistentRead(consistentReads) + .keys(entry.getValue()) + .build()); + } + return requestItems; + } + @Override public Map> batchLoad(Map, List> itemsToGet, DynamoDBMapperConfig config) { config = mergeConfig(config); @@ -1437,10 +1433,10 @@ private void processBatchGetRequest( final Map> resultSet, final DynamoDBMapperConfig config) { - BatchGetItemResult batchGetItemResult = null; - BatchGetItemRequest batchGetItemRequest = new BatchGetItemRequest() - .withRequestMetricCollector(config.getRequestMetricCollector()); - batchGetItemRequest.setRequestItems(requestItems); + BatchGetItemResponse batchGetItemResult = null; + BatchGetItemRequest batchGetItemRequest = BatchGetItemRequest.builder() + .requestItems(requestItems) + .build(); BatchLoadRetryStrategy batchLoadStrategy = config.getBatchLoadRetryStrategy(); @@ -1452,17 +1448,18 @@ private void processBatchGetRequest( if ( batchGetItemResult != null ) { retries++; batchLoadContext.setRetriesAttempted(retries); - if (!isNullOrEmpty(batchGetItemResult.getUnprocessedKeys())) { + if (!isNullOrEmpty(batchGetItemResult.unprocessedKeys())) { pause(batchLoadStrategy.getDelayBeforeNextRetry(batchLoadContext)); - batchGetItemRequest.setRequestItems( - batchGetItemResult.getUnprocessedKeys()); + batchGetItemRequest = batchGetItemRequest.toBuilder() + .requestItems(batchGetItemResult.unprocessedKeys()) + .build(); + batchLoadContext.setBatchGetItemRequest(batchGetItemRequest); } } - batchGetItemResult = db.batchGetItem( - applyBatchOperationUserAgent(batchGetItemRequest)); + batchGetItemResult = db.batchGetItem(batchGetItemRequest); - Map>> responses = batchGetItemResult.getResponses(); + Map>> responses = batchGetItemResult.responses(); for ( String tableName : responses.keySet() ) { List objects = null; if ( resultSet.get(tableName) != null ) { @@ -1487,10 +1484,10 @@ private void processBatchGetRequest( // the number of unprocessed keys and Batch Load Strategy will drive the number of retries } while ( batchLoadStrategy.shouldRetry(batchLoadContext) ); - if (!isNullOrEmpty(batchGetItemResult.getUnprocessedKeys())) { + if (!isNullOrEmpty(batchGetItemResult.unprocessedKeys())) { throw new BatchGetItemException( "The BatchGetItemResult has unprocessed keys after max retry attempts. Catch the BatchGetItemException to get the list of unprocessed keys.", - batchGetItemResult.getUnprocessedKeys(), resultSet); + batchGetItemResult.unprocessedKeys(), resultSet); } } @@ -1573,7 +1570,7 @@ public PaginatedScanList scan(Class clazz, ScanRequest scanRequest = createScanRequestFromExpression(clazz, scanExpression, config); - ScanResult scanResult = db.scan(applyUserAgent(scanRequest)); + ScanResponse scanResult = db.scan(scanRequest); return new PaginatedScanList(this, clazz, db, scanRequest, scanResult, config.getPaginationLoadingStrategy(), config); } @@ -1599,16 +1596,16 @@ public ScanResultPage scanPage(Class clazz, ScanRequest scanRequest = createScanRequestFromExpression(clazz, scanExpression, config); - ScanResult scanResult = db.scan(applyUserAgent(scanRequest)); + ScanResponse scanResult = db.scan(scanRequest); ScanResultPage result = new ScanResultPage(); List> parameters = - toParameters(scanResult.getItems(), clazz, scanRequest.getTableName(), config); + toParameters(scanResult.items(), clazz, scanRequest.tableName(), config); result.setResults(marshallIntoObjects(parameters)); - result.setLastEvaluatedKey(scanResult.getLastEvaluatedKey()); - result.setCount(scanResult.getCount()); - result.setScannedCount(scanResult.getScannedCount()); - result.setConsumedCapacity(scanResult.getConsumedCapacity()); + result.setLastEvaluatedKey(scanResult.lastEvaluatedKey()); + result.setCount(scanResult.count()); + result.setScannedCount(scanResult.scannedCount()); + result.setConsumedCapacity(scanResult.consumedCapacity()); return result; } @@ -1621,7 +1618,7 @@ public PaginatedQueryList query(Class clazz, QueryRequest queryRequest = createQueryRequestFromExpression(clazz, queryExpression, config); - QueryResult queryResult = db.query(applyUserAgent(queryRequest)); + QueryResponse queryResult = db.query(queryRequest); return new PaginatedQueryList(this, clazz, db, queryRequest, queryResult, config.getPaginationLoadingStrategy(), config); } @@ -1633,17 +1630,17 @@ public QueryResultPage queryPage(Class clazz, QueryRequest queryRequest = createQueryRequestFromExpression(clazz, queryExpression, config); - QueryResult queryResult = db.query(applyUserAgent(queryRequest)); + QueryResponse queryResult = db.query(queryRequest); QueryResultPage result = new QueryResultPage(); List> parameters = - toParameters(queryResult.getItems(), clazz, queryRequest.getTableName(), config); + toParameters(queryResult.items(), clazz, queryRequest.tableName(), config); result.setResults(marshallIntoObjects(parameters)); - result.setLastEvaluatedKey(queryResult.getLastEvaluatedKey()); - result.setCount(queryResult.getCount()); - result.setScannedCount(queryResult.getScannedCount()); - result.setConsumedCapacity(queryResult.getConsumedCapacity()); + result.setLastEvaluatedKey(queryResult.lastEvaluatedKey()); + result.setCount(queryResult.count()); + result.setScannedCount(queryResult.scannedCount()); + result.setConsumedCapacity(queryResult.consumedCapacity()); return result; } @@ -1652,17 +1649,17 @@ public QueryResultPage queryPage(Class clazz, public int count(Class clazz, DynamoDBScanExpression scanExpression, DynamoDBMapperConfig config) { config = mergeConfig(config); - ScanRequest scanRequest = createScanRequestFromExpression(clazz, scanExpression, config); - scanRequest.setSelect(Select.COUNT); + ScanRequest scanRequest = createScanRequestFromExpression(clazz, scanExpression, config) + .toBuilder().select(Select.COUNT).build(); // Count scans can also be truncated for large datasets int count = 0; - ScanResult scanResult = null; + ScanResponse scanResult = null; do { - scanResult = db.scan(applyUserAgent(scanRequest)); - count += scanResult.getCount(); - scanRequest.setExclusiveStartKey(scanResult.getLastEvaluatedKey()); - } while (scanResult.getLastEvaluatedKey() != null); + scanResult = db.scan(scanRequest); + count += scanResult.count(); + scanRequest = scanRequest.toBuilder().exclusiveStartKey(scanResult.lastEvaluatedKey()).build(); + } while (scanResult.hasLastEvaluatedKey() && !scanResult.lastEvaluatedKey().isEmpty()); return count; } @@ -1671,17 +1668,17 @@ public int count(Class clazz, DynamoDBScanExpression scanExpression, DynamoDB public int count(Class clazz, DynamoDBQueryExpression queryExpression, DynamoDBMapperConfig config) { config = mergeConfig(config); - QueryRequest queryRequest = createQueryRequestFromExpression(clazz, queryExpression, config); - queryRequest.setSelect(Select.COUNT); + QueryRequest queryRequest = createQueryRequestFromExpression(clazz, queryExpression, config) + .toBuilder().select(Select.COUNT).build(); // Count queries can also be truncated for large datasets int count = 0; - QueryResult queryResult = null; + QueryResponse queryResult = null; do { - queryResult = db.query(applyUserAgent(queryRequest)); - count += queryResult.getCount(); - queryRequest.setExclusiveStartKey(queryResult.getLastEvaluatedKey()); - } while (queryResult.getLastEvaluatedKey() != null); + queryResult = db.query(queryRequest); + count += queryResult.count(); + queryRequest = queryRequest.toBuilder().exclusiveStartKey(queryResult.lastEvaluatedKey()).build(); + } while (queryResult.hasLastEvaluatedKey() && !queryResult.lastEvaluatedKey().isEmpty()); return count; } @@ -1690,28 +1687,23 @@ public int count(Class clazz, DynamoDBQueryExpression queryExpression, * @param config never null */ private ScanRequest createScanRequestFromExpression(Class clazz, DynamoDBScanExpression scanExpression, DynamoDBMapperConfig config) { - ScanRequest scanRequest = new ScanRequest(); - - scanRequest.setTableName(getTableName(clazz, config)); - scanRequest.setIndexName(scanExpression.getIndexName()); - scanRequest.setScanFilter(scanExpression.getScanFilter()); - scanRequest.setLimit(scanExpression.getLimit()); - scanRequest.setExclusiveStartKey(scanExpression.getExclusiveStartKey()); - scanRequest.setTotalSegments(scanExpression.getTotalSegments()); - scanRequest.setSegment(scanExpression.getSegment()); - scanRequest.setConditionalOperator(scanExpression.getConditionalOperator()); - scanRequest.setFilterExpression(scanExpression.getFilterExpression()); - scanRequest.setExpressionAttributeNames(scanExpression - .getExpressionAttributeNames()); - scanRequest.setExpressionAttributeValues(scanExpression - .getExpressionAttributeValues()); - scanRequest.setRequestMetricCollector(config.getRequestMetricCollector()); - scanRequest.setSelect(scanExpression.getSelect()); - scanRequest.setProjectionExpression(scanExpression.getProjectionExpression()); - scanRequest.setReturnConsumedCapacity(scanExpression.getReturnConsumedCapacity()); - scanRequest.setConsistentRead(scanExpression.isConsistentRead()); - - return applyUserAgent(scanRequest); + return ScanRequest.builder() + .tableName(getTableName(clazz, config)) + .indexName(scanExpression.getIndexName()) + .scanFilter(scanExpression.getScanFilter()) + .limit(scanExpression.getLimit()) + .exclusiveStartKey(scanExpression.getExclusiveStartKey()) + .totalSegments(scanExpression.getTotalSegments()) + .segment(scanExpression.getSegment()) + .conditionalOperator(scanExpression.getConditionalOperator()) + .filterExpression(scanExpression.getFilterExpression()) + .expressionAttributeNames(scanExpression.getExpressionAttributeNames()) + .expressionAttributeValues(scanExpression.getExpressionAttributeValues()) + .select(scanExpression.getSelect()) + .projectionExpression(scanExpression.getProjectionExpression()) + .returnConsumedCapacity(scanExpression.getReturnConsumedCapacity()) + .consistentRead(scanExpression.isConsistentRead()) + .build(); } /** @@ -1732,9 +1724,10 @@ private List createParallelScanRequestsFromExpression(Class claz List parallelScanRequests= new LinkedList(); for (int segment = 0; segment < totalSegments; segment++) { ScanRequest scanRequest = createScanRequestFromExpression(clazz, scanExpression, config); - parallelScanRequests.add(scanRequest - .withSegment(segment).withTotalSegments(totalSegments) - .withExclusiveStartKey(null)); + parallelScanRequests.add(scanRequest.toBuilder() + .segment(segment).totalSegments(totalSegments) + .exclusiveStartKey(null) + .build()); } return parallelScanRequests; } @@ -1744,28 +1737,27 @@ protected QueryRequest createQueryRequestFromExpression(Class clazz, final DynamoDBMapperTableModel model = getTableModel(clazz, config); - QueryRequest req = new QueryRequest(); - req.setConsistentRead(xpress.isConsistentRead()); - req.setTableName(getTableName(clazz, xpress.getHashKeyValues(), config)); - req.setIndexName(xpress.getIndexName()); + QueryRequest.Builder req = QueryRequest.builder(); + req.consistentRead(xpress.isConsistentRead()); + req.tableName(getTableName(clazz, xpress.getHashKeyValues(), config)); + req.indexName(xpress.getIndexName()); - req.setKeyConditionExpression(xpress.getKeyConditionExpression()); + req.keyConditionExpression(xpress.getKeyConditionExpression()); processKeyConditions(req, xpress, model); - req.withScanIndexForward(xpress.isScanIndexForward()) - .withLimit(xpress.getLimit()) - .withExclusiveStartKey(xpress.getExclusiveStartKey()) - .withQueryFilter(xpress.getQueryFilter()) - .withConditionalOperator(xpress.getConditionalOperator()) - .withSelect(xpress.getSelect()) - .withProjectionExpression(xpress.getProjectionExpression()) - .withFilterExpression(xpress.getFilterExpression()) - .withExpressionAttributeNames(xpress.getExpressionAttributeNames()) - .withExpressionAttributeValues(xpress.getExpressionAttributeValues()) - .withReturnConsumedCapacity(xpress.getReturnConsumedCapacity()) - .withRequestMetricCollector(config.getRequestMetricCollector()) + req.scanIndexForward(xpress.isScanIndexForward()) + .limit(xpress.getLimit()) + .exclusiveStartKey(xpress.getExclusiveStartKey()) + .queryFilter(xpress.getQueryFilter()) + .conditionalOperator(xpress.getConditionalOperator()) + .select(xpress.getSelect()) + .projectionExpression(xpress.getProjectionExpression()) + .filterExpression(xpress.getFilterExpression()) + .expressionAttributeNames(xpress.getExpressionAttributeNames()) + .expressionAttributeValues(xpress.getExpressionAttributeValues()) + .returnConsumedCapacity(xpress.getReturnConsumedCapacity()) ; - return applyUserAgent(req); + return req.build(); } /** @@ -1787,7 +1779,7 @@ protected QueryRequest createQueryRequestFromExpression(Class clazz, * allow at most one range key condition. */ private static void processKeyConditions( - final QueryRequest queryRequest, + final QueryRequest.Builder queryRequest, final DynamoDBQueryExpression expression, final DynamoDBMapperTableModel model ) { @@ -1808,7 +1800,7 @@ private static void processKeyConditions( final Map rangeKeyConditions = expression.getRangeKeyConditions(); // There should be least one hash key condition. - final String keyCondExpression = queryRequest.getKeyConditionExpression(); + final String keyCondExpression = expression.getKeyConditionExpression(); if (keyCondExpression == null) { if (isNullOrEmpty(hashKeyConditions)) { throw new IllegalArgumentException( @@ -1835,7 +1827,7 @@ private static void processKeyConditions( } final boolean hasRangeKeyCondition = (rangeKeyConditions != null) && (!rangeKeyConditions.isEmpty()); - final String userProvidedIndexName = queryRequest.getIndexName(); + final String userProvidedIndexName = expression.getIndexName(); final String primaryHashKeyName = model.hashKey().name(); // First collect the names of all the global/local secondary indexes that could be applied to this query. @@ -2013,7 +2005,7 @@ private static void processKeyConditions( if (hashKeyNameForThisQuery != null) { keyConditions.put(hashKeyNameForThisQuery, hashKeyConditions.get(hashKeyNameForThisQuery)); keyConditions.putAll(rangeKeyConditions); - queryRequest.setIndexName(inferredIndexName); + queryRequest.indexName(inferredIndexName); } else { throw new IllegalArgumentException( "Illegal query expression: Cannot infer the index name from the query expression."); @@ -2038,7 +2030,7 @@ private static void processKeyConditions( if ( !hasPrimaryHashKeyCondition ) { if (annotatedGSIsOnHashKeys.get(hashKeyName).size() == 1) { // Set the index if the index hash key is only annotated with one GSI. - queryRequest.setIndexName(annotatedGSIsOnHashKeys.get(hashKeyName).iterator().next()); + queryRequest.indexName(annotatedGSIsOnHashKeys.get(hashKeyName).iterator().next()); } else if (annotatedGSIsOnHashKeys.get(hashKeyName).size() > 1) { throw new IllegalArgumentException( "Ambiguous query expression: More than one GSIs (" + @@ -2057,7 +2049,7 @@ private static void processKeyConditions( } } - queryRequest.setKeyConditions(keyConditions); + queryRequest.keyConditions(keyConditions); } private AttributeTransformer.Parameters toParameters( @@ -2239,21 +2231,6 @@ private static Map mergeExpectedAttributeValueCo return mergedExpectedValues; } - static X applyUserAgent(X request) { - request.getRequestClientOptions().appendUserAgent(USER_AGENT); - return request; - } - - static X applyBatchOperationUserAgent(X request) { - request.getRequestClientOptions().appendUserAgent(USER_AGENT_BATCH_OPERATION); - return request; - } - - static X applyTransactionOperationUserAgent(X request) { - request.getRequestClientOptions().appendUserAgent(USER_AGENT_TRANSACTION_OPERATION); - return request; - } - @Override public S3ClientCache getS3ClientCache() { return s3Links.getS3ClientCache(); @@ -2276,9 +2253,9 @@ public CreateTableRequest generateCreateTableRequest(Class clazz, DynamoD final CreateTableRequest request = new CreateTableRequest(); request.setTableName(getTableName(clazz, config)); - request.withKeySchema(new KeySchemaElement(model.hashKey().name(), HASH)); + request.withKeySchema(new KeySchemaElement(model.hashKey().name(), com.amazonaws.services.dynamodbv2.model.KeyType.HASH)); if (model.rangeKeyIfExists() != null) { - request.withKeySchema(new KeySchemaElement(model.rangeKey().name(), RANGE)); + request.withKeySchema(new KeySchemaElement(model.rangeKey().name(), com.amazonaws.services.dynamodbv2.model.KeyType.RANGE)); } request.setGlobalSecondaryIndexes(model.globalSecondaryIndexes()); request.setLocalSecondaryIndexes(model.localSecondaryIndexes()); @@ -2341,13 +2318,13 @@ public Exception getException() { } private final boolean isRequestEntityTooLarge() { - return exception instanceof AmazonServiceException && - RetryUtils.isRequestEntityTooLargeException((AmazonServiceException)exception); + return exception instanceof SdkException && + RetryUtils.isRequestEntityTooLargeException((SdkException)exception); } private final boolean isThrottling() { - return exception instanceof AmazonServiceException && - RetryUtils.isThrottlingException((AmazonServiceException)exception); + return exception instanceof SdkException && + RetryUtils.isThrottlingException((SdkException)exception); } private final int size() { @@ -2404,7 +2381,7 @@ private static void pause(long delay) { Thread.sleep(delay); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new SdkClientException(e.getMessage(), e); + throw SdkClientException.create(e.getMessage(), e); } } @@ -2413,7 +2390,7 @@ public static final class BatchGetItemException extends SdkClientException { private final Map> responses; public BatchGetItemException(String message, Map unprocessedKeys, Map> responses) { - super(message); + super(SdkClientException.builder().message(message)); this.unprocessedKeys = unprocessedKeys; this.responses = responses; } @@ -2453,7 +2430,7 @@ private TransactWriteItem generateTransactWriteItem(TransactionWriteOperation tr AttributeValue currentValue = null; if (field.versioned()) { if (writeExpression != null) { - throw new SdkClientException("A transactional write operation may not also specify a condition " + + throw SdkClientException.create("A transactional write operation may not also specify a condition " + "expression if a versioned attribute is present on the " + "model of the item."); } else { @@ -2485,53 +2462,52 @@ private TransactWriteItem generateTransactWriteItem(TransactionWriteOperation tr toParameters(attributeValues, clazz, tableName, config); Map attributeValueMap = transformAttributes(parameters); - TransactWriteItem transactWriteItem = new TransactWriteItem(); + TransactWriteItem.Builder transactWriteItem = TransactWriteItem.builder(); switch (operationType) { case Put: - transactWriteItem.setPut(generatePut(tableName, attributeValueMap, returnValuesOnConditionCheckFailure, writeExpression)); + transactWriteItem.put(generatePut(tableName, attributeValueMap, returnValuesOnConditionCheckFailure, writeExpression)); break; case Update: - transactWriteItem.setUpdate( + transactWriteItem.update( generateUpdate(model, tableName, attributeValueMap, returnValuesOnConditionCheckFailure, writeExpression)); break; case ConditionCheck: - transactWriteItem.setConditionCheck( + transactWriteItem.conditionCheck( generateConditionCheck(model, tableName, objectToWrite, returnValuesOnConditionCheckFailure, writeExpression)); break; case Delete: - transactWriteItem.setDelete( + transactWriteItem.delete( generateDelete(model, tableName, objectToWrite, returnValuesOnConditionCheckFailure, writeExpression)); break; default: throw new UnsupportedOperationException("Unsupported operationType: " + operationType + " for object: " + model.convertKey(objectToWrite) + " of type: " + clazz); } - return transactWriteItem; + return transactWriteItem.build(); } private Put generatePut(String tableName, Map attributeValueMap, ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure, DynamoDBTransactionWriteExpression writeExpression) { - Put put = new Put(); - put.setItem(attributeValueMap); - put.setTableName(tableName); + Put.Builder put = Put.builder(); + put.item(attributeValueMap); + put.tableName(tableName); if (returnValuesOnConditionCheckFailure != null) { - put.setReturnValuesOnConditionCheckFailure( - returnValuesOnConditionCheckFailure.toString()); + put.returnValuesOnConditionCheckFailure(returnValuesOnConditionCheckFailure); } if (writeExpression != null) { if (writeExpression.getConditionExpression() != null) { - put.setConditionExpression(writeExpression.getConditionExpression()); + put.conditionExpression(writeExpression.getConditionExpression()); } if (!isNullOrEmpty(writeExpression.getExpressionAttributeNames())) { - put.setExpressionAttributeNames(writeExpression.getExpressionAttributeNames()); + put.expressionAttributeNames(writeExpression.getExpressionAttributeNames()); } if (!isNullOrEmpty(writeExpression.getExpressionAttributeValues())) { - put.setExpressionAttributeValues(writeExpression.getExpressionAttributeValues()); + put.expressionAttributeValues(writeExpression.getExpressionAttributeValues()); } } - return put; + return put.build(); } private Update generateUpdate(DynamoDBMapperTableModel model, @@ -2539,16 +2515,15 @@ private Update generateUpdate(DynamoDBMapperTableModel model, Map attributeValueMap, ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure, DynamoDBTransactionWriteExpression writeExpression) { - Update update = new Update(); + Update.Builder update = Update.builder(); Map expressionAttributeNamesMap = new HashMap(); Map expressionsAttributeValuesMap = new HashMap(); if (returnValuesOnConditionCheckFailure != null) { - update.setReturnValuesOnConditionCheckFailure( - returnValuesOnConditionCheckFailure.toString()); + update.returnValuesOnConditionCheckFailure(returnValuesOnConditionCheckFailure); } if (writeExpression != null) { if (writeExpression.getConditionExpression() != null) { - update.setConditionExpression(writeExpression.getConditionExpression()); + update.conditionExpression(writeExpression.getConditionExpression()); } if (!isNullOrEmpty(writeExpression.getExpressionAttributeNames())) { expressionAttributeNamesMap.putAll(writeExpression.getExpressionAttributeNames()); @@ -2584,20 +2559,20 @@ private Update generateUpdate(DynamoDBMapperTableModel model, } } - update.setTableName(tableName); - update.setUpdateExpression(new UpdateExpressionGenerator() + update.tableName(tableName); + update.updateExpression(new UpdateExpressionGenerator() .generateUpdateExpressionAndUpdateAttributeMaps(expressionAttributeNamesMap, expressionsAttributeValuesMap, nonKeyNonNullAttributeValueMap, nullValuedNonKeyAttributeNames)); - update.setKey(keyAttributeValueMap); + update.key(keyAttributeValueMap); if (expressionAttributeNamesMap.size() > 0) { - update.setExpressionAttributeNames(expressionAttributeNamesMap); + update.expressionAttributeNames(expressionAttributeNamesMap); } if (expressionsAttributeValuesMap.size() > 0) { - update.setExpressionAttributeValues(expressionsAttributeValuesMap); + update.expressionAttributeValues(expressionsAttributeValuesMap); } - return update; + return update.build(); } private ConditionCheck generateConditionCheck(DynamoDBMapperTableModel model, @@ -2605,23 +2580,22 @@ private ConditionCheck generateConditionCheck(DynamoDBMapperTableModel m Object objectToConditionCheck, ReturnValuesOnConditionCheckFailure returnValuesOnConditionCheckFailure, DynamoDBTransactionWriteExpression writeExpression) { - ConditionCheck conditionCheck = new ConditionCheck(); - conditionCheck.setKey(model.convertKey(objectToConditionCheck)); - conditionCheck.setTableName(tableName); + ConditionCheck.Builder conditionCheck = ConditionCheck.builder(); + conditionCheck.key(model.convertKey(objectToConditionCheck)); + conditionCheck.tableName(tableName); if (returnValuesOnConditionCheckFailure != null) { - conditionCheck.setReturnValuesOnConditionCheckFailure( - returnValuesOnConditionCheckFailure.toString()); + conditionCheck.returnValuesOnConditionCheckFailure(returnValuesOnConditionCheckFailure); } if (writeExpression != null) { - conditionCheck.setConditionExpression(writeExpression.getConditionExpression()); + conditionCheck.conditionExpression(writeExpression.getConditionExpression()); if (!isNullOrEmpty(writeExpression.getExpressionAttributeNames())) { - conditionCheck.setExpressionAttributeNames(writeExpression.getExpressionAttributeNames()); + conditionCheck.expressionAttributeNames(writeExpression.getExpressionAttributeNames()); } if (!isNullOrEmpty(writeExpression.getExpressionAttributeValues())) { - conditionCheck.setExpressionAttributeValues(writeExpression.getExpressionAttributeValues()); + conditionCheck.expressionAttributeValues(writeExpression.getExpressionAttributeValues()); } } - return conditionCheck; + return conditionCheck.build(); } private Delete generateDelete(DynamoDBMapperTableModel model, @@ -2631,25 +2605,24 @@ private Delete generateDelete(DynamoDBMapperTableModel model, DynamoDBTransactionWriteExpression writeExpression) { - Delete delete = new Delete(); - delete.setKey(model.convertKey(objectToDelete)); - delete.setTableName(tableName); + Delete.Builder delete = Delete.builder(); + delete.key(model.convertKey(objectToDelete)); + delete.tableName(tableName); if (returnValuesOnConditionCheckFailure != null) { - delete.setReturnValuesOnConditionCheckFailure( - returnValuesOnConditionCheckFailure.toString()); + delete.returnValuesOnConditionCheckFailure(returnValuesOnConditionCheckFailure); } if (writeExpression != null) { if (writeExpression.getConditionExpression() != null) { - delete.setConditionExpression(writeExpression.getConditionExpression()); + delete.conditionExpression(writeExpression.getConditionExpression()); } if (!isNullOrEmpty(writeExpression.getExpressionAttributeNames())) { - delete.setExpressionAttributeNames(writeExpression.getExpressionAttributeNames()); + delete.expressionAttributeNames(writeExpression.getExpressionAttributeNames()); } if (!isNullOrEmpty(writeExpression.getExpressionAttributeValues())) { - delete.setExpressionAttributeValues(writeExpression.getExpressionAttributeValues()); + delete.expressionAttributeValues(writeExpression.getExpressionAttributeValues()); } } - return delete; + return delete.build(); } } diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperConfig.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperConfig.java index adc2e3f3d5f4..806dcb1c2402 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperConfig.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperConfig.java @@ -15,8 +15,8 @@ package software.amazon.awssdk.mapper.dynamodb; import com.amazonaws.metrics.RequestMetricCollector; -import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes; -import com.amazonaws.services.dynamodbv2.model.WriteRequest; +import software.amazon.awssdk.services.dynamodb.model.KeysAndAttributes; +import software.amazon.awssdk.services.dynamodb.model.WriteRequest; import java.util.List; import java.util.Map; import java.util.Random; @@ -808,9 +808,9 @@ public static class DefaultBatchLoadRetryStrategy implements BatchLoadRetryStrat @Override public long getDelayBeforeNextRetry(final BatchLoadContext batchLoadContext) { - Map requestedKeys = batchLoadContext.getBatchGetItemRequest().getRequestItems(); + Map requestedKeys = batchLoadContext.getBatchGetItemRequest().requestItems(); Map unprocessedKeys = batchLoadContext.getBatchGetItemResult() - .getUnprocessedKeys(); + .unprocessedKeys(); long delay = 0; //Exponential backoff only when all keys are unprocessed @@ -826,7 +826,7 @@ public long getDelayBeforeNextRetry(final BatchLoadContext batchLoadContext) { @Override public boolean shouldRetry(BatchLoadContext batchLoadContext) { - Map unprocessedKeys = batchLoadContext.getBatchGetItemResult().getUnprocessedKeys(); + Map unprocessedKeys = batchLoadContext.getBatchGetItemResult().unprocessedKeys(); return (unprocessedKeys != null && unprocessedKeys.size() > 0 && batchLoadContext.getRetriesAttempted() < MAX_RETRIES); } diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperFieldModel.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperFieldModel.java index c5f0d4ac9302..1a87cc975ec2 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperFieldModel.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperFieldModel.java @@ -16,24 +16,24 @@ import static software.amazon.awssdk.mapper.dynamodb.DynamoDBAutoGenerateStrategy.ALWAYS; import static software.amazon.awssdk.mapper.dynamodb.StandardTypeConverters.Vector.LIST; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.BEGINS_WITH; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.BETWEEN; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.CONTAINS; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.EQ; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.GE; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.GT; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.IN; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NULL; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.LE; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.LT; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NE; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NOT_CONTAINS; -import static com.amazonaws.services.dynamodbv2.model.ComparisonOperator.NOT_NULL; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.BEGINS_WITH; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.BETWEEN; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.CONTAINS; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.EQ; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.GE; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.GT; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.IN; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.NULL; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.LE; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.LT; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.NE; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.NOT_CONTAINS; +import static software.amazon.awssdk.services.dynamodb.model.ComparisonOperator.NOT_NULL; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.KeyType; import java.util.Arrays; import java.util.ArrayList; @@ -224,7 +224,7 @@ public final boolean indexed() { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition beginsWith(final V value) { - return new Condition().withComparisonOperator(BEGINS_WITH).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(BEGINS_WITH).attributeValueList(convert(value)).build(); } /** @@ -236,7 +236,7 @@ public final Condition beginsWith(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition between(final V lo, final V hi) { - return new Condition().withComparisonOperator(BETWEEN).withAttributeValueList(convert(lo), convert(hi)); + return Condition.builder().comparisonOperator(BETWEEN).attributeValueList(convert(lo), convert(hi)).build(); } /** @@ -247,7 +247,7 @@ public final Condition between(final V lo, final V hi) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition contains(final V value) { - return new Condition().withComparisonOperator(CONTAINS).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(CONTAINS).attributeValueList(convert(value)).build(); } /** @@ -258,7 +258,7 @@ public final Condition contains(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition eq(final V value) { - return new Condition().withComparisonOperator(EQ).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(EQ).attributeValueList(convert(value)).build(); } /** @@ -269,7 +269,7 @@ public final Condition eq(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition ge(final V value) { - return new Condition().withComparisonOperator(GE).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(GE).attributeValueList(convert(value)).build(); } /** @@ -280,7 +280,7 @@ public final Condition ge(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition gt(final V value) { - return new Condition().withComparisonOperator(GT).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(GT).attributeValueList(convert(value)).build(); } /** @@ -291,7 +291,7 @@ public final Condition gt(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition in(final Collection values) { - return new Condition().withComparisonOperator(IN).withAttributeValueList(LIST.convert(values, this)); + return Condition.builder().comparisonOperator(IN).attributeValueList(LIST.convert(values, this)).build(); } /** @@ -312,7 +312,7 @@ public final Condition in(final V ... values) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition isNull() { - return new Condition().withComparisonOperator(NULL); + return Condition.builder().comparisonOperator(NULL).build(); } /** @@ -323,7 +323,7 @@ public final Condition isNull() { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition le(final V value) { - return new Condition().withComparisonOperator(LE).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(LE).attributeValueList(convert(value)).build(); } /** @@ -334,7 +334,7 @@ public final Condition le(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition lt(final V value) { - return new Condition().withComparisonOperator(LT).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(LT).attributeValueList(convert(value)).build(); } /** @@ -345,7 +345,7 @@ public final Condition lt(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition ne(final V value) { - return new Condition().withComparisonOperator(NE).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(NE).attributeValueList(convert(value)).build(); } /** @@ -356,7 +356,7 @@ public final Condition ne(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition notContains(final V value) { - return new Condition().withComparisonOperator(NOT_CONTAINS).withAttributeValueList(convert(value)); + return Condition.builder().comparisonOperator(NOT_CONTAINS).attributeValueList(convert(value)).build(); } /** @@ -366,7 +366,7 @@ public final Condition notContains(final V value) { * @see com.amazonaws.services.dynamodbv2.model.Condition */ public final Condition notNull() { - return new Condition().withComparisonOperator(NOT_NULL); + return Condition.builder().comparisonOperator(NOT_NULL).build(); } /** diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperTableModel.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperTableModel.java index 5c05ef6ef3a5..b6e90f79b9d3 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperTableModel.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperTableModel.java @@ -14,13 +14,13 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import static com.amazonaws.services.dynamodbv2.model.KeyType.HASH; -import static com.amazonaws.services.dynamodbv2.model.KeyType.RANGE; +import static software.amazon.awssdk.services.dynamodb.model.KeyType.HASH; +import static software.amazon.awssdk.services.dynamodb.model.KeyType.RANGE; import static com.amazonaws.services.dynamodbv2.model.ProjectionType.KEYS_ONLY; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.KeyType; import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex; -import com.amazonaws.services.dynamodbv2.model.KeyType; import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex; import com.amazonaws.services.dynamodbv2.model.Projection; @@ -381,7 +381,7 @@ public Map globalSecondaryIndexes() { ); } gsi.withProjection(new Projection().withProjectionType(KEYS_ONLY)); - gsi.withKeySchema(new KeySchemaElement(field.name(), HASH)); + gsi.withKeySchema(new KeySchemaElement(field.name(), com.amazonaws.services.dynamodbv2.model.KeyType.HASH)); } } for (final DynamoDBMapperFieldModel field : fields.values()) { @@ -392,7 +392,7 @@ public Map globalSecondaryIndexes() { targetType.getSimpleName() + "[" + field.name() + "]; no HASH key for GSI " + indexName ); } - gsi.withKeySchema(new KeySchemaElement(field.name(), RANGE)); + gsi.withKeySchema(new KeySchemaElement(field.name(), com.amazonaws.services.dynamodbv2.model.KeyType.RANGE)); } } if (map.isEmpty()) { @@ -412,8 +412,8 @@ public Map localSecondaryIndexes() { ); } lsi.withProjection(new Projection().withProjectionType(KEYS_ONLY)); - lsi.withKeySchema(new KeySchemaElement(keys.get(HASH).name(), HASH)); - lsi.withKeySchema(new KeySchemaElement(field.name(), RANGE)); + lsi.withKeySchema(new KeySchemaElement(keys.get(HASH).name(), com.amazonaws.services.dynamodbv2.model.KeyType.HASH)); + lsi.withKeySchema(new KeySchemaElement(field.name(), com.amazonaws.services.dynamodbv2.model.KeyType.RANGE)); } } if (map.isEmpty()) { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBQueryExpression.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBQueryExpression.java index cda88b11edc9..bee9ed8a77fb 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBQueryExpression.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBQueryExpression.java @@ -18,11 +18,11 @@ import java.util.Map; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; -import com.amazonaws.services.dynamodbv2.model.QueryRequest; -import com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity; -import com.amazonaws.services.dynamodbv2.model.Select; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.QueryRequest; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.Select; /** * A query expression. @@ -955,9 +955,6 @@ public DynamoDBQueryExpression withExpressionAttributeValues( * @param value * The corresponding value of the entry to be added into * ExpressionAttributeValues. - * - * @see QueryRequest#addExpressionAttributeValuesEntry(String, - * AttributeValue) */ public DynamoDBQueryExpression addExpressionAttributeValuesEntry( String key, AttributeValue value) { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBRangeKey.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBRangeKey.java index e126783d4f42..01d061852bc4 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBRangeKey.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBRangeKey.java @@ -28,7 +28,7 @@ * This annotation is required for tables that use a range key. */ @DynamoDB -@DynamoDBKeyed(com.amazonaws.services.dynamodbv2.model.KeyType.RANGE) +@DynamoDBKeyed(software.amazon.awssdk.services.dynamodb.model.KeyType.RANGE) @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface DynamoDBRangeKey { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBScanExpression.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBScanExpression.java index c199b594d0ce..57f4cd1f4e21 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBScanExpression.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBScanExpression.java @@ -18,12 +18,12 @@ import java.util.Map; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; -import com.amazonaws.services.dynamodbv2.model.ReturnConsumedCapacity; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; -import com.amazonaws.services.dynamodbv2.model.Select; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.awssdk.services.dynamodb.model.Select; /** * Options for filtering results from a scan operation. For example, callers can @@ -622,9 +622,6 @@ public DynamoDBScanExpression withExpressionAttributeValues( * @param value * The corresponding value of the entry to be added into * ExpressionAttributeValues. - * - * @see ScanRequest#addExpressionAttributeValuesEntry(String, - * AttributeValue) */ public DynamoDBScanExpression addExpressionAttributeValuesEntry(String key, AttributeValue value) { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBTableMapper.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBTableMapper.java index d04a7c3ce44d..da273ac18d7a 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBTableMapper.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBTableMapper.java @@ -14,19 +14,15 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBDeleteExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBSaveExpression; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; -import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ResourceInUseException; -import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodbv2.model.TableDescription; -import com.amazonaws.services.s3.model.Region; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.TableDescription; import java.util.Collections; import java.util.List; @@ -143,7 +139,7 @@ public final class DynamoDBTableMapper rk; private final DynamoDBMapperConfig config; private final DynamoDBMapper mapper; - private final AmazonDynamoDB db; + private final DynamoDbClient db; /** * Constructs a new table mapper for the given class. @@ -151,7 +147,7 @@ public final class DynamoDBTableMapper model) { + protected DynamoDBTableMapper(DynamoDbClient db, DynamoDBMapper mapper, final DynamoDBMapperConfig config, final DynamoDBMapperTableModel model) { this.rk = model.rangeKeyIfExists(); this.hk = model.hashKey(); this.model = model; @@ -320,8 +316,8 @@ public void save(T object, DynamoDBSaveExpression saveExpression) { public void saveIfNotExists(T object) throws ConditionalCheckFailedException { final DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); for (final DynamoDBMapperFieldModel key : model.keys()) { - saveExpression.withExpectedEntry(key.name(), new ExpectedAttributeValue() - .withExists(false)); + saveExpression.withExpectedEntry(key.name(), ExpectedAttributeValue.builder() + .exists(false).build()); } mapper.save(object, saveExpression); } @@ -338,8 +334,8 @@ public void saveIfNotExists(T object) throws ConditionalCheckFailedException { public void saveIfExists(T object) throws ConditionalCheckFailedException { final DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); for (final DynamoDBMapperFieldModel key : model.keys()) { - saveExpression.withExpectedEntry(key.name(), new ExpectedAttributeValue() - .withExists(true).withValue(key.convert(key.get(object)))); + saveExpression.withExpectedEntry(key.name(), ExpectedAttributeValue.builder() + .exists(true).value(key.convert(key.get(object))).build()); } mapper.save(object, saveExpression); } @@ -376,8 +372,8 @@ public final void delete(final T object, final DynamoDBDeleteExpression deleteEx public void deleteIfExists(T object) throws ConditionalCheckFailedException { final DynamoDBDeleteExpression deleteExpression = new DynamoDBDeleteExpression(); for (final DynamoDBMapperFieldModel key : model.keys()) { - deleteExpression.withExpectedEntry(key.name(), new ExpectedAttributeValue() - .withExists(true).withValue(key.convert(key.get(object)))); + deleteExpression.withExpectedEntry(key.name(), ExpectedAttributeValue.builder() + .exists(true).value(key.convert(key.get(object))).build()); } mapper.delete(object, deleteExpression); } @@ -469,9 +465,7 @@ public PaginatedParallelScanList parallelScan(DynamoDBScanExpression scanExpr * @see com.amazonaws.services.dynamodbv2.AmazonDynamoDB#describeTable */ public TableDescription describeTable() { - return db.describeTable( - mapper.getTableName(model.targetType(), config) - ).getTable(); + throw new UnsupportedOperationException("table admin not yet ported to v2"); } /** @@ -483,14 +477,7 @@ public TableDescription describeTable() { * @see com.amazonaws.services.dynamodbv2.model.CreateTableRequest */ public TableDescription createTable(ProvisionedThroughput throughput) { - final CreateTableRequest request = mapper.generateCreateTableRequest(model.targetType()); - request.setProvisionedThroughput(throughput); - if (request.getGlobalSecondaryIndexes() != null) { - for (final GlobalSecondaryIndex gsi : request.getGlobalSecondaryIndexes()) { - gsi.setProvisionedThroughput(throughput); - } - } - return db.createTable(request).getTableDescription(); + throw new UnsupportedOperationException("table admin not yet ported to v2"); } /** @@ -520,9 +507,7 @@ public boolean createTableIfNotExists(ProvisionedThroughput throughput) { * @see com.amazonaws.services.dynamodbv2.model.DeleteTableRequest */ public TableDescription deleteTable() { - return db.deleteTable( - mapper.generateDeleteTableRequest(model.targetType()) - ).getTableDescription(); + throw new UnsupportedOperationException("table admin not yet ported to v2"); } /** diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedList.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedList.java index 87d8edbb37ac..9cfb794c2c20 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedList.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedList.java @@ -14,7 +14,7 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.PaginationLoadingStrategy; import java.util.ArrayList; @@ -56,7 +56,7 @@ public abstract class PaginatedList implements List { protected final Class clazz; /** The client for working with DynamoDB */ - protected final AmazonDynamoDB dynamo; + protected final DynamoDbClient dynamo; /** Tracks if all results have been loaded yet or not */ protected boolean allResultsLoaded = false; @@ -84,7 +84,7 @@ public abstract class PaginatedList implements List { /** * Constructs a PaginatedList instance using the default PaginationLoadingStrategy */ - public PaginatedList(DynamoDBMapper mapper, Class clazz, AmazonDynamoDB dynamo) { + public PaginatedList(DynamoDBMapper mapper, Class clazz, DynamoDbClient dynamo) { this(mapper, clazz, dynamo, null); } @@ -103,7 +103,7 @@ public PaginatedList(DynamoDBMapper mapper, Class clazz, AmazonDynamoDB dynam * set in the mapper is not accessible here. If null value is * provided, LAZY_LOADING will be set by default. */ - public PaginatedList(DynamoDBMapper mapper, Class clazz, AmazonDynamoDB dynamo, PaginationLoadingStrategy paginationLoadingStrategy) { + public PaginatedList(DynamoDBMapper mapper, Class clazz, DynamoDbClient dynamo, PaginationLoadingStrategy paginationLoadingStrategy) { this.mapper = mapper; this.clazz = clazz; this.dynamo = dynamo; diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedParallelScanList.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedParallelScanList.java index 648703a9103e..14c0fc891c74 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedParallelScanList.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedParallelScanList.java @@ -17,9 +17,9 @@ import java.util.LinkedList; import java.util.List; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.PaginationLoadingStrategy; -import com.amazonaws.services.dynamodbv2.model.ScanResult; +import software.amazon.awssdk.services.dynamodb.model.ScanResponse; /** * Implementation of the List interface that represents the results from a parallel scan @@ -46,7 +46,7 @@ public class PaginatedParallelScanList extends PaginatedList { public PaginatedParallelScanList( DynamoDBMapper mapper, Class clazz, - AmazonDynamoDB dynamo, + DynamoDbClient dynamo, ParallelScanTask parallelScanTask, PaginationLoadingStrategy paginationLoadingStrategy, DynamoDBMapperConfig config) { @@ -74,13 +74,13 @@ protected List fetchNextPage() { return marshalParallelScanResultsIntoObjects(parallelScanTask.getNextBatchOfScanResults()); } - private List marshalParallelScanResultsIntoObjects(List scanResults) { + private List marshalParallelScanResultsIntoObjects(List scanResults) { List allItems = new LinkedList(); - for (ScanResult scanResult : scanResults) { + for (ScanResponse scanResult : scanResults) { if (null != scanResult) { allItems.addAll(mapper.marshallIntoObjects( mapper.toParameters( - scanResult.getItems(), + scanResult.items(), clazz, parallelScanTask.getTableName(), config))); diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedQueryList.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedQueryList.java index 137c37f857ac..9127334611cd 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedQueryList.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedQueryList.java @@ -16,10 +16,10 @@ import java.util.List; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.PaginationLoadingStrategy; -import com.amazonaws.services.dynamodbv2.model.QueryRequest; -import com.amazonaws.services.dynamodbv2.model.QueryResult; +import software.amazon.awssdk.services.dynamodb.model.QueryRequest; +import software.amazon.awssdk.services.dynamodb.model.QueryResponse; /** * Implementation of the List interface that represents the results from a query @@ -39,19 +39,19 @@ public class PaginatedQueryList extends PaginatedList { /** The current query request */ - private final QueryRequest queryRequest; + private QueryRequest queryRequest; private final DynamoDBMapperConfig config; /** The current results for the last executed query operation */ - private QueryResult queryResult; + private QueryResponse queryResult; public PaginatedQueryList( DynamoDBMapper mapper, Class clazz, - AmazonDynamoDB dynamo, + DynamoDbClient dynamo, QueryRequest queryRequest, - QueryResult queryResult, + QueryResponse queryResult, PaginationLoadingStrategy paginationLoadingStrategy, DynamoDBMapperConfig config ) { @@ -64,9 +64,9 @@ public PaginatedQueryList( allResults.addAll(mapper.marshallIntoObjects( mapper.toParameters( - queryResult.getItems(), + queryResult.items(), clazz, - queryRequest.getTableName(), + queryRequest.tableName(), config))); // If the results should be eagerly loaded at once @@ -77,17 +77,17 @@ public PaginatedQueryList( @Override protected boolean atEndOfResults() { - return queryResult.getLastEvaluatedKey() == null; + return !queryResult.hasLastEvaluatedKey() || queryResult.lastEvaluatedKey().isEmpty(); } @Override protected synchronized List fetchNextPage() { - queryRequest.setExclusiveStartKey(queryResult.getLastEvaluatedKey()); - queryResult = dynamo.query(DynamoDBMapper.applyUserAgent(queryRequest)); + queryRequest = queryRequest.toBuilder().exclusiveStartKey(queryResult.lastEvaluatedKey()).build(); + queryResult = dynamo.query(queryRequest); return mapper.marshallIntoObjects(mapper.toParameters( - queryResult.getItems(), + queryResult.items(), clazz, - queryRequest.getTableName(), + queryRequest.tableName(), config)); } } diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanList.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanList.java index f3462caab511..29eba071ff0f 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanList.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanList.java @@ -16,10 +16,10 @@ import java.util.List; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.PaginationLoadingStrategy; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; -import com.amazonaws.services.dynamodbv2.model.ScanResult; +import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.awssdk.services.dynamodb.model.ScanResponse; /** * Implementation of the List interface that represents the results from a scan @@ -39,19 +39,19 @@ public class PaginatedScanList extends PaginatedList { /** The current scan request */ - private final ScanRequest scanRequest; + private ScanRequest scanRequest; private final DynamoDBMapperConfig config; /** The current results for the last executed scan operation */ - private ScanResult scanResult; + private ScanResponse scanResult; public PaginatedScanList( DynamoDBMapper mapper, Class clazz, - AmazonDynamoDB dynamo, + DynamoDbClient dynamo, ScanRequest scanRequest, - ScanResult scanResult, + ScanResponse scanResult, PaginationLoadingStrategy paginationLoadingStrategy, DynamoDBMapperConfig config ) { @@ -63,9 +63,9 @@ public PaginatedScanList( allResults.addAll(mapper.marshallIntoObjects( mapper.toParameters( - scanResult.getItems(), + scanResult.items(), clazz, - scanRequest.getTableName(), + scanRequest.tableName(), config))); // If the results should be eagerly loaded at once @@ -76,17 +76,17 @@ public PaginatedScanList( @Override protected boolean atEndOfResults() { - return scanResult.getLastEvaluatedKey() == null; + return !scanResult.hasLastEvaluatedKey() || scanResult.lastEvaluatedKey().isEmpty(); } @Override protected synchronized List fetchNextPage() { - scanRequest.setExclusiveStartKey(scanResult.getLastEvaluatedKey()); - scanResult = dynamo.scan(DynamoDBMapper.applyUserAgent(scanRequest)); + scanRequest = scanRequest.toBuilder().exclusiveStartKey(scanResult.lastEvaluatedKey()).build(); + scanResult = dynamo.scan(scanRequest); return mapper.marshallIntoObjects(mapper.toParameters( - scanResult.getItems(), + scanResult.items(), clazz, - scanRequest.getTableName(), + scanRequest.tableName(), config)); } diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ParallelScanTask.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ParallelScanTask.java index 6eadf187c53c..1cda8b0df328 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ParallelScanTask.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ParallelScanTask.java @@ -14,12 +14,12 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.SdkClientException; -import com.amazonaws.AmazonClientException; -import com.amazonaws.annotation.SdkTestInternalApi; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; -import com.amazonaws.services.dynamodbv2.model.ScanResult; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.awssdk.services.dynamodb.model.ScanResponse; import java.util.ArrayList; import java.util.Collections; @@ -44,12 +44,12 @@ public class ParallelScanTask { * Cache all the future tasks, so that we can extract the exception when * we see failed segment scan. */ - private final List> segmentScanFutureTasks; + private final List> segmentScanFutureTasks; /** - * Cache all the most recent ScanResult on each segment. + * Cache all the most recent ScanResponse on each segment. */ - private final List segmentScanResults; + private final List segmentScanResults; /** * The current state of the scan on each segment. @@ -59,19 +59,19 @@ public class ParallelScanTask { private ExecutorService executorService; - private final AmazonDynamoDB dynamo; + private final DynamoDbClient dynamo; @Deprecated - public ParallelScanTask(DynamoDBMapper mapper, AmazonDynamoDB dynamo, List parallelScanRequests) { + public ParallelScanTask(DynamoDBMapper mapper, DynamoDbClient dynamo, List parallelScanRequests) { this(dynamo, parallelScanRequests); } - ParallelScanTask(AmazonDynamoDB dynamo, List parallelScanRequests) { + ParallelScanTask(DynamoDbClient dynamo, List parallelScanRequests) { this(dynamo, parallelScanRequests, Executors.newCachedThreadPool()); } @SdkTestInternalApi - ParallelScanTask(AmazonDynamoDB dynamo, List parallelScanRequests, + ParallelScanTask(DynamoDbClient dynamo, List parallelScanRequests, ExecutorService executorService) { this.dynamo = dynamo; this.parallelScanRequests = parallelScanRequests; @@ -80,8 +80,8 @@ public ParallelScanTask(DynamoDBMapper mapper, AmazonDynamoDB dynamo, List>(totalSegments)); - segmentScanResults = Collections.synchronizedList(new ArrayList(totalSegments)); + .synchronizedList(new ArrayList>(totalSegments)); + segmentScanResults = Collections.synchronizedList(new ArrayList(totalSegments)); segmentScanStates = Collections .synchronizedList(new ArrayList(totalSegments)); @@ -89,7 +89,7 @@ public ParallelScanTask(DynamoDBMapper mapper, AmazonDynamoDB dynamo, List getNextBatchOfScanResults() throws SdkClientException { + public List getNextBatchOfScanResults() throws SdkClientException { /** * Kick-off all the parallel scan tasks. */ @@ -118,7 +118,7 @@ public List getNextBatchOfScanResults() throws SdkClientException { try { segmentScanStates.wait(); } catch (InterruptedException ie) { - throw new SdkClientException("Parallel scan interrupted by other thread.", ie); + throw SdkClientException.create("Parallel scan interrupted by other thread.", ie); } } /** @@ -137,7 +137,7 @@ private void startScanNextPages() { * Assert: Should never see any task in state of "Scanning" when starting a new batch. */ if (currentSegmentState == SegmentScanState.Scanning){ - throw new SdkClientException("Should never see a 'Scanning' state when starting parallel scans."); + throw SdkClientException.create("Should never see a 'Scanning' state when starting parallel scans."); } /** * Skip any failed or completed segment, and clear the corresponding cached result. @@ -156,9 +156,9 @@ else if (currentSegmentState == SegmentScanState.Failed segmentScanStates.set(currentSegment, SegmentScanState.Scanning); segmentScanStates.notifyAll(); } - Future futureTask = executorService.submit(new Callable() { + Future futureTask = executorService.submit(new Callable() { @Override - public ScanResult call() throws Exception { + public ScanResponse call() throws Exception { try { if (currentSegmentState == SegmentScanState.HasNextPage) { return scanNextPageOfSegment(currentSegment, true); @@ -167,7 +167,7 @@ else if (currentSegmentState == SegmentScanState.Waiting) { return scanNextPageOfSegment(currentSegment, false); } else { - throw new SdkClientException("Should not start a new future task"); + throw SdkClientException.create("Should not start a new future task"); } } catch (Exception e) { synchronized (segmentScanStates) { @@ -185,8 +185,8 @@ else if (currentSegmentState == SegmentScanState.Waiting) { } } - private List marshalParallelScanResults() { - List scanResults = new LinkedList(); + private List marshalParallelScanResults() { + List scanResults = new LinkedList(); for (int segment = 0; segment < totalSegments; segment++) { SegmentScanState currentSegmentState = segmentScanStates.get(segment); /** @@ -195,43 +195,44 @@ private List marshalParallelScanResults() { if (currentSegmentState == SegmentScanState.Failed) { try { segmentScanFutureTasks.get(segment).get(); - throw new SdkClientException("No Exception found in the failed scan task."); + throw SdkClientException.create("No Exception found in the failed scan task."); } catch (ExecutionException ee) { - if ( ee.getCause() instanceof AmazonClientException) { - throw (SdkClientException) (ee.getCause()); + if ( ee.getCause() instanceof SdkException) { + throw (SdkException) (ee.getCause()); } else { - throw new SdkClientException("Internal error during the scan on segment #" + segment + ".", + throw SdkClientException.create("Internal error during the scan on segment #" + segment + ".", ee.getCause()); } } catch (Exception e) { - throw new SdkClientException("Error during the scan on segment #" + segment + ".", e); + throw SdkClientException.create("Error during the scan on segment #" + segment + ".", e); } } /** - * Get the ScanResult from cache if the segment scan has finished. + * Get the ScanResponse from cache if the segment scan has finished. */ else if (currentSegmentState == SegmentScanState.HasNextPage || currentSegmentState == SegmentScanState.SegmentScanCompleted) { - ScanResult scanResult = segmentScanResults.get(segment); + ScanResponse scanResult = segmentScanResults.get(segment); scanResults.add(scanResult); } else if (currentSegmentState == SegmentScanState.Waiting || currentSegmentState == SegmentScanState.Scanning){ - throw new SdkClientException("Should never see a 'Scanning' or 'Waiting' state when marshalling parallel scan results."); + throw SdkClientException.create("Should never see a 'Scanning' or 'Waiting' state when marshalling parallel scan results."); } } return scanResults; } - private ScanResult scanNextPageOfSegment(int currentSegment, boolean checkLastEvaluatedKey) { + private ScanResponse scanNextPageOfSegment(int currentSegment, boolean checkLastEvaluatedKey) { ScanRequest segmentScanRequest = parallelScanRequests.get(currentSegment); if (checkLastEvaluatedKey) { - ScanResult lastScanResult = segmentScanResults.get(currentSegment); - segmentScanRequest.setExclusiveStartKey(lastScanResult.getLastEvaluatedKey()); + ScanResponse lastScanResult = segmentScanResults.get(currentSegment); + segmentScanRequest = segmentScanRequest.toBuilder().exclusiveStartKey(lastScanResult.lastEvaluatedKey()).build(); } else { - segmentScanRequest.setExclusiveStartKey(null); + segmentScanRequest = segmentScanRequest.toBuilder().exclusiveStartKey(null).build(); } - ScanResult scanResult = dynamo.scan(DynamoDBMapper.applyUserAgent(segmentScanRequest)); + parallelScanRequests.set(currentSegment, segmentScanRequest); + ScanResponse scanResult = dynamo.scan(segmentScanRequest); /** * Cache the scan result in segmentScanResults. @@ -243,7 +244,7 @@ private ScanResult scanNextPageOfSegment(int currentSegment, boolean checkLastEv * Update the state and notify any waiting thread. */ synchronized(segmentScanStates) { - if (null == scanResult.getLastEvaluatedKey()) + if (!scanResult.hasLastEvaluatedKey() || scanResult.lastEvaluatedKey().isEmpty()) segmentScanStates.set(currentSegment, SegmentScanState.SegmentScanCompleted); else segmentScanStates.set(currentSegment, SegmentScanState.HasNextPage); diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/QueryResultPage.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/QueryResultPage.java index 096173f8b696..573097d325ea 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/QueryResultPage.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/QueryResultPage.java @@ -18,7 +18,7 @@ import java.util.Map; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; /** * Container for a page of query results diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ScanResultPage.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ScanResultPage.java index 17dc55fec80d..3e1413d956e6 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ScanResultPage.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/ScanResultPage.java @@ -18,7 +18,7 @@ import java.util.Map; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; /** * Container for a page of scan results. diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/StandardAnnotationMaps.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/StandardAnnotationMaps.java index 83c09a238e54..58f49d969a89 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/StandardAnnotationMaps.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/StandardAnnotationMaps.java @@ -15,12 +15,12 @@ package software.amazon.awssdk.mapper.dynamodb; import static software.amazon.awssdk.mapper.dynamodb.DynamoDBAutoGenerateStrategy.CREATE; -import static com.amazonaws.services.dynamodbv2.model.KeyType.HASH; -import static com.amazonaws.services.dynamodbv2.model.KeyType.RANGE; +import static software.amazon.awssdk.services.dynamodb.model.KeyType.HASH; +import static software.amazon.awssdk.services.dynamodb.model.KeyType.RANGE; import com.amazonaws.annotation.SdkInternalApi; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperFieldModel.DynamoDBAttributeType; -import com.amazonaws.services.dynamodbv2.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.KeyType; import com.amazonaws.util.StringUtils; import java.lang.annotation.Annotation; diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteRequest.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteRequest.java index 4ec8ec1b0d99..1a64d6025feb 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteRequest.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteRequest.java @@ -19,7 +19,7 @@ import java.util.List; import com.amazonaws.annotation.NotThreadSafe; -import com.amazonaws.services.dynamodbv2.model.ReturnValuesOnConditionCheckFailure; +import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; /** * Represents objects to write using {@link DynamoDBMapper#transactionWrite(TransactionWriteRequest)} operation. diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/AsyncServiceTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/AsyncServiceTest.java deleted file mode 100644 index 8875961c8341..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/AsyncServiceTest.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2013 Amazon Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://aws.amazon.com/apache2.0 - * - * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES - * OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and - * limitations under the License. - */ - -package software.amazon.awssdk.mapper.dynamodb; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsync; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.handlers.AsyncHandler; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.CreateTableResult; -import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteTableResult; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.model.TableDescription; -import com.amazonaws.services.dynamodbv2.util.TableUtils; -import java.util.HashSet; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class AsyncServiceTest extends LocalDynamoDBTestBase { - - /** The DynamoDB asynchronous client to be used in this test. */ - private static AmazonDynamoDBAsync dynamoAsync; - - /** Hashset to record all of the tables created in this test. */ - private static final HashSet createdTableNames = new HashSet(); - - /** Name prefix of all the tables to be created in this test. */ - private static final String ASYNC_TEST_TABLE_NAME_PREFIX = "async-java-sdk-" + System.currentTimeMillis() + "-"; - - private static final String HASH_KEY_NAME = "hash"; - - @BeforeClass - public static void setUp() throws Exception { - dynamoAsync = asyncClient(); - } - - @AfterClass - public static void tearDown() throws Exception { - System.out.println("**********************************************************"); - System.out.println("***************** AfterClass Procedure *****************"); - System.out.println("**********************************************************"); - dynamoAsync.shutdown(); - for (String tableName : createdTableNames ) { - try { - TableUtils.waitUntilActive(dynamoAsync, tableName); - dynamoAsync.deleteTable(new DeleteTableRequest(tableName)); - } catch ( Exception e ) { - System.out.println("Error when trying to delect table [" + tableName + "]"); - System.out.println("Error detail: " + e.toString()); - } - } - } - - /** - * Tests getting the CreateTableResult by polling Future object. - */ - @Test(timeout=60*1000) - public void testAsyncCreateTableByPollingFuture() throws Exception { - String TABLE_POLLINGFUTURE_SINGLETEST = ASYNC_TEST_TABLE_NAME_PREFIX + "testTimeForPollingFuture"; - - // Create a table - recordCreatedTestTable(TABLE_POLLINGFUTURE_SINGLETEST); - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_POLLINGFUTURE_SINGLETEST) - .withKeySchema(new KeySchemaElement().withAttributeName(HASH_KEY_NAME).withKeyType(KeyType.HASH)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(HASH_KEY_NAME).withAttributeType( - ScalarAttributeType.S)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(20L).withWriteCapacityUnits(10L)); - - // Call the async method to create the table - Future futureCreateTableResult = dynamoAsync.createTableAsync(createTableRequest); - long startPollingTime = System.currentTimeMillis(); - while (!futureCreateTableResult.isDone()) { - // POLLING.... - // We need to check whether the task is somehow canceled - if (futureCreateTableResult.isCancelled()) { - fail("[" + TABLE_POLLINGFUTURE_SINGLETEST + "] table is unexpectly canceled."); - } - } - long finishPollingTime = System.currentTimeMillis(); - long timeForPolling = finishPollingTime - startPollingTime; - System.out.println("We wasted " + timeForPolling + "ms in polling the Future!"); - - TableDescription createdTableDescription = futureCreateTableResult.get().getTableDescription(); - System.out.println("Created Table: " + createdTableDescription); - - // Check whether the table is correctly created - assertEquals(TABLE_POLLINGFUTURE_SINGLETEST, createdTableDescription.getTableName()); - assertNotNull(createdTableDescription.getTableStatus()); - assertEquals(HASH_KEY_NAME, createdTableDescription.getKeySchema().get(0).getAttributeName()); - assertEquals(KeyType.HASH.toString(), createdTableDescription.getKeySchema().get(0).getKeyType()); - assertEquals(HASH_KEY_NAME, createdTableDescription.getAttributeDefinitions().get(0).getAttributeName()); - assertEquals(ScalarAttributeType.S.toString(), createdTableDescription.getAttributeDefinitions().get(0).getAttributeType()); - - } - - /** - * Tests asynchronously processing the CreateTableResult by passing the - * callback handler. - */ - @Test(timeout=60*1000) - public void testAsyncCreateTableByCallback() throws Exception { - final String TABLE_CALlBACK_SINGLETEST = ASYNC_TEST_TABLE_NAME_PREFIX + "testTimeForCallback"; - - // Create a table - recordCreatedTestTable(TABLE_CALlBACK_SINGLETEST); - CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(TABLE_CALlBACK_SINGLETEST) - .withKeySchema(new KeySchemaElement().withAttributeName(HASH_KEY_NAME).withKeyType(KeyType.HASH)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(HASH_KEY_NAME).withAttributeType( - ScalarAttributeType.S)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(20L).withWriteCapacityUnits(20L)); - - final long startTime = System.currentTimeMillis(); - // Call the async method to create the table - dynamoAsync.createTableAsync(createTableRequest, - new AsyncHandler () { - - public void onError(Exception exception) { - System.out.println("MysteriousException during creating table: [" + TABLE_CALlBACK_SINGLETEST + "]"); - fail("Error detail: " + exception.toString()); - } - - public void onSuccess(CreateTableRequest request, CreateTableResult result) { - long endTime = System.currentTimeMillis(); - long timeForPolling = endTime - startTime; - System.out.println("The callback function is called after " + timeForPolling + "ms."); - - // Check whether the table is correctly created - TableDescription createdTableDescription = result.getTableDescription(); - System.out.println("Created Table: " + createdTableDescription); - assertEquals(TABLE_CALlBACK_SINGLETEST, createdTableDescription.getTableName()); - assertNotNull(createdTableDescription.getTableStatus()); - assertEquals(HASH_KEY_NAME, createdTableDescription.getKeySchema().get(0).getAttributeName()); - assertEquals(KeyType.HASH.toString(), createdTableDescription.getKeySchema().get(0).getKeyType()); - assertEquals(HASH_KEY_NAME, createdTableDescription.getAttributeDefinitions().get(0).getAttributeName()); - assertEquals(ScalarAttributeType.S.toString(), createdTableDescription.getAttributeDefinitions().get(0).getAttributeType()); - } - }); - - } - - /** - * Tests async handler for AmazonServiceException. - */ - @Test(timeout=60*1000) - public void testServiceExceptionCallback() throws Exception { - DeleteTableRequest deleteNonexistentTableRequest = new DeleteTableRequest("NONEXISTENT_TABLE"); - try { - Future futureDeleteTableResult = dynamoAsync.deleteTableAsync(deleteNonexistentTableRequest, - new AsyncHandler () { - - public void onError(Exception exception) { - assertTrue(exception instanceof AmazonServiceException); - - AmazonServiceException ase = (AmazonServiceException)exception; - assertTrue(ase.getErrorCode().equalsIgnoreCase("ResourceNotFoundException")); - } - - public void onSuccess(DeleteTableRequest request, DeleteTableResult result) { - fail("We are not supposed to be in onCompleted handler!"); - } - }); - // For backward compatibility, we need to make sure that the ASE is rethrown to the calling thread - // So... we wait for it!! - System.out.println("Waiting for the ServiceExeption rethrown into the main thread!"); - futureDeleteTableResult.get(); - fail("Expected AmazonServiceException, but wasn't thrown"); - } catch (AmazonServiceException ex) { - fail("The exception should be wrapped in ExcecutionException!"); - } catch (ExecutionException ex) { - System.out.println("Successully catch the ExcecutionException in the calling thread!"); - assertTrue(ex.getCause() instanceof AmazonServiceException); - } catch (Exception ex) { - fail ("The exception should be wrapped in ExcecutionException!"); - } - } - - /** - * Tests async handler for other runtime exceptions. - */ - @Test(timeout=60*1000) - public void testClientExceptionCallback() throws Exception { - // Passing a null request would trigger an AmazonClientExeption by - CreateTableRequest createTableRequest = null; - try { - Future futureDeleteTableResult = dynamoAsync.createTableAsync(createTableRequest, - new AsyncHandler () { - public void onError(Exception exception) { - assertTrue(exception instanceof NullPointerException); - } - - public void onSuccess(CreateTableRequest request, CreateTableResult result) { - fail("We are not supposed to be in onCompleted handler!"); - } - }); - // For backward compatibility, we need to make sure that the ACE is rethrown to the calling thread - // So... we wait for it!! - System.out.println("Waiting for the ClientExeption rethrown into the main thread!"); - futureDeleteTableResult.get(); - fail("Expected AmazonServiceException, but wasn't thrown"); - } catch (AmazonServiceException ex) { - fail("The exception should be wrapped in ExcecutionException!"); - } catch (ExecutionException ex) { - System.out.println("Successully catch the ExcecutionException in the calling thread!"); - assertTrue(ex.getCause() instanceof NullPointerException); - } catch (Exception ex) { - fail ("The exception should be wrapped in ExcecutionException!"); - } - } - - /** - * Record the created test table, so that tearDown() will clean up all - * these temporary tables. - */ - private static void recordCreatedTestTable(String tableName) { - createdTableNames.add(tableName); - } -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java index e445b209780e..6a2ec541696c 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java @@ -15,13 +15,14 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; @@ -30,17 +31,15 @@ import java.util.Map; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemResult; -import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes; -import com.amazonaws.services.dynamodbv2.model.PutRequest; -import com.amazonaws.services.dynamodbv2.model.WriteRequest; + +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.KeysAndAttributes; +import software.amazon.awssdk.services.dynamodb.model.PutRequest; +import software.amazon.awssdk.services.dynamodb.model.WriteRequest; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.BatchLoadRetryStrategy; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper.BatchGetItemException; @@ -51,16 +50,10 @@ public class BatchLoadRetryStrategyTest { private static final String TABLE_NAME3 = "tableName3"; private static final String HASH_ATTR = "hash"; - // private static BatchGetItemResult batchGetItemResult; private static List itemsToGet; - private AmazonDynamoDB ddbMock; + private DynamoDbClient ddbMock; private DynamoDBMapper mapper; - private BatchGetItemRequest mockItemRequest; - private BatchGetItemResult mockItemResult; - - @Rule - public final ExpectedException thrown = ExpectedException.none(); static { @@ -72,79 +65,82 @@ public class BatchLoadRetryStrategyTest { @Before public void setup() { - ddbMock = createMock(AmazonDynamoDB.class); - mockItemRequest = createMock(BatchGetItemRequest.class); - mockItemResult = createMock(BatchGetItemResult.class); + ddbMock = mock(DynamoDbClient.class); } @Test public void testBatchReadCallFailure_NoRetry() { - expect(ddbMock.batchGetItem((BatchGetItemRequest) anyObject())).andReturn(buildDefaultGetItemResult().withUnprocessedKeys(buildUnprocessedKeysMap(1))) - .times(1); + when(ddbMock.batchGetItem(any(BatchGetItemRequest.class))) + .thenReturn(buildGetItemResultWithUnprocessedKeys(1)); mapper = new DynamoDBMapper(ddbMock, getConfigWithCustomBatchLoadRetryStrategy(new DynamoDBMapperConfig.NoRetryBatchLoadRetryStrategy())); - replay(ddbMock); - thrown.expect(BatchGetItemException.class); - mapper.batchLoad(itemsToGet); - verify(ddbMock); + assertBatchLoadFails(); + verify(ddbMock, times(1)).batchGetItem(any(BatchGetItemRequest.class)); } @Test public void testBatchReadCallFailure_Retry() { - expect(ddbMock.batchGetItem((BatchGetItemRequest) anyObject())).andReturn(buildDefaultGetItemResult().withUnprocessedKeys(buildUnprocessedKeysMap(1))) - .times(4); + when(ddbMock.batchGetItem(any(BatchGetItemRequest.class))) + .thenReturn(buildGetItemResultWithUnprocessedKeys(1)); mapper = new DynamoDBMapper(ddbMock, getConfigWithCustomBatchLoadRetryStrategy(new BatchLoadRetryStrategyWithNoDelay(3))); - replay(ddbMock); - thrown.expect(BatchGetItemException.class); - mapper.batchLoad(itemsToGet); - verify(ddbMock); + assertBatchLoadFails(); + verify(ddbMock, times(4)).batchGetItem(any(BatchGetItemRequest.class)); } @Test public void testBatchReadCallSuccess_Retry() { - expect(ddbMock.batchGetItem((BatchGetItemRequest) anyObject())).andReturn( - buildDefaultGetItemResult().withUnprocessedKeys(new HashMap(1))).times(1); + when(ddbMock.batchGetItem(any(BatchGetItemRequest.class))) + .thenReturn(buildDefaultGetItemResult() + .toBuilder() + .unprocessedKeys(new HashMap(1)) + .build()); mapper = new DynamoDBMapper(ddbMock, getConfigWithCustomBatchLoadRetryStrategy(new DynamoDBMapperConfig.DefaultBatchLoadRetryStrategy())); - replay(ddbMock); mapper.batchLoad(itemsToGet); - verify(ddbMock); + verify(ddbMock, times(1)).batchGetItem(any(BatchGetItemRequest.class)); } @Test public void testBatchReadCallFailure_Retry_RetryOnCompleteFailure() { - expect(ddbMock.batchGetItem((BatchGetItemRequest) anyObject())).andReturn(buildDefaultGetItemResult().withUnprocessedKeys(buildUnprocessedKeysMap(3))) - .times(6); + when(ddbMock.batchGetItem(any(BatchGetItemRequest.class))) + .thenReturn(buildGetItemResultWithUnprocessedKeys(3)); mapper = new DynamoDBMapper(ddbMock, getConfigWithCustomBatchLoadRetryStrategy(new DynamoDBMapperConfig.DefaultBatchLoadRetryStrategy())); - replay(ddbMock); - thrown.expect(BatchGetItemException.class); - mapper.batchLoad(itemsToGet); - verify(ddbMock); + assertBatchLoadFails(); + verify(ddbMock, times(6)).batchGetItem(any(BatchGetItemRequest.class)); } @Test public void testBatchReadCallFailure_NoRetry_RetryOnCompleteFailure() { - expect(ddbMock.batchGetItem((BatchGetItemRequest) anyObject())).andReturn(buildDefaultGetItemResult().withUnprocessedKeys(buildUnprocessedKeysMap(3))) - .times(1); + when(ddbMock.batchGetItem(any(BatchGetItemRequest.class))) + .thenReturn(buildGetItemResultWithUnprocessedKeys(3)); mapper = new DynamoDBMapper(ddbMock, getConfigWithCustomBatchLoadRetryStrategy(new DynamoDBMapperConfig.NoRetryBatchLoadRetryStrategy())); - replay(ddbMock); - thrown.expect(BatchGetItemException.class); - mapper.batchLoad(itemsToGet); - verify(ddbMock); + assertBatchLoadFails(); + verify(ddbMock, times(1)).batchGetItem(any(BatchGetItemRequest.class)); + } + + private void assertBatchLoadFails() { + try { + mapper.batchLoad(itemsToGet); + fail("Expected BatchGetItemException"); + } catch (BatchGetItemException expected) { + // expected + } } @Test public void testNoDelayOnPartialFailure_DefaultRetry() { BatchLoadRetryStrategy defaultRetryStrategy = new DynamoDBMapperConfig.DefaultBatchLoadRetryStrategy(); - expect(mockItemResult.getUnprocessedKeys()).andReturn(buildUnprocessedKeysMap(2)); - expect(mockItemRequest.getRequestItems()).andReturn(buildUnprocessedKeysMap(3)); - replay(mockItemRequest); - replay(mockItemResult); - BatchLoadContext context = new BatchLoadContext(mockItemRequest); - context.setBatchGetItemResult(mockItemResult); + BatchGetItemRequest itemRequest = BatchGetItemRequest.builder() + .requestItems(buildUnprocessedKeysMap(3)) + .build(); + BatchGetItemResponse itemResult = BatchGetItemResponse.builder() + .unprocessedKeys(buildUnprocessedKeysMap(2)) + .build(); + BatchLoadContext context = new BatchLoadContext(itemRequest); + context.setBatchGetItemResult(itemResult); context.setRetriesAttempted(2); assertEquals(0, defaultRetryStrategy.getDelayBeforeNextRetry(context)); } @@ -152,12 +148,14 @@ public void testNoDelayOnPartialFailure_DefaultRetry() { @Test public void testDelayOnPartialFailure_DefaultRetry() { BatchLoadRetryStrategy defaultRetryStrategy = new DynamoDBMapperConfig.DefaultBatchLoadRetryStrategy(); - expect(mockItemResult.getUnprocessedKeys()).andReturn(buildUnprocessedKeysMap(3)); - expect(mockItemRequest.getRequestItems()).andReturn(buildUnprocessedKeysMap(3)); - replay(mockItemRequest); - replay(mockItemResult); - BatchLoadContext context = new BatchLoadContext(mockItemRequest); - context.setBatchGetItemResult(mockItemResult); + BatchGetItemRequest itemRequest = BatchGetItemRequest.builder() + .requestItems(buildUnprocessedKeysMap(3)) + .build(); + BatchGetItemResponse itemResult = BatchGetItemResponse.builder() + .unprocessedKeys(buildUnprocessedKeysMap(3)) + .build(); + BatchLoadContext context = new BatchLoadContext(itemRequest); + context.setBatchGetItemResult(itemResult); context.setRetriesAttempted(2); assertTrue(defaultRetryStrategy.getDelayBeforeNextRetry(context) > 0); } @@ -169,23 +167,30 @@ private DynamoDBMapperConfig getConfigWithCustomBatchLoadRetryStrategy(final Bat private Map buildUnprocessedKeysMap(final int size) { final Map unproccessedKeys = new HashMap(size); for (int i = 0; i < size; i++) { - unproccessedKeys.put("test" + i, new KeysAndAttributes()); + unproccessedKeys.put("test" + i, KeysAndAttributes.builder().build()); } return unproccessedKeys; } - private BatchGetItemResult buildDefaultGetItemResult() { + private BatchGetItemResponse buildDefaultGetItemResult() { final Map>> map = new HashMap>>(); - return new BatchGetItemResult().withResponses(map); + return BatchGetItemResponse.builder().responses(map).build(); + + } + private BatchGetItemResponse buildGetItemResultWithUnprocessedKeys(final int size) { + return buildDefaultGetItemResult() + .toBuilder() + .unprocessedKeys(buildUnprocessedKeysMap(size)) + .build(); } static class BatchLoadRetryStrategyWithNoDelay implements BatchLoadRetryStrategy { private final int maxRetry; - + /** * @param maxRetry */ @@ -209,7 +214,7 @@ public long getDelayBeforeNextRetry(final BatchLoadContext batchLoadContext) { return 0; } - + } @@ -233,7 +238,11 @@ public void setHash(final String hash) { } public WriteRequest toPutSaveRequest() { - return new WriteRequest().withPutRequest(new PutRequest(Collections.singletonMap(HASH_ATTR, new AttributeValue(hash)))); + return WriteRequest.builder() + .putRequest(PutRequest.builder() + .item(Collections.singletonMap(HASH_ATTR, AttributeValue.builder().s(hash).build())) + .build()) + .build(); } } @@ -257,7 +266,11 @@ public void setHash(final String hash) { } public WriteRequest toPutSaveRequest() { - return new WriteRequest().withPutRequest(new PutRequest(Collections.singletonMap(HASH_ATTR, new AttributeValue(hash)))); + return WriteRequest.builder() + .putRequest(PutRequest.builder() + .item(Collections.singletonMap(HASH_ATTR, AttributeValue.builder().s(hash).build())) + .build()) + .build(); } } @@ -281,7 +294,11 @@ public void setHash(final String hash) { } public WriteRequest toPutSaveRequest() { - return new WriteRequest().withPutRequest(new PutRequest(Collections.singletonMap(HASH_ATTR, new AttributeValue(hash)))); + return WriteRequest.builder() + .putRequest(PutRequest.builder() + .item(Collections.singletonMap(HASH_ATTR, AttributeValue.builder().s(hash).build())) + .build()) + .build(); } } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadTest.java index c8d3643502c5..605ada6e3fb7 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadTest.java @@ -18,12 +18,12 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.LocalDynamoDBTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.ConsistentReads; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.SaveBehavior; import software.amazon.awssdk.mapper.dynamodb.mapper.NumberSetAttributeClass; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import java.math.BigDecimal; import java.math.BigInteger; @@ -48,7 +48,7 @@ public class BatchLoadTest extends LocalDynamoDBTestBase { private static int byteStart = 1; private static int startKeyDebug = 1; private static long startKey = System.currentTimeMillis(); - private static AmazonDynamoDB dynamo; + private static DynamoDbClient dynamo; private static DynamoDBMapper mapper; private static String tableName; private static String tableName2; @@ -59,11 +59,11 @@ public static void setUp() throws Exception { mapper = new DynamoDBMapper(dynamo, new DynamoDBMapperConfig(SaveBehavior.UPDATE, ConsistentReads.CONSISTENT, null)); CreateTableRequest createTableRequest = mapper.generateCreateTableRequest(NumberSetAttributeClass.class) - .withProvisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT); + .toBuilder().provisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT).build(); CreateTableRequest createTableRequest2 = mapper.generateCreateTableRequest(RangeKeyClass.class) - .withProvisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT); - tableName = createTableRequest.getTableName(); - tableName2 = createTableRequest2.getTableName(); + .toBuilder().provisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT).build(); + tableName = createTableRequest.tableName(); + tableName2 = createTableRequest2.tableName(); dynamo.createTable(createTableRequest); dynamo.createTable(createTableRequest2); } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchWriteRetryStrategyTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchWriteRetryStrategyTest.java index 59e0fa088a55..931c09e33634 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchWriteRetryStrategyTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchWriteRetryStrategyTest.java @@ -14,32 +14,32 @@ */ package software.amazon.awssdk.mapper.dynamodb; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; -import junit.framework.Assert; - -import org.easymock.IExpectationSetters; import org.junit.Before; import org.junit.Test; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.isA; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper.FailedBatch; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.BatchWriteRetryStrategy; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemResult; -import com.amazonaws.services.dynamodbv2.model.PutRequest; -import com.amazonaws.services.dynamodbv2.model.WriteRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutRequest; +import software.amazon.awssdk.services.dynamodb.model.WriteRequest; public class BatchWriteRetryStrategyTest { @@ -49,15 +49,17 @@ public class BatchWriteRetryStrategyTest { private static Map> unprocessedItems; - private AmazonDynamoDB ddbMock; + private DynamoDbClient ddbMock; private DynamoDBMapper mapper; static { - WriteRequest writeReq = new WriteRequest() - .withPutRequest(new PutRequest() - .withItem(Collections.singletonMap( + WriteRequest writeReq = WriteRequest.builder() + .putRequest(PutRequest.builder() + .item(Collections.singletonMap( HASH_ATTR, - new AttributeValue("foo")))); + AttributeValue.builder().s("foo").build())) + .build()) + .build(); unprocessedItems = Collections.singletonMap(TABLE_NAME, Arrays.asList(writeReq)); @@ -65,7 +67,7 @@ public class BatchWriteRetryStrategyTest { @Before public void setup() { - ddbMock = createMock(AmazonDynamoDB.class); + ddbMock = mock(DynamoDbClient.class); mapper = new DynamoDBMapper( ddbMock, getConfigWithCustomBatchWriteRetryStrategy( @@ -75,34 +77,34 @@ public void setup() { @Test public void testBatchWriteItemCallSuccess_NoRetry() { - // BatchWriteItem is expected to be called only once - expectBatchWriteItemSuccess().once(); + stubBatchWriteItemSuccess(); - replay(ddbMock); List failedBatches = mapper.batchSave(new Item("foo")); - verify(ddbMock); - Assert.assertEquals(0, failedBatches.size()); + // BatchWriteItem is expected to be called only once + verify(ddbMock, times(1)).batchWriteItem(isA(BatchWriteItemRequest.class)); + + assertEquals(0, failedBatches.size()); } @Test public void testUnprocessedItemReturned_BatchWriteItemCallNotExceedMaxRetry() { - // BatchWriteItem is expected to be called exactly (MAX_RETRY + 1) times - expectBatchWriteItemReturnUnprocessedItems().times(MAX_RETRY + 1); + stubBatchWriteItemReturnUnprocessedItems(); - replay(ddbMock); List failedBatches = mapper.batchSave(new Item("foo")); - verify(ddbMock); - Assert.assertEquals(1, failedBatches.size()); + // BatchWriteItem is expected to be called exactly (MAX_RETRY + 1) times + verify(ddbMock, times(MAX_RETRY + 1)).batchWriteItem(isA(BatchWriteItemRequest.class)); + + assertEquals(1, failedBatches.size()); FailedBatch failedBatch = failedBatches.get(0); - Assert.assertEquals( + assertEquals( "Failed batch should contain the same UnprocessedItems returned in the BatchWriteItem response.", unprocessedItems, failedBatch.getUnprocessedItems()); - Assert.assertNull( + assertNull( "No exception should be set if the batch failed after max retry", failedBatch.getException()); } @@ -111,43 +113,44 @@ public void testUnprocessedItemReturned_BatchWriteItemCallNotExceedMaxRetry() { public void testExceptionThrown_NoRetry() { RuntimeException exception = new RuntimeException("BOOM"); - expectedBatchWriteItemThrowException(exception); + stubBatchWriteItemThrowException(exception); - replay(ddbMock); // put a random item Item item = new Item(UUID.randomUUID().toString()); List failedBatches = mapper.batchSave(item); - verify(ddbMock); - Assert.assertEquals(1, failedBatches.size()); + verify(ddbMock, times(1)).batchWriteItem(isA(BatchWriteItemRequest.class)); + + assertEquals(1, failedBatches.size()); FailedBatch failedBatch = failedBatches.get(0); - Assert.assertEquals( + assertEquals( "Failed batch should contain all the input items for batchWrite", Collections.singletonMap(TABLE_NAME, Arrays.asList(item.toPutSaveRequest())), failedBatch.getUnprocessedItems()); - Assert.assertSame( + assertSame( "The exception should be the same as one thrown by BatchWriteItem", exception, failedBatch.getException()); } - private IExpectationSetters expectBatchWriteItemSuccess() { - return expect(ddbMock.batchWriteItem(isA(BatchWriteItemRequest.class))) - .andReturn(new BatchWriteItemResult() - .withUnprocessedItems(Collections.>emptyMap())); + private void stubBatchWriteItemSuccess() { + when(ddbMock.batchWriteItem(isA(BatchWriteItemRequest.class))) + .thenReturn(BatchWriteItemResponse.builder() + .unprocessedItems(Collections.>emptyMap()) + .build()); } - private IExpectationSetters expectBatchWriteItemReturnUnprocessedItems() { - return expect(ddbMock.batchWriteItem(isA(BatchWriteItemRequest.class))) - .andReturn( - new BatchWriteItemResult() - .withUnprocessedItems(unprocessedItems)); + private void stubBatchWriteItemReturnUnprocessedItems() { + when(ddbMock.batchWriteItem(isA(BatchWriteItemRequest.class))) + .thenReturn(BatchWriteItemResponse.builder() + .unprocessedItems(unprocessedItems) + .build()); } - private void expectedBatchWriteItemThrowException(Exception e) { - expect(ddbMock.batchWriteItem(isA(BatchWriteItemRequest.class))) - .andThrow(e); + private void stubBatchWriteItemThrowException(RuntimeException e) { + when(ddbMock.batchWriteItem(isA(BatchWriteItemRequest.class))) + .thenThrow(e); } private DynamoDBMapperConfig getConfigWithCustomBatchWriteRetryStrategy( @@ -200,9 +203,11 @@ public void setHash(String hash) { } public WriteRequest toPutSaveRequest() { - return new WriteRequest() - .withPutRequest(new PutRequest( - Collections.singletonMap(HASH_ATTR, new AttributeValue(hash)))); + return WriteRequest.builder() + .putRequest(PutRequest.builder() + .item(Collections.singletonMap(HASH_ATTR, AttributeValue.builder().s(hash).build())) + .build()) + .build(); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ConvenientMapSetterTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ConvenientMapSetterTest.java deleted file mode 100644 index d861820f4e6d..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ConvenientMapSetterTest.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package software.amazon.awssdk.mapper.dynamodb; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import java.util.AbstractMap; -import java.util.Map; - -import org.junit.Test; - -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; - -/** - * Tests on using convenient map setters. - */ -public class ConvenientMapSetterTest { - - /** Test on using map entry adder method. */ - @Test - public void testMapEntryAdderMethod() { - PutItemRequest putItemRequest = new PutItemRequest() - .addItemEntry("hash-key", new AttributeValue().withS("1")) - .addItemEntry("range-key", new AttributeValue().withS("2")) - .addItemEntry("attribute", new AttributeValue().withS("3")); - - Map item = putItemRequest.getItem(); - assertEquals(3, item.size()); - assertEquals("1", item.get("hash-key").getS()); - assertEquals("2", item.get("range-key").getS()); - assertEquals("3", item.get("attribute").getS()); - - putItemRequest.clearItemEntries(); - assertNull(putItemRequest.getItem()); - } - - /** Test on using predefined map entry setter to provide map parameter. */ - @Test - public void testPredefinedMapEntryMethod() { - ScanRequest scanRequest = new ScanRequest().withExclusiveStartKey( - new AbstractMap.SimpleEntry("hash-key", new AttributeValue().withS("1")), - new AbstractMap.SimpleEntry("range-key", new AttributeValue().withS("2"))); - - Map item = scanRequest.getExclusiveStartKey(); - assertEquals(2, item.size()); - assertEquals("1", item.get("hash-key").getS()); - assertEquals("2", item.get("range-key").getS()); - } - - /** Test on IllegalArgumentException when providing duplicated keys. */ - @Test(expected = IllegalArgumentException.class) - public void testDuplicatedKeysException() { - new PutItemRequest() - .addItemEntry("hash-key", new AttributeValue().withS("1")) - .addItemEntry("hash-key", new AttributeValue().withS("2")); - } - - /** Test on handling null entry objects. */ - @Test - public void testNullEntryException() { - // hashKey is set as not nullable, and rangeKey is nullable - // so this call should be fine. - ScanRequest scanRequest = new ScanRequest().withExclusiveStartKey( - new AbstractMap.SimpleEntry("hash-key", new AttributeValue().withS("1")), - null); - - // but this call should throw IllegalArgumentException. - try { - scanRequest.withExclusiveStartKey( - null, - new AbstractMap.SimpleEntry("hash-key", new AttributeValue().withS("1"))); - fail("Should throw IllegalArgumentException."); - } catch (IllegalArgumentException iae) { - } - } -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperExpressionsIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperExpressionsIntegrationTest.java index f9b9ece54447..987d850bd96a 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperExpressionsIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapperExpressionsIntegrationTest.java @@ -18,29 +18,30 @@ import java.io.FileNotFoundException; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.DescribeTableResult; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.ResourceInUseException; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; import software.amazon.awssdk.mapper.dynamodb.test.AWSTestBase; -import com.amazonaws.util.ImmutableMapParameter; -import com.amazonaws.util.ImmutableMapParameter.Builder; +import software.amazon.awssdk.mapper.dynamodb.test.util.DynamoDBTestBase; public class DynamoDBMapperExpressionsIntegrationTest extends AWSTestBase { @@ -73,25 +74,25 @@ public class DynamoDBMapperExpressionsIntegrationTest extends AWSTestBase { protected static DynamoDBMapper mapper; /** Reference to the client being used by the mapper. */ - protected static AmazonDynamoDBClient client; + protected static DynamoDbClient client; @BeforeClass public static void setUp() throws FileNotFoundException, IOException, InterruptedException { - setUpCredentials(); - client = new AmazonDynamoDBClient(credentials); + client = DynamoDBTestBase.getClient(); mapper = new DynamoDBMapper(client); try { - client.createTable(new CreateTableRequest() - .withTableName(TABLENAME) - .withKeySchema(new KeySchemaElement(HASH_KEY, KeyType.HASH), - new KeySchemaElement(RANGE_KEY, KeyType.RANGE)) - .withAttributeDefinitions( - new AttributeDefinition(HASH_KEY, ScalarAttributeType.N), - new AttributeDefinition(RANGE_KEY, - ScalarAttributeType.S)) - .withProvisionedThroughput( - new ProvisionedThroughput(READ_CAPACITY, WRITE_CAPACITY))); + client.createTable(CreateTableRequest.builder() + .tableName(TABLENAME) + .keySchema(KeySchemaElement.builder().attributeName(HASH_KEY).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(RANGE_KEY).keyType(KeyType.RANGE).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName(HASH_KEY).attributeType(ScalarAttributeType.N).build(), + AttributeDefinition.builder().attributeName(RANGE_KEY) + .attributeType(ScalarAttributeType.S).build()) + .provisionedThroughput( + ProvisionedThroughput.builder().readCapacityUnits(READ_CAPACITY).writeCapacityUnits(WRITE_CAPACITY).build()) + .build()); } catch(ResourceInUseException ex) { ex.printStackTrace(); } @@ -100,35 +101,33 @@ public static void setUp() throws FileNotFoundException, IOException, } public static void fillInData() { - final Builder record1 = ImmutableMapParameter - .builder(); - record1.put(HASH_KEY, new AttributeValue().withN(FIRST_CUSTOMER_ID)) - .put(RANGE_KEY, new AttributeValue().withS(ADDRESS_TYPE_WORK)) - .put("AddressLine1", - new AttributeValue().withS("1918 8th Aven")) - .put("city", new AttributeValue().withS("seattle")) - .put("state", new AttributeValue().withS("WA")) - .put("zipcode", new AttributeValue().withN("98104")); - final Builder record2 = ImmutableMapParameter - .builder(); - record2.put(HASH_KEY, new AttributeValue().withN(FIRST_CUSTOMER_ID)) - .put(RANGE_KEY, new AttributeValue().withS(ADDRESS_TYPE_HOME)) - .put("AddressLine1", - new AttributeValue().withS("15606 NE 40th ST")) - .put("city", new AttributeValue().withS("redmond")) - .put("state", new AttributeValue().withS("WA")) - .put("zipcode", new AttributeValue().withN("98052")); - - client.putItem(new PutItemRequest(TABLENAME, record1.build())); - client.putItem(new PutItemRequest(TABLENAME, record2.build())); + final Map record1 = new HashMap(); + record1.put(HASH_KEY, AttributeValue.builder().n(FIRST_CUSTOMER_ID).build()); + record1.put(RANGE_KEY, AttributeValue.builder().s(ADDRESS_TYPE_WORK).build()); + record1.put("AddressLine1", + AttributeValue.builder().s("1918 8th Aven").build()); + record1.put("city", AttributeValue.builder().s("seattle").build()); + record1.put("state", AttributeValue.builder().s("WA").build()); + record1.put("zipcode", AttributeValue.builder().n("98104").build()); + final Map record2 = new HashMap(); + record2.put(HASH_KEY, AttributeValue.builder().n(FIRST_CUSTOMER_ID).build()); + record2.put(RANGE_KEY, AttributeValue.builder().s(ADDRESS_TYPE_HOME).build()); + record2.put("AddressLine1", + AttributeValue.builder().s("15606 NE 40th ST").build()); + record2.put("city", AttributeValue.builder().s("redmond").build()); + record2.put("state", AttributeValue.builder().s("WA").build()); + record2.put("zipcode", AttributeValue.builder().n("98052").build()); + + client.putItem(PutItemRequest.builder().tableName(TABLENAME).item(record1).build()); + client.putItem(PutItemRequest.builder().tableName(TABLENAME).item(record2).build()); } public static void waitForTableCreation() throws InterruptedException { while (true) { - DescribeTableResult describeResult = client - .describeTable(TABLENAME); - if (TABLE_STATUS_ACTIVE.equals(describeResult.getTable() - .getTableStatus())) { + DescribeTableResponse describeResult = client + .describeTable(b -> b.tableName(TABLENAME)); + if (TABLE_STATUS_ACTIVE.equals(describeResult.table() + .tableStatusAsString())) { break; } Thread.sleep(SLEEP_TIME_IN_MILLIS); @@ -147,21 +146,20 @@ public void testQueryFilterExpression() { DynamoDBQueryExpression queryExpression = new DynamoDBQueryExpression() .withHashKeyValues(customer) - .withRangeKeyCondition(RANGE_KEY, new Condition() - .withComparisonOperator(ComparisonOperator.EQ) - .withAttributeValueList(new AttributeValue(ADDRESS_TYPE_HOME))) + .withRangeKeyCondition(RANGE_KEY, Condition.builder() + .comparisonOperator(ComparisonOperator.EQ) + .attributeValueList(AttributeValue.builder().s(ADDRESS_TYPE_HOME).build()).build()) ; PaginatedQueryList results = mapper.query(Customer.class, queryExpression); assertTrue(results.size() == 1); - final Builder builder = ImmutableMapParameter - .builder(); - builder.put(":zipcode", new AttributeValue().withN("98109")); + final Map builder = new HashMap(); + builder.put(":zipcode", AttributeValue.builder().n("98109").build()); queryExpression = queryExpression .withFilterExpression("zipcode = :zipcode") - .withExpressionAttributeValues(builder.build()); + .withExpressionAttributeValues(builder); results = mapper.query(Customer.class, queryExpression); assertTrue(results.size() == 0); } @@ -178,19 +176,18 @@ public void testKeyConditionExpression() { new DynamoDBQueryExpression() .withKeyConditionExpression( "customerId = :customerId AND addressType = :addressType"); - final Builder builder = - ImmutableMapParameter.builder(); - builder.put(":customerId", new AttributeValue().withN(FIRST_CUSTOMER_ID)) - .put(":addressType", new AttributeValue(ADDRESS_TYPE_HOME)) - ; - qxp.withExpressionAttributeValues(builder.build()); + final Map builder = + new HashMap(); + builder.put(":customerId", AttributeValue.builder().n(FIRST_CUSTOMER_ID).build()); + builder.put(":addressType", AttributeValue.builder().s(ADDRESS_TYPE_HOME).build()); + qxp.withExpressionAttributeValues(builder); PaginatedQueryList results = mapper.query(Customer.class, qxp); assertTrue(results.size() == 1); - builder.put(":zipcode", new AttributeValue().withN("98109")); + builder.put(":zipcode", AttributeValue.builder().n("98109").build()); qxp.withFilterExpression("zipcode = :zipcode") - .withExpressionAttributeValues(builder.build()) + .withExpressionAttributeValues(builder) ; results = mapper.query(Customer.class, qxp); @@ -212,19 +209,17 @@ public void testScanFilterExpression() { scanExpression); assertTrue(results.size() == 2); - final Builder attributeValueMapBuilder = ImmutableMapParameter - .builder(); + final Map attributeValueMapBuilder = new HashMap(); attributeValueMapBuilder - .put(":state", new AttributeValue().withS("WA")); + .put(":state", AttributeValue.builder().s("WA").build()); - final Builder attributeNameMapBuilder = ImmutableMapParameter - .builder(); + final Map attributeNameMapBuilder = new HashMap(); attributeNameMapBuilder.put("#statename", "state"); scanExpression = scanExpression .withFilterExpression("#statename = :state") - .withExpressionAttributeValues(attributeValueMapBuilder.build()) - .withExpressionAttributeNames(attributeNameMapBuilder.build()); + .withExpressionAttributeValues(attributeValueMapBuilder) + .withExpressionAttributeNames(attributeNameMapBuilder); results = mapper.scan(Customer.class, scanExpression); assertTrue(results.size() == 2); } @@ -240,21 +235,18 @@ public void testDeleteConditionalExpression() { customer.setCustomerId(Long.valueOf(FIRST_CUSTOMER_ID)); customer.setAddressType(ADDRESS_TYPE_WORK); - Builder expectedMapBuilder = ImmutableMapParameter - .builder(); - expectedMapBuilder.put("zipcode", new ExpectedAttributeValue() - .withAttributeValueList(new AttributeValue().withN("98052")) - .withComparisonOperator(ComparisonOperator.EQ)); + Map expectedMapBuilder = new HashMap(); + expectedMapBuilder.put("zipcode", ExpectedAttributeValue.builder() + .attributeValueList(AttributeValue.builder().n("98052").build()) + .comparisonOperator(ComparisonOperator.EQ).build()); DynamoDBDeleteExpression deleteExpression = new DynamoDBDeleteExpression(); deleteExpression.setConditionExpression("zipcode = :zipcode"); - final Builder attributeValueMapBuilder = ImmutableMapParameter - .builder(); + final Map attributeValueMapBuilder = new HashMap(); attributeValueMapBuilder.put(":zipcode", - new AttributeValue().withN("98052")); - deleteExpression.setExpressionAttributeValues(attributeValueMapBuilder - .build()); + AttributeValue.builder().n("98052").build()); + deleteExpression.setExpressionAttributeValues(attributeValueMapBuilder); try { mapper.delete(customer, deleteExpression); } catch (Exception e) { @@ -266,12 +258,12 @@ public void testDeleteConditionalExpression() { public static void tearDown() { try { if (client != null) { - client.deleteTable(TABLENAME); + client.deleteTable(b -> b.tableName(TABLENAME)); } } catch (Exception e) { } finally { if (client != null) - client.shutdown(); + client.close(); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDB.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDB.java index e87d291b6c63..2e520a1613f8 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDB.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDB.java @@ -15,22 +15,18 @@ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsync; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsyncClientBuilder; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; - -import com.amazonaws.ClientConfiguration; -import com.amazonaws.auth.AWSCredentialsProvider; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.AnonymousAWSCredentials; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder; -import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; import java.io.IOException; import java.net.ServerSocket; +import java.net.URI; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClientBuilder; /** * Wrapper for a local DynamoDb server used in testing. Each instance of this class will find a new port to run on, @@ -70,36 +66,35 @@ void start() { * Create a standard AWS v2 SDK client pointing to the local DynamoDb instance * @return A DynamoDbClient pointing to the local DynamoDb instance */ - AmazonDynamoDB createClient() { - return createClient(new ClientConfiguration()); + DynamoDbClient createClient() { + return clientBuilder().build(); } /** - * Create a standard AWS v2 SDK client pointing to the local DynamoDb instance - * @return A DynamoDbClient pointing to the local DynamoDb instance + * Create a client with a caller-supplied override configuration (e.g. a custom retry policy). */ - AmazonDynamoDB createClient(ClientConfiguration config) { - return AmazonDynamoDBClient.builder() - .withEndpointConfiguration(endpointConfig()) - .withCredentials(credentials()) - .withClientConfiguration(config) - .build(); + DynamoDbClient createClient(ClientOverrideConfiguration overrideConfiguration) { + return clientBuilder().overrideConfiguration(overrideConfiguration).build(); } - AmazonDynamoDBAsync createAsyncClient() { - return AmazonDynamoDBAsyncClientBuilder.standard() - .withEndpointConfiguration(endpointConfig()) - .withCredentials(credentials()) - .build(); - } - - private EndpointConfiguration endpointConfig() { + private DynamoDbClientBuilder clientBuilder() { String endpoint = String.format("http://localhost:%d", port); - return new EndpointConfiguration(endpoint, "us-east-1"); + return DynamoDbClient.builder() + .endpointOverride(URI.create(endpoint)) + // The region is meaningless for local DynamoDb but required for client builder validation + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))); } - private AWSCredentialsProvider credentials() { - return new AWSStaticCredentialsProvider(new BasicAWSCredentials("akid", "skid")); + DynamoDbAsyncClient createAsyncClient() { + String endpoint = String.format("http://localhost:%d", port); + return DynamoDbAsyncClient.builder() + .endpointOverride(URI.create(endpoint)) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .build(); } /** diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDBTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDBTestBase.java index a449f94651d4..5623dea24756 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDBTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/LocalDynamoDBTestBase.java @@ -1,11 +1,10 @@ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBAsync; - -import com.amazonaws.ClientConfiguration; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteBufferClass; import java.nio.ByteBuffer; import java.util.Collection; @@ -18,7 +17,8 @@ import org.junit.BeforeClass; public class LocalDynamoDBTestBase { - protected static final ProvisionedThroughput DEFAULT_PROVISIONED_THROUGHPUT = new ProvisionedThroughput(50L, 50L); + protected static final ProvisionedThroughput DEFAULT_PROVISIONED_THROUGHPUT = + ProvisionedThroughput.builder().readCapacityUnits(50L).writeCapacityUnits(50L).build(); private static final LocalDynamoDB LOCAL = new LocalDynamoDB(); @BeforeClass @@ -31,15 +31,15 @@ public static void stopLocalDynamoDb() { LOCAL.stop(); } - protected static AmazonDynamoDB client() { + protected static DynamoDbClient client() { return LOCAL.createClient(); } - protected static AmazonDynamoDB client(ClientConfiguration configuration) { + protected static DynamoDbClient client(ClientOverrideConfiguration configuration) { return LOCAL.createClient(configuration); } - protected static AmazonDynamoDBAsync asyncClient() { + protected static DynamoDbAsyncClient asyncClient() { return LOCAL.createAsyncClient(); } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java index 89522fa294ed..9b5cd6b23881 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java @@ -14,11 +14,11 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughputExceededException; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; -import com.amazonaws.services.dynamodbv2.model.ScanResult; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughputExceededException; +import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.awssdk.services.dynamodb.model.ScanResponse; import org.junit.Before; import org.junit.Test; @@ -53,7 +53,7 @@ public class PaginatedScanTaskTest { private ExecutorService executorService; @Mock - private AmazonDynamoDB dynamoDB; + private DynamoDbClient dynamoDB; @Before public void setup() { @@ -74,7 +74,7 @@ public void segmentFailsToScan_ExecutorServiceIsShutdown() throws InterruptedExc stubSuccessfulScan(0); stubSuccessfulScan(1); when(dynamoDB.scan(isSegmentNumber(2))) - .thenThrow(new ProvisionedThroughputExceededException("Slow Down!")); + .thenThrow(ProvisionedThroughputExceededException.builder().message("Slow Down!").build()); stubSuccessfulScan(3); stubSuccessfulScan(4); @@ -95,14 +95,14 @@ public void segmentFailsToScan_ExecutorServiceIsShutdown() throws InterruptedExc */ private void stubSuccessfulScan(int segmentNumber) { when(dynamoDB.scan(isSegmentNumber(segmentNumber))) - .thenReturn(new ScanResult().withItems(generateItems())); + .thenReturn(ScanResponse.builder().items(generateItems()).build()); } private Map generateItems() { final int numItems = 10; Map items = new HashMap(numItems); for (int i = 0; i < numItems; i++) { - items.put(UUID.randomUUID().toString(), new AttributeValue().withS("foo")); + items.put(UUID.randomUUID().toString(), AttributeValue.builder().s("foo").build()); } return items; } @@ -116,10 +116,11 @@ private List createScanRequests() { } private ScanRequest createScanRequest(int segmentNumber) { - return new ScanRequest() - .withTableName(TABLE_NAME) - .withSegment(segmentNumber) - .withTotalSegments(TOTAL_SEGMENTS); + return ScanRequest.builder() + .tableName(TABLE_NAME) + .segment(segmentNumber) + .totalSegments(TOTAL_SEGMENTS) + .build(); } /** @@ -149,7 +150,7 @@ public boolean matches(Object argument) { if (!(argument instanceof ScanRequest)) { return false; } - return matchingSegmentNumber == ((ScanRequest) argument).getSegment(); + return matchingSegmentNumber == ((ScanRequest) argument).segment(); } } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/RequestProgressTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/RequestProgressTest.java deleted file mode 100644 index 1068874d4817..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/RequestProgressTest.java +++ /dev/null @@ -1,211 +0,0 @@ -package software.amazon.awssdk.mapper.dynamodb; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.concurrent.ExecutionException; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.amazonaws.AmazonClientException; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.AmazonWebServiceRequest; -import com.amazonaws.ClientConfiguration; -import software.amazon.awssdk.mapper.dynamodb.test.resources.tables.BasicTempTable; -import software.amazon.awssdk.mapper.dynamodb.test.util.DynamoDBTestBase; -import com.amazonaws.event.ProgressEventType; -import com.amazonaws.event.ProgressListener.ExceptionReporter; -import com.amazonaws.event.ProgressTracker; -import com.amazonaws.event.SDKProgressPublisher; -import com.amazonaws.event.request.Progress; -import com.amazonaws.retry.PredefinedRetryPolicies; -import com.amazonaws.retry.RetryPolicy; -import com.amazonaws.retry.RetryPolicy.RetryCondition; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.PutRequest; -import com.amazonaws.services.dynamodbv2.model.WriteRequest; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.RequiredResource; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.ResourceCreationPolicy; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.ResourceRetentionPolicy; -import software.amazon.awssdk.mapper.dynamodb.test.resources.ResourceCentricBlockJUnit4ClassRunner; -import software.amazon.awssdk.mapper.dynamodb.test.util.ProgressListenerWithEventCodeVerification; -import com.amazonaws.util.ImmutableMapParameter; - -public class RequestProgressTest extends LocalDynamoDBTestBase { - private static final long KB = 1024; - private static AmazonDynamoDB dynamo; - - @BeforeClass - public static void setup() { - dynamo = client(); - dynamo.createTable(BasicTempTable.getCreateTableRequest()); - } - - /** - * Tests that the user-specified progress listener is properly notified with - * all the request/response progress event code. - */ - @Test - public void testProgressEventNotification_SuccessfulRequest() { - BatchWriteItemRequest request = generateLargeBatchWriteItemRequest(); - - ExceptionReporter listener = ExceptionReporter.wrap(new ProgressListenerWithEventCodeVerification( - ProgressEventType.CLIENT_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_COMPLETED_EVENT, - ProgressEventType.HTTP_RESPONSE_STARTED_EVENT, - ProgressEventType.HTTP_RESPONSE_COMPLETED_EVENT, - ProgressEventType.CLIENT_REQUEST_SUCCESS_EVENT)); - request.setGeneralProgressListener(listener); - - dynamo.batchWriteItem(request); - waitTillListenerCallbacksComplete(); - listener.throwExceptionIfAny(); - } - - @Test - public void testProgressEventNotification_FailedRequest_NoRetry() { - // An invalid PutItemRequest that does not have the key attribute value - PutItemRequest request = new PutItemRequest( - BasicTempTable.TEMP_TABLE_NAME, - ImmutableMapParameter.of("foo", new AttributeValue("bar"))); - - ExceptionReporter listener = ExceptionReporter.wrap(new ProgressListenerWithEventCodeVerification( - ProgressEventType.CLIENT_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_COMPLETED_EVENT, - ProgressEventType.CLIENT_REQUEST_FAILED_EVENT)); - request.setGeneralProgressListener(listener); - - ClientConfiguration config = new ClientConfiguration().withRetryPolicy(new RetryPolicy(new RetryCondition() { - - @Override - public boolean shouldRetry(AmazonWebServiceRequest originalRequest, - AmazonClientException exception, int retriesAttempted) { - return false; - } - - }, PredefinedRetryPolicies.DEFAULT_BACKOFF_STRATEGY, 0, false)); - - AmazonDynamoDB ddb_NoRetry = client(config); - try { - ddb_NoRetry.putItem(request); - Assert.fail("Exception is expected since the PutItemRequest is invalid."); - } catch (AmazonServiceException expected) {} - - waitTillListenerCallbacksComplete(); - listener.throwExceptionIfAny(); - } - - @Test - public void testProgressEventNotification_FailedRequest_WithRetry() { - // An invalid PutItemRequest that does not have the key attribute value - PutItemRequest request = new PutItemRequest( - BasicTempTable.TEMP_TABLE_NAME, - ImmutableMapParameter.of("foo", new AttributeValue("bar"))); - - // ClientConfiguration that specifies a maximum of two retries - ClientConfiguration config = new ClientConfiguration().withRetryPolicy(new RetryPolicy(new RetryCondition() { - - @Override - public boolean shouldRetry(AmazonWebServiceRequest originalRequest, - AmazonClientException exception, int retriesAttempted) { - return true; - } - - }, PredefinedRetryPolicies.DEFAULT_BACKOFF_STRATEGY, 2, false)); - - AmazonDynamoDB ddb_OneRetry = client(config); - - ExceptionReporter listener = ExceptionReporter.wrap(new ProgressListenerWithEventCodeVerification( - ProgressEventType.CLIENT_REQUEST_STARTED_EVENT, - // First attempt - ProgressEventType.HTTP_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_COMPLETED_EVENT, - // Second attempt - ProgressEventType.CLIENT_REQUEST_RETRY_EVENT, - ProgressEventType.HTTP_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_COMPLETED_EVENT, - // Third attempt - ProgressEventType.CLIENT_REQUEST_RETRY_EVENT, - ProgressEventType.HTTP_REQUEST_STARTED_EVENT, - ProgressEventType.HTTP_REQUEST_COMPLETED_EVENT, - ProgressEventType.CLIENT_REQUEST_FAILED_EVENT)); - request.setGeneralProgressListener(listener); - - - try { - ddb_OneRetry.putItem(request); - Assert.fail("Exception is expected since the PutItemRequest is invalid."); - } catch (AmazonServiceException expected) {} - - waitTillListenerCallbacksComplete(); - listener.throwExceptionIfAny(); - } - - /** - * Tests that RequestCycleProgressUpdatingListener properly tracks the - * request/response progress. - */ - @Test - public void testRequestCycleProgressReporting() { - ProgressTracker tracker = new ProgressTracker(); - BatchWriteItemRequest request = generateLargeBatchWriteItemRequest() - .withGeneralProgressListener(tracker); - dynamo.batchWriteItem(request); - Progress progress = tracker.getProgress(); - Assert.assertTrue(progress.getRequestContentLength() > 0); - Assert.assertEquals((Long)progress.getRequestContentLength(), - (Long)progress.getRequestBytesTransferred()); - Assert.assertTrue(progress.getResponseContentLength() > 0); - Assert.assertEquals((Long)progress.getResponseContentLength(), - (Long)progress.getResponseBytesTransferred()); - } - - private static BatchWriteItemRequest generateLargeBatchWriteItemRequest() { - List writes = new LinkedList(); - for (int i = 0; i < 25; i++) { - writes.add(new WriteRequest(new PutRequest( - ImmutableMapParameter.of( - BasicTempTable.HASH_KEY_NAME, new AttributeValue(Integer.toString(i)), - "large-random-string", new AttributeValue(RandomStringGenerator.nextRandomString(40 * KB)))))); - } - return new BatchWriteItemRequest( - Collections.singletonMap(BasicTempTable.TEMP_TABLE_NAME, writes)); - } - - private static class RandomStringGenerator { - - private static final String characters = "abcdefghijklmnopqrstuvwxyz"; - private static final Random random = new Random(); - - public static String nextRandomString(long length) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < length; i++) { - sb.append(characters.charAt(random.nextInt(characters.length()))); - } - return sb.toString(); - } - } - - private static void waitTillListenerCallbacksComplete() { - try { - SDKProgressPublisher.waitTillCompletion(); - } catch (InterruptedException e) { - Assert.fail("Interrupted when waiting for the progress listener callbacks to return. " - + e.getMessage()); - } catch (ExecutionException e) { - Assert.fail("Error when executing the progress listner callbacks. " - + e.getCause().getMessage()); - } - } -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/SecondaryIndexesTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/SecondaryIndexesTest.java deleted file mode 100644 index fab868ef9364..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/SecondaryIndexesTest.java +++ /dev/null @@ -1,456 +0,0 @@ -package software.amazon.awssdk.mapper.dynamodb; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.UUID; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.amazonaws.AmazonServiceException; -import software.amazon.awssdk.mapper.dynamodb.test.resources.tables.TempTableWithSecondaryIndexes; -import software.amazon.awssdk.mapper.dynamodb.test.util.DynamoDBTestBase; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProjectionType; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.QueryRequest; -import com.amazonaws.services.dynamodbv2.model.QueryResult; -import com.amazonaws.services.dynamodbv2.model.Select; -import com.amazonaws.services.dynamodbv2.model.TableDescription; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.RequiredResource; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.ResourceCreationPolicy; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.ResourceRetentionPolicy; -import software.amazon.awssdk.mapper.dynamodb.test.resources.ResourceCentricBlockJUnit4ClassRunner; - -/** - * DynamoDB integration tests for LSI & GSI. - */ -public class SecondaryIndexesTest extends LocalDynamoDBTestBase { - - private static final int MAX_RETRIES = 5; - private static final int SLEEP_TIME = 20000; - private static final String tableName = TempTableWithSecondaryIndexes.TEMP_TABLE_NAME; - private static final String HASH_KEY_NAME = TempTableWithSecondaryIndexes.HASH_KEY_NAME; - private static final String RANGE_KEY_NAME = TempTableWithSecondaryIndexes.RANGE_KEY_NAME; - private static final String LSI_NAME = TempTableWithSecondaryIndexes.LSI_NAME; - private static final String LSI_RANGE_KEY_NAME = TempTableWithSecondaryIndexes.LSI_RANGE_KEY_NAME; - private static final String GSI_NAME = TempTableWithSecondaryIndexes.GSI_NAME; - private static final String GSI_HASH_KEY_NAME = TempTableWithSecondaryIndexes.GSI_HASH_KEY_NAME; - private static final String GSI_RANGE_KEY_NAME = TempTableWithSecondaryIndexes.GSI_RANGE_KEY_NAME; - private static AmazonDynamoDB dynamo; - - @BeforeClass - public static void setUp() throws Exception { - dynamo = client(); - dynamo.createTable(TempTableWithSecondaryIndexes.getCreateTableRequest()); - } - - /** - * Assert the tableDescription is as expected - */ - @Test - public void testDescribeTempTableWithIndexes() { - TableDescription tableDescription = dynamo.describeTable(tableName).getTable(); - assertEquals(tableName, tableDescription.getTableName()); - assertNotNull(tableDescription.getTableStatus()); - assertEquals(2, tableDescription.getKeySchema().size()); - assertEquals(HASH_KEY_NAME, - tableDescription.getKeySchema().get(0) - .getAttributeName()); - assertEquals(KeyType.HASH.toString(), tableDescription - .getKeySchema().get(0).getKeyType()); - assertEquals(RANGE_KEY_NAME, tableDescription.getKeySchema() - .get(1).getAttributeName()); - assertEquals(KeyType.RANGE.toString(), tableDescription - .getKeySchema().get(1).getKeyType()); - - assertEquals(1, tableDescription.getLocalSecondaryIndexes().size()); - assertEquals(LSI_NAME, tableDescription - .getLocalSecondaryIndexes().get(0).getIndexName()); - assertEquals(2, tableDescription - .getLocalSecondaryIndexes().get(0).getKeySchema().size()); - assertEquals(HASH_KEY_NAME, tableDescription - .getLocalSecondaryIndexes().get(0).getKeySchema().get(0).getAttributeName()); - assertEquals(KeyType.HASH.toString(), tableDescription - .getLocalSecondaryIndexes().get(0).getKeySchema().get(0).getKeyType()); - assertEquals(LSI_RANGE_KEY_NAME, tableDescription - .getLocalSecondaryIndexes().get(0).getKeySchema().get(1).getAttributeName()); - assertEquals(KeyType.RANGE.toString(), tableDescription - .getLocalSecondaryIndexes().get(0).getKeySchema().get(1).getKeyType()); - assertEquals(ProjectionType.KEYS_ONLY.toString(), - tableDescription.getLocalSecondaryIndexes().get(0) - .getProjection().getProjectionType()); - assertEquals(null, tableDescription.getLocalSecondaryIndexes().get(0) - .getProjection().getNonKeyAttributes()); - - assertEquals(1, tableDescription.getGlobalSecondaryIndexes().size()); - assertEquals(GSI_NAME, tableDescription - .getGlobalSecondaryIndexes().get(0).getIndexName()); - assertEquals(2, tableDescription - .getGlobalSecondaryIndexes().get(0).getKeySchema().size()); - assertEquals(GSI_HASH_KEY_NAME, tableDescription - .getGlobalSecondaryIndexes().get(0).getKeySchema().get(0).getAttributeName()); - assertEquals(KeyType.HASH.toString(), tableDescription - .getGlobalSecondaryIndexes().get(0).getKeySchema().get(0).getKeyType()); - assertEquals(GSI_RANGE_KEY_NAME, tableDescription - .getGlobalSecondaryIndexes().get(0).getKeySchema().get(1).getAttributeName()); - assertEquals(KeyType.RANGE.toString(), tableDescription - .getGlobalSecondaryIndexes().get(0).getKeySchema().get(1).getKeyType()); - assertEquals(ProjectionType.KEYS_ONLY.toString(), - tableDescription.getGlobalSecondaryIndexes().get(0) - .getProjection().getProjectionType()); - assertEquals(null, tableDescription.getGlobalSecondaryIndexes().get(0) - .getProjection().getNonKeyAttributes()); - - } - - /** - * Tests making queries with global secondary index. - * @throws InterruptedException - */ - @Test - public void testQueryWithGlobalSecondaryIndex() throws InterruptedException { - // GSI attributes don't have to be unique - // so items with the same GSI keys but different primary keys - // could co-exist in the table. - int totalDuplicateGSIKeys = 10; - Random random = new Random(); - String duplicateGSIHashValue = UUID.randomUUID().toString(); - int duplicateGSIRangeValue = random.nextInt(); - for (int i = 0; i < totalDuplicateGSIKeys; i++) { - Map item = new HashMap(); - item.put(HASH_KEY_NAME, new AttributeValue().withS(UUID.randomUUID().toString())); - item.put(RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put(GSI_HASH_KEY_NAME, new AttributeValue().withS(duplicateGSIHashValue)); - item.put(GSI_RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(duplicateGSIRangeValue))); - dynamo.putItem(new PutItemRequest(tableName, item)); - } - - // Query the duplicate GSI key values should return all the items - Map keyConditions = new HashMap(); - keyConditions.put( - GSI_HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue().withS((duplicateGSIHashValue))) - .withComparisonOperator(ComparisonOperator.EQ)); - keyConditions.put( - GSI_RANGE_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue().withN(Integer - .toString(duplicateGSIRangeValue))) - .withComparisonOperator(ComparisonOperator.EQ)); - - // All the items with the GSI keys should be returned - assertQueryResultCount(totalDuplicateGSIKeys, new QueryRequest() - .withTableName(tableName) - .withIndexName(GSI_NAME) - .withKeyConditions(keyConditions)); - - // Other than this, the behavior of GSI query should be the similar - // as LSI query. So following code is similar to that used for - // LSI query test. - - String randomPrimaryHashKeyValue = UUID.randomUUID().toString(); - String randomGSIHashKeyValue = UUID.randomUUID().toString(); - int totalItemsPerHash = 10; - int totalIndexedItemsPerHash = 5; - Map item = new HashMap(); - - item.put(HASH_KEY_NAME, new AttributeValue().withS(randomPrimaryHashKeyValue)); - item.put(GSI_HASH_KEY_NAME, new AttributeValue().withS(randomGSIHashKeyValue)); - // Items with GSI keys - for (int i = 0; i < totalIndexedItemsPerHash; i++) { - item.put(RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put(GSI_RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put("attribute_" + i, new AttributeValue().withS(UUID.randomUUID().toString())); - dynamo.putItem(new PutItemRequest(tableName, item)); - item.remove("attribute_" + i); - } - item.remove(GSI_RANGE_KEY_NAME); - // Items with incomplete GSI keys (no GSI range key) - for (int i = totalIndexedItemsPerHash; i < totalItemsPerHash; i++) { - item.put(RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put("attribute_" + i, new AttributeValue().withS(UUID.randomUUID().toString())); - dynamo.putItem(new PutItemRequest(tableName, item)); - item.remove("attribute_" + i); - } - - /** - * 1) Query-with-GSI (only by GSI hash key) - */ - QueryResult result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(GSI_NAME) - .withKeyConditions( - Collections.singletonMap( - GSI_HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomGSIHashKeyValue)) - .withComparisonOperator( - ComparisonOperator.EQ)))); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // By default, the result includes all the key attributes (2 primary + 2 GSI). - assertEquals(4, result.getItems().get(0).size()); - - /** - * 2) Query-with-GSI (by GSI hash + range) - */ - int rangeKeyConditionRange = 2; - keyConditions = new HashMap(); - keyConditions.put( - GSI_HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue().withS(randomGSIHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ)); - keyConditions.put( - GSI_RANGE_KEY_NAME, - new Condition().withAttributeValueList(new AttributeValue() - .withN(Integer.toString(rangeKeyConditionRange))).withComparisonOperator(ComparisonOperator.LT)); - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(GSI_NAME) - .withKeyConditions(keyConditions)); - assertEquals((Object)rangeKeyConditionRange, (Object)result.getCount()); - - /** - * 3) Query-with-GSI on selected attributes (by AttributesToGet) - */ - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(GSI_NAME) - .withKeyConditions( - Collections.singletonMap( - GSI_HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomGSIHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ))) - .withAttributesToGet(HASH_KEY_NAME, RANGE_KEY_NAME)); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // Two attributes as specified in AttributesToGet - assertEquals(2, result.getItems().get(0).size()); - - /** - * 4) Exception when using both Selection and AttributeToGet - */ - try { - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(GSI_NAME) - .withKeyConditions( - Collections.singletonMap( - GSI_HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomGSIHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ))) - .withAttributesToGet(HASH_KEY_NAME, RANGE_KEY_NAME, LSI_RANGE_KEY_NAME) - .withSelect(Select.ALL_PROJECTED_ATTRIBUTES)); - fail("Should trigger exception when using both Select and AttributeToGet."); - } catch (AmazonServiceException ase) {} - - /** - * 5) Query-with-GSI on selected attributes (by Select.SPECIFIC_ATTRIBUTES) - */ - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(GSI_NAME) - .withKeyConditions( - Collections.singletonMap( - GSI_HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomGSIHashKeyValue)) - .withComparisonOperator( - ComparisonOperator.EQ))) - .withAttributesToGet(HASH_KEY_NAME) - .withSelect(Select.SPECIFIC_ATTRIBUTES)); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // Only one attribute as specified in AttributesToGet - assertEquals(1, result.getItems().get(0).size()); - } - /** - * Tests making queries with local secondary index. - */ - @Test - public void testQueryWithLocalSecondaryIndex() throws Exception { - String randomHashKeyValue = UUID.randomUUID().toString(); - int totalItemsPerHash = 10; - int totalIndexedItemsPerHash = 5; - Map item = new HashMap(); - - item.put(HASH_KEY_NAME, new AttributeValue().withS(randomHashKeyValue)); - // Items with LSI range key - for (int i = 0; i < totalIndexedItemsPerHash; i++) { - item.put(RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put(LSI_RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put("attribute_" + i, new AttributeValue().withS(UUID.randomUUID().toString())); - dynamo.putItem(new PutItemRequest(tableName, item)); - item.remove("attribute_" + i); - } - item.remove(LSI_RANGE_KEY_NAME); - // Items without LSI range key - for (int i = totalIndexedItemsPerHash; i < totalItemsPerHash; i++) { - item.put(RANGE_KEY_NAME, new AttributeValue().withN(Integer.toString(i))); - item.put("attribute_" + i, new AttributeValue().withS(UUID.randomUUID().toString())); - dynamo.putItem(new PutItemRequest(tableName, item)); - item.remove("attribute_" + i); - } - - /** - * 1) Query-with-LSI (only by hash key) - */ - QueryResult result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(LSI_NAME) - .withKeyConditions( - Collections.singletonMap( - HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomHashKeyValue)) - .withComparisonOperator( - ComparisonOperator.EQ)))); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // By default, the result includes all the projected attributes. - assertEquals(3, result.getItems().get(0).size()); - - /** - * 2) Query-with-LSI (by hash + LSI range) - */ - int rangeKeyConditionRange = 2; - Map keyConditions = new HashMap(); - keyConditions.put( - HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue().withS(randomHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ)); - keyConditions.put( - LSI_RANGE_KEY_NAME, - new Condition().withAttributeValueList(new AttributeValue() - .withN(Integer.toString(rangeKeyConditionRange))).withComparisonOperator(ComparisonOperator.LT)); - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(LSI_NAME) - .withKeyConditions(keyConditions)); - assertEquals((Object)rangeKeyConditionRange, (Object)result.getCount()); - - /** - * 3) Query-with-LSI on selected attributes (by Select) - */ - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(LSI_NAME) - .withKeyConditions( - Collections.singletonMap( - HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ))) - .withSelect(Select.ALL_ATTRIBUTES)); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // By setting Select.ALL_ATTRIBUTES, all attributes in the item will be returned - assertEquals(4, result.getItems().get(0).size()); - - /** - * 4) Query-with-LSI on selected attributes (by AttributesToGet) - */ - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(LSI_NAME) - .withKeyConditions( - Collections.singletonMap( - HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ))) - .withAttributesToGet(HASH_KEY_NAME, RANGE_KEY_NAME)); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // Two attributes as specified in AttributesToGet - assertEquals(2, result.getItems().get(0).size()); - - /** - * 5) Exception when using both Selection and AttributeToGet - */ - try { - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(LSI_NAME) - .withKeyConditions( - Collections.singletonMap( - HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomHashKeyValue)) - .withComparisonOperator(ComparisonOperator.EQ))) - .withAttributesToGet(HASH_KEY_NAME, RANGE_KEY_NAME, LSI_RANGE_KEY_NAME) - .withSelect(Select.ALL_PROJECTED_ATTRIBUTES)); - fail("Should trigger exception when using both Select and AttributeToGet."); - } catch (AmazonServiceException ase) {} - - /** - * 6) Query-with-LSI on selected attributes (by Select.SPECIFIC_ATTRIBUTES) - */ - result = dynamo.query(new QueryRequest() - .withTableName(tableName) - .withIndexName(LSI_NAME) - .withKeyConditions( - Collections.singletonMap( - HASH_KEY_NAME, - new Condition().withAttributeValueList( - new AttributeValue() - .withS(randomHashKeyValue)) - .withComparisonOperator( - ComparisonOperator.EQ))) - .withAttributesToGet(HASH_KEY_NAME) - .withSelect(Select.SPECIFIC_ATTRIBUTES)); - // Only the indexed items should be returned - assertEquals((Object)totalIndexedItemsPerHash, (Object)result.getCount()); - // Only one attribute as specified in AttributesToGet - assertEquals(1, result.getItems().get(0).size()); - } - - private void assertQueryResultCount(Integer expected, QueryRequest request) - throws InterruptedException { - - int retries = 0; - QueryResult result = null; - do { - result = dynamo.query(request); - - if (expected == result.getCount()) { - return; - } - // Handling eventual consistency. - Thread.sleep(SLEEP_TIME); - retries++; - } while (retries <= MAX_RETRIES); - - Assert.fail("Failed to assert query count. Expected : " + expected - + " actual : " + result.getCount()); - } -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ServiceTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ServiceTest.java deleted file mode 100644 index b27dd188ced5..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/ServiceTest.java +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright 2013 Amazon Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://aws.amazon.com/apache2.0 - * - * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES - * OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and - * limitations under the License. - */ -package software.amazon.awssdk.mapper.dynamodb; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; - -import static software.amazon.awssdk.mapper.dynamodb.test.util.SdkAsserts.assertNotEmpty; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.AmazonServiceException.ErrorType; -import software.amazon.awssdk.mapper.dynamodb.test.resources.tables.BasicTempTable; -import software.amazon.awssdk.mapper.dynamodb.test.resources.tables.TempTableWithBinaryKey; -import software.amazon.awssdk.mapper.dynamodb.test.util.DynamoDBTestBase; -import com.amazonaws.services.dynamodbv2.model.AttributeAction; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemResult; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.DeleteItemRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteItemResult; -import com.amazonaws.services.dynamodbv2.model.DeleteRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteTableResult; -import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes; -import com.amazonaws.services.dynamodbv2.model.ListTablesResult; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.PutItemResult; -import com.amazonaws.services.dynamodbv2.model.PutRequest; -import com.amazonaws.services.dynamodbv2.model.ReturnValue; -import com.amazonaws.services.dynamodbv2.model.ScanRequest; -import com.amazonaws.services.dynamodbv2.model.ScanResult; -import com.amazonaws.services.dynamodbv2.model.TableDescription; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; -import com.amazonaws.services.dynamodbv2.model.WriteRequest; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.RequiredResource; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.ResourceCreationPolicy; -import software.amazon.awssdk.mapper.dynamodb.test.resources.RequiredResources.ResourceRetentionPolicy; -import software.amazon.awssdk.mapper.dynamodb.test.resources.ResourceCentricBlockJUnit4ClassRunner; - -public class ServiceTest extends LocalDynamoDBTestBase { - - private static final String HASH_KEY_NAME = BasicTempTable.HASH_KEY_NAME; - private static final String tableName = BasicTempTable.TEMP_TABLE_NAME; - private static final String binaryKeyTableName = TempTableWithBinaryKey.TEMP_BINARY_TABLE_NAME; - private static final Long READ_CAPACITY = BasicTempTable.READ_CAPACITY; - private static final Long WRITE_CAPACITY = BasicTempTable.WRITE_CAPACITY; - private static AmazonDynamoDB dynamo; - - /** - * The only @BeforeClass method. - */ - @BeforeClass - public static void setUp() { - DynamoDBTestBase.setUpTestBase(); - dynamo = client(); - dynamo.createTable(BasicTempTable.getCreateTableRequest()); - dynamo.createTable(TempTableWithBinaryKey.getCreateTableRequest()); - } - - @Test - @SuppressWarnings("unchecked") - public void testNullQueryKeyErrorHandling() { - Map item = new HashMap(); - // Put a valid item first - item.put(HASH_KEY_NAME, new AttributeValue("bar")); - item.put("age", new AttributeValue("30")); - PutItemRequest putItemRequest = new PutItemRequest(tableName, item).withReturnValues(ReturnValue.ALL_OLD - .toString()); - dynamo.putItem(putItemRequest); - Map items = new HashMap(); - // Put a valid key and a null one - items.put(tableName, - new KeysAndAttributes().withKeys(getMapKey(HASH_KEY_NAME, new AttributeValue().withS("bar")), null)); - - BatchGetItemRequest request = new BatchGetItemRequest(); - request.setRequestItems(items); - - try { - dynamo.batchGetItem(request); - } catch (AmazonServiceException ase) { - assertEquals("ValidationException", ase.getErrorCode()); - } - - Map> requestItems = new HashMap>(); - List writeRequests = new ArrayList(); - Map writeAttributes = new HashMap(); - writeAttributes.put(HASH_KEY_NAME, new AttributeValue().withS("" + System.currentTimeMillis())); - writeAttributes.put("bar", new AttributeValue().withS("" + System.currentTimeMillis())); - writeRequests.add(new WriteRequest().withPutRequest(new PutRequest().withItem(writeAttributes))); - writeRequests.add(new WriteRequest().withPutRequest(new PutRequest().withItem(null))); - requestItems.put(tableName, writeRequests); - try { - dynamo.batchWriteItem(new BatchWriteItemRequest().withRequestItems(requestItems)); - } catch (AmazonServiceException ase) { - assertEquals("ValidationException", ase.getErrorCode()); - } - - } - - /** - * Tests that we correctly parse JSON error responses into AmazonServiceExceptions. - */ - @Test - public void testErrorHandling() throws Exception { - - DeleteTableRequest request = new DeleteTableRequest("non-existant-table"); - try { - dynamo.deleteTable(request); - fail("Expected an exception to be thrown"); - } catch (AmazonServiceException ase) { - assertNotEmpty(ase.getErrorCode()); - assertEquals(ErrorType.Client, ase.getErrorType()); - assertNotEmpty(ase.getMessage()); - assertNotEmpty(ase.getRequestId()); - assertNotEmpty(ase.getServiceName()); - assertTrue(ase.getStatusCode() >= 400); - assertTrue(ase.getStatusCode() < 600); - } - } - - /** - * Tests that we properly handle error responses for request entities that - * are too large. - */ - // DISABLED because DynamoDB apparently upped their max request size; we - // should be hitting this with a unit test that simulates an appropriate - // AmazonServiceException. - // @Test - public void testRequestEntityTooLargeErrorHandling() throws Exception { - BatchGetItemRequest request = new BatchGetItemRequest(); - - Map items = new HashMap(); - for (int i = 0; i < 1024; i++) { - KeysAndAttributes kaa = new KeysAndAttributes(); - StringBuilder bigString = new StringBuilder(); - for (int j = 0; j < 1024; j++) { - bigString.append("a"); - } - bigString.append(i); - items.put(bigString.toString(), kaa); - } - request.setRequestItems(items); - - try { - dynamo.batchGetItem(request); - } catch (AmazonServiceException ase) { - assertNotNull(ase.getMessage()); - assertEquals("Request entity too large", ase.getErrorCode()); - assertEquals(ErrorType.Client, ase.getErrorType()); - assertEquals(413, ase.getStatusCode()); - } - } - - @Test - public void testBatchWriteTooManyItemsErrorHandling() throws Exception { - int itemNumber = 26; - HashMap> requestItems = new HashMap>(); - List writeRequests = new ArrayList(); - for (int i = 0; i < itemNumber; i++) { - HashMap writeAttributes = new HashMap(); - writeAttributes.put(HASH_KEY_NAME, new AttributeValue().withS("" + System.currentTimeMillis())); - writeAttributes.put("bar", new AttributeValue().withS("" + System.currentTimeMillis())); - writeRequests.add(new WriteRequest().withPutRequest(new PutRequest().withItem(writeAttributes))); - } - requestItems.put(tableName, writeRequests); - try { - dynamo.batchWriteItem(new BatchWriteItemRequest().withRequestItems(requestItems)); - } catch (AmazonServiceException ase) { - assertEquals("ValidationException", ase.getErrorCode()); - assertEquals(ErrorType.Client, ase.getErrorType()); - assertNotEmpty(ase.getMessage()); - assertNotEmpty(ase.getRequestId()); - assertNotEmpty(ase.getServiceName()); - assertEquals(400, ase.getStatusCode()); - } - } - - /** - * Tests that we can call each service operation to create and describe - * tables, put, update and delete data, and query. - */ - @Test - public void testServiceOperations() throws Exception { - // Describe all tables - ListTablesResult describeTablesResult = dynamo.listTables(); - - // Describe our new table - DescribeTableRequest describeTablesRequest = new DescribeTableRequest().withTableName(tableName); - TableDescription tableDescription = dynamo.describeTable(describeTablesRequest).getTable(); - assertEquals(tableName, tableDescription.getTableName()); - assertNotNull(tableDescription.getTableStatus()); - assertEquals(HASH_KEY_NAME, tableDescription.getKeySchema().get(0).getAttributeName()); - assertEquals(KeyType.HASH.toString(), tableDescription.getKeySchema().get(0).getKeyType()); - assertNotNull(tableDescription.getProvisionedThroughput().getNumberOfDecreasesToday()); - assertEquals(READ_CAPACITY, tableDescription.getProvisionedThroughput().getReadCapacityUnits()); - assertEquals(WRITE_CAPACITY, tableDescription.getProvisionedThroughput().getWriteCapacityUnits()); - - // Add some data - int contentLength = 1 * 1024; - Set byteBufferSet = new HashSet(); - byteBufferSet.add(ByteBuffer.wrap(generateByteArray(contentLength))); - byteBufferSet.add(ByteBuffer.wrap(generateByteArray(contentLength + 1))); - - Map item = new HashMap(); - item.put(HASH_KEY_NAME, new AttributeValue("bar")); - item.put("age", new AttributeValue().withN("30")); - item.put("bar", new AttributeValue("" + System.currentTimeMillis())); - item.put("foos", new AttributeValue().withSS("bleh", "blah")); - item.put("S", new AttributeValue().withSS("ONE", "TWO")); - item.put("blob", new AttributeValue().withB(ByteBuffer.wrap(generateByteArray(contentLength)))); - item.put("blobs", new AttributeValue().withBS(ByteBuffer.wrap(generateByteArray(contentLength)), ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - item.put("BS", new AttributeValue().withBS(byteBufferSet)); - - PutItemRequest putItemRequest = new PutItemRequest(tableName, item).withReturnValues(ReturnValue.ALL_OLD.toString()); - - PutItemResult putItemResult = dynamo.putItem(putItemRequest); - - // Get our new item - GetItemResult getItemResult = dynamo.getItem(new GetItemRequest(tableName, getMapKey(HASH_KEY_NAME, - new AttributeValue("bar"))).withConsistentRead(true)); - assertNotNull(getItemResult.getItem().get("S").getSS()); - assertEquals(2, getItemResult.getItem().get("S").getSS().size()); - assertTrue(getItemResult.getItem().get("S").getSS().contains("ONE")); - assertTrue(getItemResult.getItem().get("S").getSS().contains("TWO")); - assertEquals("30", getItemResult.getItem().get("age").getN()); - assertNotNull(getItemResult.getItem().get("bar").getS()); - assertNotNull(getItemResult.getItem().get("blob").getB()); - assertEquals(0, getItemResult.getItem().get("blob").getB().compareTo(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertNotNull(getItemResult.getItem().get("blobs").getBS()); - assertEquals(2, getItemResult.getItem().get("blobs").getBS().size()); - assertTrue(getItemResult.getItem().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertTrue(getItemResult.getItem().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - assertNotNull(getItemResult.getItem().get("BS").getBS()); - assertEquals(2, getItemResult.getItem().get("BS").getBS().size()); - assertTrue(getItemResult.getItem().get("BS").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertTrue(getItemResult.getItem().get("BS").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - - // Add some data into the table with binary hash key - ByteBuffer byteBuffer = ByteBuffer.allocate(contentLength * 2); - byteBuffer.put(generateByteArray(contentLength)); - byteBuffer.flip(); - item = new HashMap(); - item.put(HASH_KEY_NAME, new AttributeValue().withB(byteBuffer)); - // Reuse the byteBuffer - item.put("blob", new AttributeValue().withB(byteBuffer)); - item.put("blobs", new AttributeValue().withBS(ByteBuffer.wrap(generateByteArray(contentLength)), ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - // Reuse the byteBufferSet - item.put("BS", new AttributeValue().withBS(byteBufferSet)); - - putItemRequest = new PutItemRequest(binaryKeyTableName, item).withReturnValues(ReturnValue.ALL_OLD.toString()); - dynamo.putItem(putItemRequest); - - // Get our new item - getItemResult = dynamo.getItem(new GetItemRequest(binaryKeyTableName, getMapKey(HASH_KEY_NAME, - new AttributeValue().withB(byteBuffer))).withConsistentRead(true)); - assertNotNull(getItemResult.getItem().get("blob").getB()); - assertEquals(0, getItemResult.getItem().get("blob").getB().compareTo(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertNotNull(getItemResult.getItem().get("blobs").getBS()); - assertEquals(2, getItemResult.getItem().get("blobs").getBS().size()); - assertTrue(getItemResult.getItem().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertTrue(getItemResult.getItem().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - assertNotNull(getItemResult.getItem().get("BS").getBS()); - assertEquals(2, getItemResult.getItem().get("BS").getBS().size()); - assertTrue(getItemResult.getItem().get("BS").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertTrue(getItemResult.getItem().get("BS").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - - // Load some random data - System.out.println("Loading data..."); - Random random = new Random(); - for (int i = 0; i < 50; i++) { - item = new HashMap(); - item.put(HASH_KEY_NAME, new AttributeValue("bar-" + System.currentTimeMillis())); - item.put("age", new AttributeValue().withN(Integer.toString(random.nextInt(100) + 30))); - item.put("bar", new AttributeValue("" + System.currentTimeMillis())); - item.put("foos", new AttributeValue().withSS("bleh", "blah")); - dynamo.putItem(new PutItemRequest(tableName, item).withReturnValues(ReturnValue.ALL_OLD.toString())); - } - - // Update an item - Map itemUpdates = new HashMap(); - itemUpdates.put("1", new AttributeValueUpdate(new AttributeValue("\u00A2"), AttributeAction.PUT.toString())); - itemUpdates.put("foos", new AttributeValueUpdate(new AttributeValue().withSS("foo"), AttributeAction.PUT.toString())); - itemUpdates.put("S", new AttributeValueUpdate(new AttributeValue().withSS("THREE"), AttributeAction.ADD.toString())); - itemUpdates.put("age", new AttributeValueUpdate(new AttributeValue().withN("10"), AttributeAction.ADD.toString())); - itemUpdates.put("blob", new AttributeValueUpdate(new AttributeValue().withB(ByteBuffer.wrap(generateByteArray(contentLength + 1))), AttributeAction.PUT.toString())); - itemUpdates.put("blobs", new AttributeValueUpdate(new AttributeValue().withBS(ByteBuffer.wrap(generateByteArray(contentLength))), AttributeAction.PUT.toString())); - UpdateItemRequest updateItemRequest = new UpdateItemRequest(tableName, getMapKey(HASH_KEY_NAME, new AttributeValue("bar")), itemUpdates).withReturnValues("ALL_NEW"); - - UpdateItemResult updateItemResult = dynamo.updateItem(updateItemRequest); - - assertEquals("\u00A2", updateItemResult.getAttributes().get("1").getS()); - assertEquals(1, updateItemResult.getAttributes().get("foos").getSS().size()); - assertTrue(updateItemResult.getAttributes().get("foos").getSS().contains("foo")); - assertEquals(3, updateItemResult.getAttributes().get("S").getSS().size()); - assertTrue(updateItemResult.getAttributes().get("S").getSS().contains("ONE")); - assertTrue(updateItemResult.getAttributes().get("S").getSS().contains("TWO")); - assertTrue(updateItemResult.getAttributes().get("S").getSS().contains("THREE")); - assertEquals(Integer.toString(30 + 10), updateItemResult.getAttributes().get("age").getN()); - assertEquals(0, updateItemResult.getAttributes().get("blob").getB().compareTo(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - assertEquals(1, updateItemResult.getAttributes().get("blobs").getBS().size()); - assertTrue(updateItemResult.getAttributes().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); - - itemUpdates.clear(); - itemUpdates.put("age", new AttributeValueUpdate(new AttributeValue().withN("30"), AttributeAction.PUT.toString())); - itemUpdates.put("blobs", new AttributeValueUpdate(new AttributeValue().withBS(ByteBuffer.wrap(generateByteArray(contentLength + 1))), AttributeAction.ADD.toString())); - updateItemRequest = new UpdateItemRequest(tableName, getMapKey(HASH_KEY_NAME, new AttributeValue("bar")), - itemUpdates).withReturnValues("ALL_NEW"); - - updateItemResult = dynamo.updateItem(updateItemRequest); - - assertEquals("30", updateItemResult.getAttributes().get("age").getN()); - assertEquals(2, updateItemResult.getAttributes().get("blobs").getBS().size()); - assertTrue(updateItemResult.getAttributes().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); - assertTrue(updateItemResult.getAttributes().get("blobs").getBS().contains(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); - - // Get an item that doesn't exist. - GetItemRequest getItemsRequest = new GetItemRequest(tableName, getMapKey(HASH_KEY_NAME, new AttributeValue("3"))).withConsistentRead(true); - GetItemResult getItemsResult = dynamo.getItem(getItemsRequest); - assertNull(getItemsResult.getItem()); - - // Get an item that doesn't have any attributes, - getItemsRequest = new GetItemRequest(tableName, getMapKey(HASH_KEY_NAME, new AttributeValue("bar"))).withConsistentRead(true).withAttributesToGet("non-existent-attribute"); - getItemsResult = dynamo.getItem(getItemsRequest); - assertEquals(0, getItemsResult.getItem().size()); - - - // Scan data - ScanRequest scanRequest = new ScanRequest(tableName).withAttributesToGet(HASH_KEY_NAME); - ScanResult scanResult = dynamo.scan(scanRequest); - assertTrue(scanResult.getCount() > 0); - assertTrue(scanResult.getScannedCount() > 0); - - - // Try a more advanced Scan query and run it a few times for performance metrics - System.out.println("Testing Scan..."); - for (int i = 0; i < 10; i++) { - HashMap scanFilter = new HashMap(); - scanFilter.put("age", new Condition().withAttributeValueList(new AttributeValue().withN("40")).withComparisonOperator(ComparisonOperator.GT.toString())); - scanRequest = new ScanRequest(tableName).withScanFilter(scanFilter); - scanResult = dynamo.scan(scanRequest); - } - - // Batch write - HashMap> requestItems = new HashMap>(); - List writeRequests = new ArrayList(); - HashMap writeAttributes = new HashMap(); - writeAttributes.put(HASH_KEY_NAME, new AttributeValue().withS("" + System.currentTimeMillis())); - writeAttributes.put("bar", new AttributeValue().withS("" + System.currentTimeMillis())); - writeRequests.add(new WriteRequest().withPutRequest(new PutRequest().withItem(writeAttributes))); - writeRequests.add(new WriteRequest().withDeleteRequest(new DeleteRequest().withKey(getMapKey(HASH_KEY_NAME, new AttributeValue().withS("toDelete"))))); - requestItems.put(tableName, writeRequests); - BatchWriteItemResult batchWriteItem = dynamo.batchWriteItem(new BatchWriteItemRequest().withRequestItems(requestItems)); -// assertNotNull(batchWriteItem.getItemCollectionMetrics()); -// assertEquals(1, batchWriteItem.getItemCollectionMetrics().size()); -// assertEquals(tableName, batchWriteItem.getItemCollectionMetrics().entrySet().iterator().next().get); -// assertNotNull(tableName, batchWriteItem.getResponses().iterator().next().getCapacityUnits()); - assertNotNull(batchWriteItem.getUnprocessedItems()); - assertTrue(batchWriteItem.getUnprocessedItems().isEmpty()); - - // Delete some data - DeleteItemRequest deleteItemRequest = new DeleteItemRequest(tableName, getMapKey(HASH_KEY_NAME, - new AttributeValue("jeep"))).withReturnValues(ReturnValue.ALL_OLD.toString()); - DeleteItemResult deleteItemResult = dynamo.deleteItem(deleteItemRequest); - - // Delete our table - DeleteTableResult deleteTable = dynamo.deleteTable(new DeleteTableRequest().withTableName(tableName)); - - } - -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/StandardModelFactoriesTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/StandardModelFactoriesTest.java index a22e39d1a1ab..2e51b08af53f 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/StandardModelFactoriesTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/StandardModelFactoriesTest.java @@ -23,7 +23,7 @@ import software.amazon.awssdk.mapper.dynamodb.pojos.DateRange; import software.amazon.awssdk.mapper.dynamodb.pojos.KeyAndVal; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.KeyType; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; import java.math.BigDecimal; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TestObjectCreator.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TestObjectCreator.java index c0884cd22a0f..7df3254a8ca3 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TestObjectCreator.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TestObjectCreator.java @@ -15,7 +15,7 @@ */ package software.amazon.awssdk.mapper.dynamodb; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import static software.amazon.awssdk.mapper.dynamodb.pojos.CustomBooleanClass.CustomBoolean; @@ -25,17 +25,18 @@ import software.amazon.awssdk.mapper.dynamodb.TransactionLoadRequest; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest.TransactionWriteOperation; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.DescribeTableResult; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodbv2.model.ReturnValuesOnConditionCheckFailure; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.TableStatus; import software.amazon.awssdk.mapper.dynamodb.pojos.AllSupportedAnnotationsClass; import software.amazon.awssdk.mapper.dynamodb.pojos.AllSupportedDataTypesClass; import software.amazon.awssdk.mapper.dynamodb.pojos.Currency; @@ -51,7 +52,6 @@ import software.amazon.awssdk.mapper.dynamodb.pojos.SlimAttributeNamesClass; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; -import com.amazonaws.services.dynamodbv2.util.TableUtils; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; @@ -67,8 +67,8 @@ public class TestObjectCreator { - public static final ProvisionedThroughput DEFAULT_PROVISIONED_THROUGHPUT = new ProvisionedThroughput().withReadCapacityUnits(10L) - .withWriteCapacityUnits(10L); + public static final ProvisionedThroughput DEFAULT_PROVISIONED_THROUGHPUT = + ProvisionedThroughput.builder().readCapacityUnits(10L).writeCapacityUnits(10L).build(); private static final String AWS_JAVA_SDK_UTIL_TABLE_NAME = "aws-java-sdk-util"; private static final String AWS_JAVA_SDK_DYNAMODB_MAPPER_SAVE_CONFIG_TEST_TABLE_NAME = "aws-java-sdk-dynamodb-mapper-save-config-test"; @@ -678,11 +678,11 @@ private static Set toSet(T... array) { return set; } - public static void createStringHashKeyTable(AmazonDynamoDB dynamoDB) throws InterruptedException { + public static void createStringHashKeyTable(DynamoDbClient dynamoDB) throws InterruptedException { createStringHashKeyTable(dynamoDB, AWS_JAVA_SDK_UTIL_TABLE_NAME); } - public static void createStringHashKeyTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createStringHashKeyTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "key" /* hashKeyName */, @@ -691,11 +691,11 @@ public static void createStringHashKeyTable(AmazonDynamoDB dynamoDB, String tabl null /* rangeKeyAttributeType */); } - public static void createSdkMapperSaveConfigTable(AmazonDynamoDB dynamoDB) throws InterruptedException { + public static void createSdkMapperSaveConfigTable(DynamoDbClient dynamoDB) throws InterruptedException { createSdkMapperSaveConfigTable(dynamoDB, AWS_JAVA_SDK_DYNAMODB_MAPPER_SAVE_CONFIG_TEST_TABLE_NAME); } - public static void createSdkMapperSaveConfigTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createSdkMapperSaveConfigTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "hashKey", @@ -704,11 +704,11 @@ public static void createSdkMapperSaveConfigTable(AmazonDynamoDB dynamoDB, Strin ScalarAttributeType.N); } - public static void createSdkRangeTestTable(AmazonDynamoDB dynamoDB) throws InterruptedException { + public static void createSdkRangeTestTable(DynamoDbClient dynamoDB) throws InterruptedException { createSdkRangeTestTable(dynamoDB, AWS_JAVA_SDK_RANGE_TEST_TABLE_NAME); } - public static void createSdkRangeTestTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createSdkRangeTestTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "key", @@ -717,11 +717,11 @@ public static void createSdkRangeTestTable(AmazonDynamoDB dynamoDB, String table ScalarAttributeType.N); } - public static void createSdkStringRangeTable(AmazonDynamoDB dynamoDB) throws InterruptedException { + public static void createSdkStringRangeTable(DynamoDbClient dynamoDB) throws InterruptedException { createSdkStringRangeTable(dynamoDB, AWS_JAVA_SDK_STRING_RANGE_TABLE_NAME); } - public static void createSdkStringRangeTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createSdkStringRangeTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "key", @@ -730,7 +730,7 @@ public static void createSdkStringRangeTable(AmazonDynamoDB dynamoDB, String tab ScalarAttributeType.S); } - public static void createHashKeyRangeKeyTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createHashKeyRangeKeyTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "hashKey", @@ -739,11 +739,11 @@ public static void createHashKeyRangeKeyTable(AmazonDynamoDB dynamoDB, String ta ScalarAttributeType.N); } - public static void createSdkDocAttributeTable(AmazonDynamoDB dynamoDB) throws InterruptedException { + public static void createSdkDocAttributeTable(DynamoDbClient dynamoDB) throws InterruptedException { createSdkDocAttributeTable(dynamoDB, AWS_JAVA_SDK_DOC_ATTRIBUTE_TABLE); } - public static void createSdkDocAttributeTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createSdkDocAttributeTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "id" /* hashKeyName */, @@ -752,7 +752,7 @@ public static void createSdkDocAttributeTable(AmazonDynamoDB dynamoDB, String ta null /* rangeKeyAttributeType */); } - public static void createAllSupportedAnnotationsTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + public static void createAllSupportedAnnotationsTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { createTestTable(dynamoDB, DEFAULT_PROVISIONED_THROUGHPUT, tableName, "id" /* hashKeyName */, @@ -768,41 +768,45 @@ public static void createAllSupportedAnnotationsTable(AmazonDynamoDB dynamoDB, S * rangeKeyName and rangeKeyAttributeType are optional. * */ - public static void createTestTable(AmazonDynamoDB dynamoDB, + public static void createTestTable(DynamoDbClient dynamoDB, ProvisionedThroughput provisionedThroughput, String tableName, String hashKeyName, ScalarAttributeType hashKeyAttributeType, String rangeKeyName, ScalarAttributeType rangeKeyAttributeType) throws InterruptedException { - CreateTableRequest createTableRequest = null; - createTableRequest = new CreateTableRequest() - .withTableName(tableName) - .withKeySchema( - new KeySchemaElement().withAttributeName( - hashKeyName).withKeyType( - KeyType.HASH)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName( - hashKeyName).withAttributeType( - hashKeyAttributeType)); + List keySchema = new ArrayList(); + List attributeDefinitions = new ArrayList(); + + keySchema.add(KeySchemaElement.builder().attributeName(hashKeyName).keyType(KeyType.HASH).build()); + attributeDefinitions.add( + AttributeDefinition.builder().attributeName(hashKeyName).attributeType(hashKeyAttributeType).build()); if (rangeKeyName != null) { - createTableRequest - .withKeySchema( - new KeySchemaElement().withAttributeName( - rangeKeyName).withKeyType( - KeyType.RANGE)) - - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName( - rangeKeyName).withAttributeType( - rangeKeyAttributeType)); + keySchema.add(KeySchemaElement.builder().attributeName(rangeKeyName).keyType(KeyType.RANGE).build()); + attributeDefinitions.add( + AttributeDefinition.builder().attributeName(rangeKeyName).attributeType(rangeKeyAttributeType).build()); } - createTableRequest.setProvisionedThroughput(provisionedThroughput); - if (TableUtils.createTableIfNotExists(dynamoDB, createTableRequest)) { - TableUtils.waitUntilActive(dynamoDB, tableName); + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(tableName) + .keySchema(keySchema) + .attributeDefinitions(attributeDefinitions) + .provisionedThroughput(provisionedThroughput) + .build(); + + if (createTableIfNotExists(dynamoDB, createTableRequest)) { + dynamoDB.waiter().waitUntilTableExists(b -> b.tableName(tableName)); + } + } + + private static boolean createTableIfNotExists(DynamoDbClient dynamoDB, CreateTableRequest createTableRequest) { + try { + dynamoDB.createTable(createTableRequest); + return true; + } catch (software.amazon.awssdk.services.dynamodb.model.ResourceInUseException e) { + // Table already exists. + return false; } } @@ -810,22 +814,26 @@ public static void createTestTable(AmazonDynamoDB dynamoDB, * Helper method to delete a table in Amazon DynamoDB. * Waits till the table becomes deleted or transitions to DELETING state. */ - public static void deleteTestTable(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { - DeleteTableRequest deleteTableRequest = new DeleteTableRequest().withTableName(tableName); + public static void deleteTestTable(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { + DeleteTableRequest deleteTableRequest = DeleteTableRequest.builder().tableName(tableName).build(); - if (TableUtils.deleteTableIfExists(dynamoDB, deleteTableRequest)) { + try { + dynamoDB.deleteTable(deleteTableRequest); waitUntilTableDeletedOrInDeleting(dynamoDB, tableName); + } catch (ResourceNotFoundException e) { + // Table does not exist; nothing to delete. } } - private static void waitUntilTableDeletedOrInDeleting(AmazonDynamoDB dynamoDB, String tableName) throws InterruptedException { + private static void waitUntilTableDeletedOrInDeleting(DynamoDbClient dynamoDB, String tableName) throws InterruptedException { long startTime = System.currentTimeMillis(); // Wait up to one minute for a table to be deleted or transition to DELETING state. long endTime = startTime + 60 * 1000; while (System.currentTimeMillis() < endTime) { try { - DescribeTableResult describeTableResult = dynamoDB.describeTable(tableName); - if ("DELETING".equals(describeTableResult.getTable().getTableStatus())) { + DescribeTableResponse describeTableResult = + dynamoDB.describeTable(b -> b.tableName(tableName)); + if (describeTableResult.table().tableStatus() == TableStatus.DELETING) { // Table will eventually get deleted, stopping to wait here reduces test run time by more than half return; } @@ -1099,8 +1107,8 @@ public static DynamoDBTransactionWriteExpression generateStringMatcherTransactWr attributeNameMap.put("#sA", "stringAttribute"); writeExpression.withConditionExpression("(#sA IN (:attr1, :attr2))"); Map attributeValueMap = new HashMap(); - attributeValueMap.put(":attr1", new AttributeValue(matchingString1)); - attributeValueMap.put(":attr2", new AttributeValue(matchingString2)); + attributeValueMap.put(":attr1", AttributeValue.builder().s(matchingString1).build()); + attributeValueMap.put(":attr2", AttributeValue.builder().s(matchingString2).build()); writeExpression.withExpressionAttributeValues(attributeValueMap); writeExpression.withExpressionAttributeNames(attributeNameMap); return writeExpression; @@ -1113,7 +1121,7 @@ public static DynamoDBTransactionWriteExpression generateStringContainsTransactW attributeNameMap.put("#sA", "stringAttribute"); writeExpression.withConditionExpression("contains(#sA, :attrV)"); Map attributeValueMap = new HashMap(); - attributeValueMap.put(":attrV", new AttributeValue(matchingSubString)); + attributeValueMap.put(":attrV", AttributeValue.builder().s(matchingSubString).build()); writeExpression.withExpressionAttributeValues(attributeValueMap); writeExpression.withExpressionAttributeNames(attributeNameMap); return writeExpression; @@ -1136,7 +1144,7 @@ public static DynamoDBTransactionWriteExpression generateStringContainsWithExpre DynamoDBTransactionWriteExpression writeExpression = new DynamoDBTransactionWriteExpression(); writeExpression.withConditionExpression("contains(stringAttribute, :attrV)"); Map attributeValueMap = new HashMap(); - attributeValueMap.put(":attrV", new AttributeValue(subStringToMatch)); + attributeValueMap.put(":attrV", AttributeValue.builder().s(subStringToMatch).build()); writeExpression.withExpressionAttributeValues(attributeValueMap); return writeExpression; } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionLoadUnitTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionLoadUnitTest.java index 9b99f1bc130b..102a92950059 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionLoadUnitTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionLoadUnitTest.java @@ -33,9 +33,9 @@ import java.util.Map; import software.amazon.awssdk.mapper.dynamodb.mapper.NoSuchTableClass; -import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteTableMapperUnitTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteTableMapperUnitTest.java index adb07422afec..b00987469958 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteTableMapperUnitTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteTableMapperUnitTest.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.Map; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; import org.junit.BeforeClass; @@ -90,8 +90,8 @@ public void testMultipleItemTableMapperTransactionWriteSucceeds() { Map attributeNameMap = new HashMap(); attributeNameMap.put("#sA", "stringAttribute"); Map attributeValueMap = new HashMap(); - attributeValueMap.put(":attr1", new AttributeValue(objectToBeConditionChecked.getStringAttribute())); - attributeValueMap.put(":attr2", new AttributeValue("not" + updatedStringAttribute)); + attributeValueMap.put(":attr1", AttributeValue.builder().s(objectToBeConditionChecked.getStringAttribute()).build()); + attributeValueMap.put(":attr2", AttributeValue.builder().s("not" + updatedStringAttribute).build()); conditionCheckWriteExpression.withExpressionAttributeValues(attributeValueMap); conditionCheckWriteExpression.withExpressionAttributeNames(attributeNameMap); transactionWriteRequest.addConditionCheck(objectToBeConditionChecked, conditionCheckWriteExpression); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteUnitTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteUnitTest.java index fc5d33e79132..80ef4f69e802 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteUnitTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionWriteUnitTest.java @@ -42,14 +42,15 @@ import java.util.Set; import java.util.UUID; -import com.amazonaws.SdkClientException; +import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.mapper.dynamodb.mapper.NoSuchTableClass; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodbv2.model.ReturnValuesOnConditionCheckFailure; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyBothAutoGenerated; import software.amazon.awssdk.mapper.dynamodb.pojos.MultiVersionRangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.PrimaryKeysNotAutogenerated_IndexKeysAutogenerated; @@ -126,9 +127,9 @@ public void testTransactionWriteSingleItemTest() { writeExpression = generateStringMatcherTransactWriteExpression("not1" + updatedStringAttribute, "not2" + updatedStringAttribute); Map expectedResponseValueMap = new HashMap(); - expectedResponseValueMap.put("originalName", new AttributeValue(obj.getRenamedAttribute())); - expectedResponseValueMap.put("key", new AttributeValue(obj.getKey())); - expectedResponseValueMap.put("stringAttribute", new AttributeValue(obj.getStringAttribute())); + expectedResponseValueMap.put("originalName", AttributeValue.builder().s(obj.getRenamedAttribute()).build()); + expectedResponseValueMap.put("key", AttributeValue.builder().s(obj.getKey()).build()); + expectedResponseValueMap.put("stringAttribute", AttributeValue.builder().s(obj.getStringAttribute()).build()); transactionWriteRequest.addConditionCheck(obj, writeExpression, ReturnValuesOnConditionCheckFailure.ALL_OLD); try { dynamoMapper.transactionWrite(transactionWriteRequest); @@ -713,11 +714,11 @@ public void testUpdateItemWithTransformerSucceeds() { // Retrieve the item directly to verify signature field exists Map key = new HashMap(); - key.put("hashKey", new AttributeValue(obj.getHashKey())); - key.put("rangeKey", new AttributeValue().withN(String.valueOf(obj.getRangeKey()))); - GetItemResult item = dynamoDB.getItem(TestItem.TABLE_NAME, key); - assertTrue(item.getItem().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); - assertEquals(ATTRIBUTE_ADDER_START, Integer.parseInt(item.getItem().get(ADDITIONAL_ATTRIBUTE_NAME).getN())); + key.put("hashKey", AttributeValue.builder().s(obj.getHashKey()).build()); + key.put("rangeKey", AttributeValue.builder().n(String.valueOf(obj.getRangeKey())).build()); + GetItemResponse item = dynamoDB.getItem(GetItemRequest.builder().tableName(TestItem.TABLE_NAME).key(key).build()); + assertTrue(item.item().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); + assertEquals(ATTRIBUTE_ADDER_START, Integer.parseInt(item.item().get(ADDITIONAL_ATTRIBUTE_NAME).n())); TestItem objToUpdate = new TestItem(); objToUpdate.setHashKey(obj.getHashKey()); @@ -731,11 +732,11 @@ public void testUpdateItemWithTransformerSucceeds() { assertEquals(objToUpdate, mapperWithTransformer.load(objToUpdate)); // Retrieve the item directly to verify signature field exists and is different from prior signature - key.put("hashKey", new AttributeValue(objToUpdate.getHashKey())); - key.put("rangeKey", new AttributeValue().withN(String.valueOf(objToUpdate.getRangeKey()))); - GetItemResult updatedItem = dynamoDB.getItem(TestItem.TABLE_NAME, key); - assertTrue(updatedItem.getItem().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); - assertEquals(ATTRIBUTE_ADDER_START + 1, Integer.parseInt(updatedItem.getItem().get(ADDITIONAL_ATTRIBUTE_NAME).getN())); + key.put("hashKey", AttributeValue.builder().s(objToUpdate.getHashKey()).build()); + key.put("rangeKey", AttributeValue.builder().n(String.valueOf(objToUpdate.getRangeKey())).build()); + GetItemResponse updatedItem = dynamoDB.getItem(GetItemRequest.builder().tableName(TestItem.TABLE_NAME).key(key).build()); + assertTrue(updatedItem.item().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); + assertEquals(ATTRIBUTE_ADDER_START + 1, Integer.parseInt(updatedItem.item().get(ADDITIONAL_ATTRIBUTE_NAME).n())); } @Test @@ -752,11 +753,11 @@ public void testUpdateItemWithTransformerNullAttributesSucceeds() { // Retrieve the item directly to verify additional field exists Map key = new HashMap(); - key.put("hashKey", new AttributeValue(obj.getHashKey())); - key.put("rangeKey", new AttributeValue().withN(String.valueOf(obj.getRangeKey()))); - GetItemResult item = dynamoDB.getItem(TestItem.TABLE_NAME, key); - assertTrue(item.getItem().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); - assertEquals(ATTRIBUTE_ADDER_START, Integer.parseInt(item.getItem().get(ADDITIONAL_ATTRIBUTE_NAME).getN())); + key.put("hashKey", AttributeValue.builder().s(obj.getHashKey()).build()); + key.put("rangeKey", AttributeValue.builder().n(String.valueOf(obj.getRangeKey())).build()); + GetItemResponse item = dynamoDB.getItem(GetItemRequest.builder().tableName(TestItem.TABLE_NAME).key(key).build()); + assertTrue(item.item().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); + assertEquals(ATTRIBUTE_ADDER_START, Integer.parseInt(item.item().get(ADDITIONAL_ATTRIBUTE_NAME).n())); // Update object with NullAttributeAdder (to verify removal of null non-modeled key) DynamoDBMapper mapperWithNullTransformer = new DynamoDBMapper(dynamoDB, null, new NullAttributeAdder(ADDITIONAL_ATTRIBUTE_NAME)); @@ -773,10 +774,10 @@ public void testUpdateItemWithTransformerNullAttributesSucceeds() { assertEquals(objToUpdate, mapperWithNullTransformer.load(objToUpdate)); // Retrieve the item directly to verify additional field doesn't exit - key.put("hashKey", new AttributeValue(objToUpdate.getHashKey())); - key.put("rangeKey", new AttributeValue().withN(String.valueOf(objToUpdate.getRangeKey()))); - GetItemResult updatedItem = dynamoDB.getItem(TestItem.TABLE_NAME, key); - assertFalse(updatedItem.getItem().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); + key.put("hashKey", AttributeValue.builder().s(objToUpdate.getHashKey()).build()); + key.put("rangeKey", AttributeValue.builder().n(String.valueOf(objToUpdate.getRangeKey())).build()); + GetItemResponse updatedItem = dynamoDB.getItem(GetItemRequest.builder().tableName(TestItem.TABLE_NAME).key(key).build()); + assertFalse(updatedItem.item().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); } @Test @@ -792,11 +793,11 @@ public void testPutItemWithTransformerSucceeds() { // Retrieve the item directly to verify signature field exists Map key = new HashMap(); - key.put("hashKey", new AttributeValue(obj.getHashKey())); - key.put("rangeKey", new AttributeValue().withN(String.valueOf(obj.getRangeKey()))); - GetItemResult item = dynamoDB.getItem(TestItem.TABLE_NAME, key); - assertTrue(item.getItem().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); - assertEquals(ATTRIBUTE_ADDER_START, Integer.parseInt(item.getItem().get(ADDITIONAL_ATTRIBUTE_NAME).getN())); + key.put("hashKey", AttributeValue.builder().s(obj.getHashKey()).build()); + key.put("rangeKey", AttributeValue.builder().n(String.valueOf(obj.getRangeKey())).build()); + GetItemResponse item = dynamoDB.getItem(GetItemRequest.builder().tableName(TestItem.TABLE_NAME).key(key).build()); + assertTrue(item.item().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); + assertEquals(ATTRIBUTE_ADDER_START, Integer.parseInt(item.item().get(ADDITIONAL_ATTRIBUTE_NAME).n())); } @Test @@ -856,8 +857,8 @@ private DynamoDBTransactionWriteExpression generateStringMatcherTransactWriteExp attributeNameMap.put("#sA", "stringAttribute"); writeExpression.withConditionExpression("(#sA IN (:attr1, :attr2))"); Map attributeValueMap = new HashMap(); - attributeValueMap.put(":attr1", new AttributeValue(matchingString1)); - attributeValueMap.put(":attr2", new AttributeValue(matchingString2)); + attributeValueMap.put(":attr1", AttributeValue.builder().s(matchingString1).build()); + attributeValueMap.put(":attr2", AttributeValue.builder().s(matchingString2).build()); writeExpression.withExpressionAttributeValues(attributeValueMap); writeExpression.withExpressionAttributeNames(attributeNameMap); return writeExpression; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionsUnitTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionsUnitTestBase.java index 647beb034869..ececcee9c180 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionsUnitTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/TransactionsUnitTestBase.java @@ -16,8 +16,8 @@ package software.amazon.awssdk.mapper.dynamodb; import software.amazon.awssdk.mapper.dynamodb.test.util.DynamoDBUnitTestBase; -import com.amazonaws.services.dynamodbv2.model.CancellationReason; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.CancellationReason; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import java.util.HashSet; import java.util.List; @@ -56,12 +56,12 @@ protected List transactionLoadObjects(TransactionLoadRequest transaction actualResponseObjects = dynamoMapper.transactionLoad(transactionLoadRequest, config); break; } catch (TransactionCanceledException tce) { - List cancellationReasons = tce.getCancellationReasons(); + List cancellationReasons = tce.cancellationReasons(); Set uniqueCancellationReasonCodes = new HashSet(); for (CancellationReason cancellationReason: cancellationReasons) { - uniqueCancellationReasonCodes.add(cancellationReason.getCode()); + uniqueCancellationReasonCodes.add(cancellationReason.code()); } - if (uniqueCancellationReasonCodes.size() != 1 || !"TransactionConflict".equals(cancellationReasons.get(0).getCode())) { + if (uniqueCancellationReasonCodes.size() != 1 || !"TransactionConflict".equals(cancellationReasons.get(0).code())) { fail("transactionLoad failed with TransactionCanceledException having non-TransactionConflict cancellation reason(s): " + tce); } // Sleep for some time before re-trying transactionLoad diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/VersionAttributeConditionExpressionGeneratorUnitTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/VersionAttributeConditionExpressionGeneratorUnitTest.java index bf281646e016..b08996476e23 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/VersionAttributeConditionExpressionGeneratorUnitTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/VersionAttributeConditionExpressionGeneratorUnitTest.java @@ -22,7 +22,7 @@ import java.util.HashMap; import java.util.Map; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.mapper.dynamodb.pojos.MultiVersionRangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import org.junit.Test; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/AutoGeneratedKeysIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/AutoGeneratedKeysIntegrationTest.java index d2fb4eb4a9dd..4b5d2488b2f5 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/AutoGeneratedKeysIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/AutoGeneratedKeysIntegrationTest.java @@ -38,21 +38,22 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBRangeKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBSaveExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; -import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.Projection; -import com.amazonaws.services.dynamodbv2.model.ProjectionType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.util.TableUtils; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GlobalSecondaryIndex; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import java.util.HashMap; +import java.util.Map; /** * Tests using auto-generated keys for range keys, hash keys, or both. @@ -72,28 +73,32 @@ public static void setUp() throws Exception { String keyName = DynamoDBMapperIntegrationTestBase.KEY_NAME; String rangeKeyAttributeName = "rangeKey"; - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_NAME) - .withKeySchema( - new KeySchemaElement(keyName, KeyType.HASH), - new KeySchemaElement(rangeKeyAttributeName, KeyType.RANGE)) - .withGlobalSecondaryIndexes(new GlobalSecondaryIndex() - .withIndexName(GSI_NAME) - .withKeySchema( - new KeySchemaElement(GSI_HASH_KEY, KeyType.HASH), - new KeySchemaElement(GSI_RANGE_KEY, KeyType.RANGE)) - .withProjection(new Projection() - .withProjectionType(ProjectionType.ALL)) - .withProvisionedThroughput(new ProvisionedThroughput(3L, 3L))) - .withAttributeDefinitions( - new AttributeDefinition(keyName, ScalarAttributeType.S), - new AttributeDefinition(rangeKeyAttributeName, ScalarAttributeType.S), - new AttributeDefinition(GSI_HASH_KEY, ScalarAttributeType.S), - new AttributeDefinition(GSI_RANGE_KEY, ScalarAttributeType.S)) - .withProvisionedThroughput(new ProvisionedThroughput(10L, 5L)); - - if (TableUtils.createTableIfNotExists(dynamo, createTableRequest)) { - TableUtils.waitUntilActive(dynamo, TABLE_NAME); + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(TABLE_NAME) + .keySchema( + KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(rangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .globalSecondaryIndexes(GlobalSecondaryIndex.builder() + .indexName(GSI_NAME) + .keySchema( + KeySchemaElement.builder().attributeName(GSI_HASH_KEY).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(GSI_RANGE_KEY).keyType(KeyType.RANGE).build()) + .projection(Projection.builder() + .projectionType(ProjectionType.ALL).build()) + .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(3L).writeCapacityUnits(3L).build()).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName(keyName).attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName(rangeKeyAttributeName).attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName(GSI_HASH_KEY).attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName(GSI_RANGE_KEY).attributeType(ScalarAttributeType.S).build()) + .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L).writeCapacityUnits(5L).build()) + .build(); + + try { + dynamo.createTable(createTableRequest); + dynamo.waiter().waitUntilTableExists(b -> b.tableName(TABLE_NAME)); + } catch (ResourceInUseException e) { + // Table already exists. } } @@ -157,7 +162,7 @@ public void testAutogeneratedKeyWithUserProvidedExpectedConditions() { DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); saveExpression .withExpected(Collections.singletonMap( - "otherAttribute", new ExpectedAttributeValue(false))) + "otherAttribute", ExpectedAttributeValue.builder().exists(false).build())) .withConditionalOperator(ConditionalOperator.AND); // The save should succeed since the user provided conditions are joined by AND. mapper.save(obj, saveExpression); @@ -178,19 +183,21 @@ public void testAutogeneratedKeyWithUserProvidedExpectedConditions() { } catch (IllegalArgumentException expected) {} // User-provided OR conditions should work if they completely override the generated conditions. + Map overrideConditions = new HashMap(); + overrideConditions.put("otherAttribute", ExpectedAttributeValue.builder().exists(false).build()); + overrideConditions.put("key", ExpectedAttributeValue.builder().exists(false).build()); + overrideConditions.put("rangeKey", ExpectedAttributeValue.builder().exists(false).build()); saveExpression - .withExpected(ImmutableMapParameter.of( - "otherAttribute", new ExpectedAttributeValue(false), - "key", new ExpectedAttributeValue(false), - "rangeKey", new ExpectedAttributeValue(false))) + .withExpected(overrideConditions) .withConditionalOperator(ConditionalOperator.OR); mapper.save(new HashKeyRangeKeyBothAutoGenerated(), saveExpression); + Map nonExistentConditions = new HashMap(); + nonExistentConditions.put("otherAttribute", ExpectedAttributeValue.builder().value(AttributeValue.builder().s("non-existent-value").build()).build()); + nonExistentConditions.put("key", ExpectedAttributeValue.builder().value(AttributeValue.builder().s("non-existent-value").build()).build()); + nonExistentConditions.put("rangeKey", ExpectedAttributeValue.builder().value(AttributeValue.builder().s("non-existent-value").build()).build()); saveExpression - .withExpected(ImmutableMapParameter.of( - "otherAttribute", new ExpectedAttributeValue(new AttributeValue("non-existent-value")), - "key", new ExpectedAttributeValue(new AttributeValue("non-existent-value")), - "rangeKey", new ExpectedAttributeValue(new AttributeValue("non-existent-value")))) + .withExpected(nonExistentConditions) .withConditionalOperator(ConditionalOperator.OR); try { mapper.save(new HashKeyRangeKeyBothAutoGenerated(), saveExpression); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BatchWriteTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BatchWriteTest.java index b5d250ce0bbe..3cb117149ae8 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BatchWriteTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BatchWriteTest.java @@ -18,11 +18,11 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.LocalDynamoDBTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper.FailedBatch; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteBufferClass; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import java.math.BigDecimal; @@ -51,16 +51,16 @@ public class BatchWriteTest extends LocalDynamoDBTestBase { private static int byteStart = 1; private static int startKeyDebug = 1; private static long startKey = System.currentTimeMillis(); - private static AmazonDynamoDB dynamo; + private static DynamoDbClient dynamo; @BeforeClass public static void setUp() throws Exception { dynamo = client(); DynamoDBMapper mapper = new DynamoDBMapper(dynamo); dynamo.createTable(mapper.generateCreateTableRequest(NumberSetAttributeClass.class) - .withProvisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT)); + .toBuilder().provisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT).build()); dynamo.createTable(mapper.generateCreateTableRequest(RangeKeyClass.class) - .withProvisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT)); + .toBuilder().provisionedThroughput(DEFAULT_PROVISIONED_THROUGHPUT).build()); } @Test diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BinaryAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BinaryAttributesIntegrationTest.java index 4708afd3700b..52c542ecbc29 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BinaryAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/BinaryAttributesIntegrationTest.java @@ -35,8 +35,9 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteArrayClass; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteBufferClass; @@ -52,11 +53,11 @@ public class BinaryAttributesIntegrationTest extends DynamoDBMapperIntegrationTe // Test data static { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withS("" + startKey++)); - attr.put(BINARY_ATTRIBUTE, new AttributeValue().withB(ByteBuffer.wrap(generateByteArray(contentLength)))); - attr.put(BINARY_SET_ATTRIBUTE, new AttributeValue(). - withBS(ByteBuffer.wrap(generateByteArray(contentLength)), - ByteBuffer.wrap(generateByteArray(contentLength + 1)))); + attr.put(KEY_NAME, AttributeValue.builder().s("" + startKey++).build()); + attr.put(BINARY_ATTRIBUTE, AttributeValue.builder().b(SdkBytes.fromByteBuffer(ByteBuffer.wrap(generateByteArray(contentLength)))).build()); + attr.put(BINARY_SET_ATTRIBUTE, AttributeValue.builder(). + bs(SdkBytes.fromByteBuffer(ByteBuffer.wrap(generateByteArray(contentLength))), + SdkBytes.fromByteBuffer(ByteBuffer.wrap(generateByteArray(contentLength + 1)))).build()); attrs.add(attr); }; @@ -67,7 +68,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_NAME, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(attr).build()); } } @@ -77,15 +78,15 @@ public void testLoad() throws Exception { for ( Map attr : attrs ) { // test BinaryAttributeClass - BinaryAttributeByteBufferClass x = util.load(BinaryAttributeByteBufferClass.class, attr.get(KEY_NAME).getS()); - assertEquals(x.getKey(), attr.get(KEY_NAME).getS()); + BinaryAttributeByteBufferClass x = util.load(BinaryAttributeByteBufferClass.class, attr.get(KEY_NAME).s()); + assertEquals(x.getKey(), attr.get(KEY_NAME).s()); assertEquals(x.getBinaryAttribute(), ByteBuffer.wrap(generateByteArray(contentLength))); assertTrue(x.getBinarySetAttribute().contains(ByteBuffer.wrap(generateByteArray(contentLength)))); assertTrue(x.getBinarySetAttribute().contains(ByteBuffer.wrap(generateByteArray(contentLength + 1)))); // test BinaryAttributeByteArrayClass - BinaryAttributeByteArrayClass y = util.load(BinaryAttributeByteArrayClass.class, attr.get(KEY_NAME).getS()); - assertEquals(y.getKey(), attr.get(KEY_NAME).getS()); + BinaryAttributeByteArrayClass y = util.load(BinaryAttributeByteArrayClass.class, attr.get(KEY_NAME).s()); + assertEquals(y.getKey(), attr.get(KEY_NAME).s()); assertTrue(Arrays.equals(y.getBinaryAttribute(), (generateByteArray(contentLength)))); assertEquals(2, y.getBinarySetAttribute().size()); assertTrue(setContainsBytes(y.getBinarySetAttribute(), generateByteArray(contentLength))); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/CrossSDKIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/CrossSDKIntegrationTest.java deleted file mode 100644 index e99c8968bef4..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/CrossSDKIntegrationTest.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2013 Amazon Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://aws.amazon.com/apache2.0 - * - * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES - * OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and - * limitations under the License. - */ -package software.amazon.awssdk.mapper.dynamodb.mapper; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Calendar; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -import org.junit.Test; - -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; -import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; -import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import software.amazon.awssdk.mapper.dynamodb.pojos.CrossSDKVerificationClass; -import com.amazonaws.services.dynamodbv2.util.TableUtils; - - -/** - * Cross-SDK acceptance test. More of a smoke test, verifies that the formats - * used by each program's ORM can be read by the others. - */ -public class CrossSDKIntegrationTest extends DynamoDBMapperIntegrationTestBase { - - private static final String TABLE_NAME = "aws-xsdk"; - - private static final String HASH_KEY = "3530a51a-0760-47d2-bfcb-158320d6188a"; - private static final String RANGE_KEY = "61cdf81e-792f-4dd8-a812-a16185bfbf60"; - - private static int start = 1; - - // @BeforeClass - public static void setUp() throws Exception { - setUpCredentials(); - dynamo = new AmazonDynamoDBClient(credentials); - - // Create a table - String keyName = DynamoDBMapperIntegrationTestBase.KEY_NAME; - String rangeKey = "rangeKey"; - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_NAME) - .withKeySchema(new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(rangeKey).withKeyType(KeyType.RANGE)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(keyName).withAttributeType( - ScalarAttributeType.S), - new AttributeDefinition().withAttributeName(rangeKey).withAttributeType( - ScalarAttributeType.S)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(10L) - .withWriteCapacityUnits(10L)); - - if (TableUtils.createTableIfNotExists(dynamo, createTableRequest)) { - TableUtils.waitUntilActive(dynamo, TABLE_NAME); - } - } - - @Test - public void disabled() { - } - - // This record written by the .NET mapper no longer exists, so this test - // NPEs. If we want to add back something similar we should generate some - // items using the .NET mapper and check a serialized form of them into - // this package so this can be run as a unit test. - // @Test - public void testLoad() throws Exception { - DynamoDBMapper mapper = new DynamoDBMapper(dynamo); - - CrossSDKVerificationClass obj = mapper.load(CrossSDKVerificationClass.class, HASH_KEY, RANGE_KEY); - - Long originalVersion = obj.getVersion(); - - assertNotNull(obj); - assertNotNull(obj.getKey()); - assertEquals(obj.getKey(), HASH_KEY); - assertNotNull(obj.getRangeKey()); - assertEquals(obj.getRangeKey(), RANGE_KEY); - assertNotNull(originalVersion); - assertNotNull(obj.getBigDecimalAttribute()); - assertNotNull(obj.getBigDecimalSetAttribute()); - assertEquals(3, obj.getBigDecimalSetAttribute().size()); - assertNotNull(obj.getBigIntegerAttribute()); - assertNotNull(obj.getBigIntegerSetAttribute()); - assertEquals(3, obj.getBigIntegerSetAttribute().size()); - assertNotNull(obj.getBooleanAttribute()); - assertNotNull(obj.getBooleanSetAttribute()); - assertEquals(2, obj.getBooleanSetAttribute().size()); - assertNotNull(obj.getByteAttribute()); - assertNotNull(obj.getByteSetAttribute()); - assertEquals(3, obj.getByteSetAttribute().size()); - assertNotNull(obj.getCalendarAttribute()); - assertNotNull(obj.getCalendarSetAttribute()); - assertEquals(3, obj.getCalendarSetAttribute().size()); - assertNotNull(obj.getDateAttribute()); - assertNotNull(obj.getDateSetAttribute()); - assertEquals(3, obj.getDateSetAttribute().size()); - assertNotNull(obj.getDoubleAttribute()); - assertNotNull(obj.getDoubleSetAttribute()); - assertEquals(3, obj.getDoubleSetAttribute().size()); - assertNotNull(obj.getFloatAttribute()); - assertNotNull(obj.getFloatSetAttribute()); - assertEquals(3, obj.getFloatSetAttribute().size()); - assertNotNull(obj.getIntegerAttribute()); - assertNotNull(obj.getIntegerSetAttribute()); - assertEquals(3, obj.getIntegerSetAttribute().size()); - assertNotNull(obj.getLongAttribute()); - assertNotNull(obj.getLongSetAttribute()); - assertEquals(3, obj.getLongSetAttribute().size()); - assertNotNull(obj.getStringSetAttribute()); - assertEquals(3, obj.getStringSetAttribute().size()); - - updateObjectValues(obj); - - mapper.save(obj); - assertFalse(originalVersion.equals(obj.getVersion())); - - CrossSDKVerificationClass loaded = mapper.load(CrossSDKVerificationClass.class, HASH_KEY, RANGE_KEY); - assertEquals(loaded, obj); - } - - /** - * Updates all values in the object (except for the keys and version) - */ - private void updateObjectValues(CrossSDKVerificationClass obj) { - obj.setBigDecimalAttribute(obj.getBigDecimalAttribute().add(BigDecimal.ONE)); - Set bigDecimals = new HashSet(); - for (BigDecimal d : obj.getBigDecimalSetAttribute()) { - bigDecimals.add(d.add(BigDecimal.ONE)); - } - obj.setBigDecimalSetAttribute(bigDecimals); - - obj.setBigIntegerAttribute(obj.getBigIntegerAttribute().add(BigInteger.ONE)); - Set bigInts = new HashSet(); - for (BigInteger d : obj.getBigIntegerSetAttribute()) { - bigInts.add(d.add(BigInteger.ONE)); - } - obj.setBigIntegerSetAttribute(bigInts); - - obj.setBooleanAttribute(!obj.getBooleanAttribute()); - - obj.setByteAttribute((byte) ((obj.getByteAttribute() +1) % Byte.MAX_VALUE)); - Set bytes = new HashSet(); - for (Byte b : obj.getByteSetAttribute()) { - bytes.add((byte) ((b +1) % Byte.MAX_VALUE)); - } - - obj.getCalendarAttribute().setTime(new Date(obj.getCalendarAttribute().getTimeInMillis() + 1000)); - for (Calendar c : obj.getCalendarSetAttribute()) { - c.setTime(new Date(c.getTimeInMillis() + 1000)); - } - - obj.getDateAttribute().setTime(obj.getDateAttribute().getTime() + 1000); - for (Date d : obj.getDateSetAttribute()) { - d.setTime(d.getTime() + 1000); - } - - obj.setDoubleAttribute(obj.getDoubleAttribute() + 1.0); - Set doubleSet = new HashSet(); - for (Double d : obj.getDoubleSetAttribute()) { - doubleSet.add(d + 1.0); - } - obj.setDoubleSetAttribute(doubleSet); - - obj.setFloatAttribute((float) (obj.getFloatAttribute() + 1.0)); - Set floatSet = new HashSet(); - for (Float f : obj.getFloatSetAttribute()) { - floatSet.add(f + 1.0f); - } - obj.setFloatSetAttribute(floatSet); - - obj.setIntegerAttribute(obj.getIntegerAttribute() + 1); - Set intSet = new HashSet(); - for (Integer i : obj.getIntegerSetAttribute()) { - intSet.add(i + 1); - } - obj.setIntegerSetAttribute(intSet); - - obj.setLastUpdater("java-sdk"); - - obj.setLongAttribute(obj.getLongAttribute() + 1); - Set longSet = new HashSet(); - for (Long l : obj.getLongSetAttribute()) { - longSet.add(l + 1); - } - obj.setLongSetAttribute(longSet); - - obj.setStringSetAttribute(toSet(UUID.randomUUID().toString(), UUID.randomUUID().toString(), UUID.randomUUID().toString())); - } - - /** - * Used to set up the original object, no longer used. - */ - @SuppressWarnings("unused") - private CrossSDKVerificationClass getUniqueObject() { - CrossSDKVerificationClass obj = new CrossSDKVerificationClass(); - obj.setKey(HASH_KEY); - obj.setRangeKey(RANGE_KEY); - obj.setBigDecimalAttribute(new BigDecimal(start++)); - obj.setBigDecimalSetAttribute(toSet(new BigDecimal(start++), new BigDecimal(start++), new BigDecimal(start++))); - obj.setBigIntegerAttribute(new BigInteger("" + start++)); - obj.setBigIntegerSetAttribute(toSet(new BigInteger("" + start++), new BigInteger("" + start++), new BigInteger("" + start++))); - obj.setBooleanAttribute(start++ % 2 == 0); - obj.setBooleanSetAttribute(toSet(true, false)); - obj.setByteAttribute((byte) start++); - obj.setByteSetAttribute(toSet((byte) start++, (byte) start++, (byte) start++)); - obj.setCalendarAttribute(getUniqueCalendar()); - obj.setCalendarSetAttribute(toSet(getUniqueCalendar(), getUniqueCalendar(), getUniqueCalendar())); - obj.setDateAttribute(new Date(start++)); - obj.setDateSetAttribute(toSet(new Date(start++), new Date(start++), new Date(start++))); - obj.setDoubleAttribute((double) start++); - obj.setDoubleSetAttribute(toSet((double) start++, (double) start++, (double) start++)); - obj.setFloatAttribute((float) start++); - obj.setFloatSetAttribute(toSet((float) start++, (float) start++, (float) start++)); - obj.setIntegerAttribute(start++); - obj.setIntegerSetAttribute(toSet(start++, start++, start++)); - obj.setLongAttribute((long) start++); - obj.setLongSetAttribute(toSet((long) start++, (long) start++, (long) start++)); - obj.setStringSetAttribute(toSet("" + start++, "" + start++, "" + start++)); - return obj; - } - - private Calendar getUniqueCalendar() { - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date(start++)); - return cal; - } - -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/DynamoDBTypeConvertedEpochDateTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/DynamoDBTypeConvertedEpochDateTest.java index f32383d72648..270bbea8bd02 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/DynamoDBTypeConvertedEpochDateTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/DynamoDBTypeConvertedEpochDateTest.java @@ -14,18 +14,19 @@ */ package software.amazon.awssdk.mapper.dynamodb.mapper; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConvertedEpochDate; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; -import software.amazon.awssdk.mapper.dynamodb.test.AWSIntegrationTestBase; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; + +import java.util.HashMap; +import java.util.Map; import org.joda.time.DateTime; import org.junit.Before; @@ -52,21 +53,21 @@ * via the {@link DynamoDBTypeConvertedEpochDate} annontation. */ @RunWith(MockitoJUnitRunner.class) -public class DynamoDBTypeConvertedEpochDateTest extends AWSIntegrationTestBase { +public class DynamoDBTypeConvertedEpochDateTest { private static final String HASH_KEY = "1234"; private DynamoDBMapper mapper; @Mock - private AmazonDynamoDB ddb; + private DynamoDbClient ddb; @Before public void setup() { MockitoAnnotations.initMocks(this); mapper = new DynamoDBMapper(ddb); // Just stub dummy response for all save related tests - when(ddb.updateItem(any(UpdateItemRequest.class))).thenReturn(new UpdateItemResult()); + when(ddb.updateItem(any(UpdateItemRequest.class))).thenReturn(UpdateItemResponse.builder().build()); } @Test @@ -75,7 +76,7 @@ public void saveItem_DateSentAsNumericUpdate() { mapper.save(new PojoWithDate() .setHashKey(UUID.randomUUID().toString()) .setDate(date)); - verifyAttributeUpdatedWithValue("date", new AttributeValue().withN(String.valueOf(date.getTime()))); + verifyAttributeUpdatedWithValue("date", AttributeValue.builder().n(String.valueOf(date.getTime())).build()); } @Test @@ -84,7 +85,7 @@ public void saveItem_CalendarSentAsNumericUpdate() { mapper.save(new PojoWithDate() .setHashKey(UUID.randomUUID().toString()) .setCalendar(calendar)); - verifyAttributeUpdatedWithValue("calendar", new AttributeValue().withN(String.valueOf(calendar.getTime().getTime()))); + verifyAttributeUpdatedWithValue("calendar", AttributeValue.builder().n(String.valueOf(calendar.getTime().getTime())).build()); } @Test @@ -93,26 +94,26 @@ public void saveItem_DateTimeSentAsNumericUpdate() { mapper.save(new PojoWithDate() .setHashKey(UUID.randomUUID().toString()) .setDateTime(dateTime)); - verifyAttributeUpdatedWithValue("dateTime", new AttributeValue().withN(String.valueOf(dateTime.toDate().getTime()))); + verifyAttributeUpdatedWithValue("dateTime", AttributeValue.builder().n(String.valueOf(dateTime.toDate().getTime())).build()); } @Test public void getItem_WithNumericDateInResponse_UnmarshalledCorrectly() { - stubGetItemRequest("date", new AttributeValue().withN("1234")); + stubGetItemRequest("date", AttributeValue.builder().n("1234").build()); final PojoWithDate pojo = loadPojo(); assertThat(pojo.getDate().getTime(), equalTo(1234L)); } @Test public void getItem_WithNumericCalendarInResponse_UnmarshalledCorrectly() { - stubGetItemRequest("calendar", new AttributeValue().withN("1234")); + stubGetItemRequest("calendar", AttributeValue.builder().n("1234").build()); final PojoWithDate pojo = loadPojo(); assertThat(pojo.getCalendar().getTime().getTime(), equalTo(1234L)); } @Test public void getItem_WithNumericDateTimeInResponse_UnmarshalledCorrectly() { - stubGetItemRequest("dateTime", new AttributeValue().withN("1234")); + stubGetItemRequest("dateTime", AttributeValue.builder().n("1234").build()); final PojoWithDate pojo = loadPojo(); assertThat(pojo.getDateTime().toDate().getTime(), equalTo(1234L)); } @@ -132,15 +133,16 @@ private void stubGetItemRequest(String attributeName, AttributeValue attributeVa } /** - * Create a {@link GetItemResult} with the hash key value ({@value #HASH_KEY} and the additional attribute. + * Create a {@link GetItemResponse} with the hash key value ({@value #HASH_KEY} and the additional attribute. * - * @param attributeName Additional attribute to include in created {@link GetItemResult}. + * @param attributeName Additional attribute to include in created {@link GetItemResponse}. * @param attributeValue Value of additional attribute. */ - private GetItemResult createGetItemResult(String attributeName, AttributeValue attributeValue) { - return new GetItemResult().withItem( - ImmutableMapParameter.of("hashKey", new AttributeValue(HASH_KEY), - attributeName, attributeValue)); + private GetItemResponse createGetItemResult(String attributeName, AttributeValue attributeValue) { + Map item = new HashMap<>(); + item.put("hashKey", AttributeValue.builder().s(HASH_KEY).build()); + item.put(attributeName, attributeValue); + return GetItemResponse.builder().item(item).build(); } /** @@ -152,7 +154,7 @@ private GetItemResult createGetItemResult(String attributeName, AttributeValue a private void verifyAttributeUpdatedWithValue(String attributeName, AttributeValue expected) { ArgumentCaptor updateItemRequestCaptor = ArgumentCaptor.forClass(UpdateItemRequest.class); verify(ddb).updateItem(updateItemRequestCaptor.capture()); - assertEquals(expected, updateItemRequestCaptor.getValue().getAttributeUpdates().get(attributeName).getValue()); + assertEquals(expected, updateItemRequestCaptor.getValue().attributeUpdates().get(attributeName).value()); } @DynamoDBTable(tableName = "PojoWithDate") diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteArrayAttributesTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteArrayAttributesTest.java index 81b9bbd9d4aa..f4c1c2aadc91 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteArrayAttributesTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteArrayAttributesTest.java @@ -14,25 +14,26 @@ */ package software.amazon.awssdk.mapper.dynamodb.mapper; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteArrayClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,7 +52,7 @@ public class EmptyBinaryByteArrayAttributesTest { private static final String KEY_NAME = "key"; private static final String KEY_VALUE = "test-id"; private static final byte[] EMPTY_BINARY = new byte[]{}; - private static final AttributeValue EMPTY_BINARY_AV = new AttributeValue().withB(ByteBuffer.wrap(EMPTY_BINARY)); + private static final AttributeValue EMPTY_BINARY_AV = AttributeValue.builder().b(SdkBytes.fromByteArray(EMPTY_BINARY)).build(); private static final Map ITEM_MAP; private static final Map KEY_MAP; @@ -59,10 +60,10 @@ public class EmptyBinaryByteArrayAttributesTest { static { KEY_MAP = new HashMap<>(); - KEY_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + KEY_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP = new HashMap<>(); - ITEM_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + ITEM_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP.put(BINARY_ATTRIBUTE, EMPTY_BINARY_AV); TEST_OBJECT = new BinaryAttributeByteArrayClass(); @@ -71,7 +72,7 @@ public class EmptyBinaryByteArrayAttributesTest { } @Mock - private AmazonDynamoDB mockDynamo; + private DynamoDbClient mockDynamo; @Captor private ArgumentCaptor getItemRequestCaptor; @@ -84,17 +85,18 @@ public class EmptyBinaryByteArrayAttributesTest { @Test public void testLoad() { - when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(new GetItemResult().withItem(ITEM_MAP)); + when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(GetItemResponse.builder().item(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); BinaryAttributeByteArrayClass x = dynamoDBMapper.load(BinaryAttributeByteArrayClass.class, - ITEM_MAP.get(KEY_NAME).getS()); - assertEquals(ITEM_MAP.get(KEY_NAME).getS(), x.getKey()); - assertEquals(EMPTY_BINARY, x.getBinaryAttribute()); + ITEM_MAP.get(KEY_NAME).s()); + assertEquals(ITEM_MAP.get(KEY_NAME).s(), x.getKey()); + // v2 SdkBytes.asByteArray() returns a defensive copy, so compare by content rather than identity. + assertArrayEquals(EMPTY_BINARY, x.getBinaryAttribute()); verify(mockDynamo).getItem(getItemRequestCaptor.capture()); GetItemRequest getItemRequest = getItemRequestCaptor.getValue(); - assertEquals(KEY_MAP, getItemRequest.getKey()); + assertEquals(KEY_MAP, getItemRequest.key()); } @Test @@ -107,13 +109,13 @@ public void testSaveUsingPut() { verify(mockDynamo).putItem(putItemRequestCaptor.capture()); PutItemRequest putItemRequest = putItemRequestCaptor.getValue(); - assertEquals(ITEM_MAP, putItemRequest.getItem()); + assertEquals(ITEM_MAP, putItemRequest.item()); } @Test public void testSaveUsingUpdate() { when(mockDynamo.updateItem(any(UpdateItemRequest.class))) - .thenReturn(new UpdateItemResult().withAttributes(ITEM_MAP)); + .thenReturn(UpdateItemResponse.builder().attributes(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); dynamoDBMapper.save(TEST_OBJECT, DynamoDBMapperConfig.builder() @@ -122,10 +124,10 @@ public void testSaveUsingUpdate() { verify(mockDynamo).updateItem(updateItemRequestArgumentCaptor.capture()); UpdateItemRequest updateItemRequest = updateItemRequestArgumentCaptor.getValue(); - assertEquals(KEY_MAP, updateItemRequest.getKey()); - Map updates = updateItemRequest.getAttributeUpdates(); + assertEquals(KEY_MAP, updateItemRequest.key()); + Map updates = updateItemRequest.attributeUpdates(); AttributeValueUpdate attributeValueUpdate = updates.get(BINARY_ATTRIBUTE); - assertEquals(EMPTY_BINARY_AV, attributeValueUpdate.getValue()); - assertEquals("PUT", attributeValueUpdate.getAction()); + assertEquals(EMPTY_BINARY_AV, attributeValueUpdate.value()); + assertEquals("PUT", attributeValueUpdate.actionAsString()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteBufferAttributesTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteBufferAttributesTest.java index 8d74139f71a8..9c111817aba1 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteBufferAttributesTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinaryByteBufferAttributesTest.java @@ -23,16 +23,17 @@ import java.util.HashMap; import java.util.Map; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteBufferClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,7 +52,7 @@ public class EmptyBinaryByteBufferAttributesTest { private static final String KEY_NAME = "key"; private static final String KEY_VALUE = "test-id"; private static final ByteBuffer EMPTY_BINARY = ByteBuffer.wrap(new byte[]{}); - private static final AttributeValue EMPTY_BINARY_AV = new AttributeValue().withB(EMPTY_BINARY); + private static final AttributeValue EMPTY_BINARY_AV = AttributeValue.builder().b(SdkBytes.fromByteBuffer(EMPTY_BINARY)).build(); private static final Map ITEM_MAP; private static final Map KEY_MAP; @@ -59,10 +60,10 @@ public class EmptyBinaryByteBufferAttributesTest { static { KEY_MAP = new HashMap<>(); - KEY_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + KEY_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP = new HashMap<>(); - ITEM_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + ITEM_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP.put(BINARY_ATTRIBUTE, EMPTY_BINARY_AV); TEST_OBJECT = new BinaryAttributeByteBufferClass(); @@ -71,7 +72,7 @@ public class EmptyBinaryByteBufferAttributesTest { } @Mock - private AmazonDynamoDB mockDynamo; + private DynamoDbClient mockDynamo; @Captor private ArgumentCaptor getItemRequestCaptor; @@ -84,17 +85,17 @@ public class EmptyBinaryByteBufferAttributesTest { @Test public void testLoad() { - when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(new GetItemResult().withItem(ITEM_MAP)); + when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(GetItemResponse.builder().item(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); BinaryAttributeByteBufferClass x = dynamoDBMapper.load(BinaryAttributeByteBufferClass.class, - ITEM_MAP.get(KEY_NAME).getS()); - assertEquals(ITEM_MAP.get(KEY_NAME).getS(), x.getKey()); + ITEM_MAP.get(KEY_NAME).s()); + assertEquals(ITEM_MAP.get(KEY_NAME).s(), x.getKey()); assertEquals(EMPTY_BINARY, x.getBinaryAttribute()); verify(mockDynamo).getItem(getItemRequestCaptor.capture()); GetItemRequest getItemRequest = getItemRequestCaptor.getValue(); - assertEquals(KEY_MAP, getItemRequest.getKey()); + assertEquals(KEY_MAP, getItemRequest.key()); } @Test @@ -107,13 +108,13 @@ public void testSaveUsingPut() { verify(mockDynamo).putItem(putItemRequestCaptor.capture()); PutItemRequest putItemRequest = putItemRequestCaptor.getValue(); - assertEquals(ITEM_MAP, putItemRequest.getItem()); + assertEquals(ITEM_MAP, putItemRequest.item()); } @Test public void testSaveUsingUpdate() { when(mockDynamo.updateItem(any(UpdateItemRequest.class))) - .thenReturn(new UpdateItemResult().withAttributes(ITEM_MAP)); + .thenReturn(UpdateItemResponse.builder().attributes(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); dynamoDBMapper.save(TEST_OBJECT, DynamoDBMapperConfig.builder() @@ -122,10 +123,10 @@ public void testSaveUsingUpdate() { verify(mockDynamo).updateItem(updateItemRequestArgumentCaptor.capture()); UpdateItemRequest updateItemRequest = updateItemRequestArgumentCaptor.getValue(); - assertEquals(KEY_MAP, updateItemRequest.getKey()); - Map updates = updateItemRequest.getAttributeUpdates(); + assertEquals(KEY_MAP, updateItemRequest.key()); + Map updates = updateItemRequest.attributeUpdates(); AttributeValueUpdate attributeValueUpdate = updates.get(BINARY_ATTRIBUTE); - assertEquals(EMPTY_BINARY_AV, attributeValueUpdate.getValue()); - assertEquals("PUT", attributeValueUpdate.getAction()); + assertEquals(EMPTY_BINARY_AV, attributeValueUpdate.value()); + assertEquals("PUT", attributeValueUpdate.actionAsString()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteArrayAttributesTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteArrayAttributesTest.java index 863744065b3d..0ca9bf538c6f 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteArrayAttributesTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteArrayAttributesTest.java @@ -14,27 +14,28 @@ */ package software.amazon.awssdk.mapper.dynamodb.mapper; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.nio.ByteBuffer; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteArrayClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -54,7 +55,7 @@ public class EmptyBinarySetByteArrayAttributesTest { private static final String KEY_VALUE = "test-id"; private static final byte[] EMPTY_BINARY = new byte[]{}; private static final Set EMPTY_BINARY_SET; - private static final AttributeValue EMPTY_BINARY_SET_AV = new AttributeValue().withBS(ByteBuffer.wrap(EMPTY_BINARY)); + private static final AttributeValue EMPTY_BINARY_SET_AV = AttributeValue.builder().bs(SdkBytes.fromByteArray(EMPTY_BINARY)).build(); private static final Map ITEM_MAP; private static final Map KEY_MAP; @@ -65,10 +66,10 @@ public class EmptyBinarySetByteArrayAttributesTest { EMPTY_BINARY_SET.add(EMPTY_BINARY); KEY_MAP = new HashMap<>(); - KEY_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + KEY_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP = new HashMap<>(); - ITEM_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + ITEM_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP.put(BINARY_SET_ATTRIBUTE, EMPTY_BINARY_SET_AV); TEST_OBJECT = new BinaryAttributeByteArrayClass(); @@ -77,7 +78,7 @@ public class EmptyBinarySetByteArrayAttributesTest { } @Mock - private AmazonDynamoDB mockDynamo; + private DynamoDbClient mockDynamo; @Captor private ArgumentCaptor getItemRequestCaptor; @@ -90,17 +91,21 @@ public class EmptyBinarySetByteArrayAttributesTest { @Test public void testLoad() { - when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(new GetItemResult().withItem(ITEM_MAP)); + when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(GetItemResponse.builder().item(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); BinaryAttributeByteArrayClass x = dynamoDBMapper.load(BinaryAttributeByteArrayClass.class, - ITEM_MAP.get(KEY_NAME).getS()); - assertEquals(ITEM_MAP.get(KEY_NAME).getS(), x.getKey()); - assertEquals(EMPTY_BINARY_SET, x.getBinarySetAttribute()); + ITEM_MAP.get(KEY_NAME).s()); + assertEquals(ITEM_MAP.get(KEY_NAME).s(), x.getKey()); + // v2 SdkBytes.asByteArray() returns a defensive copy, so Set equality (which compares byte[] + // elements by identity) would fail; compare the single element by content instead. + Set loadedSet = x.getBinarySetAttribute(); + assertEquals(EMPTY_BINARY_SET.size(), loadedSet.size()); + assertArrayEquals(EMPTY_BINARY_SET.iterator().next(), loadedSet.iterator().next()); verify(mockDynamo).getItem(getItemRequestCaptor.capture()); GetItemRequest getItemRequest = getItemRequestCaptor.getValue(); - assertEquals(KEY_MAP, getItemRequest.getKey()); + assertEquals(KEY_MAP, getItemRequest.key()); } @Test @@ -113,13 +118,13 @@ public void testSaveUsingPut() { verify(mockDynamo).putItem(putItemRequestCaptor.capture()); PutItemRequest putItemRequest = putItemRequestCaptor.getValue(); - assertEquals(ITEM_MAP, putItemRequest.getItem()); + assertEquals(ITEM_MAP, putItemRequest.item()); } @Test public void testSaveUsingUpdate() { when(mockDynamo.updateItem(any(UpdateItemRequest.class))) - .thenReturn(new UpdateItemResult().withAttributes(ITEM_MAP)); + .thenReturn(UpdateItemResponse.builder().attributes(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); dynamoDBMapper.save(TEST_OBJECT, DynamoDBMapperConfig.builder() @@ -128,10 +133,10 @@ public void testSaveUsingUpdate() { verify(mockDynamo).updateItem(updateItemRequestArgumentCaptor.capture()); UpdateItemRequest updateItemRequest = updateItemRequestArgumentCaptor.getValue(); - assertEquals(KEY_MAP, updateItemRequest.getKey()); - Map updates = updateItemRequest.getAttributeUpdates(); + assertEquals(KEY_MAP, updateItemRequest.key()); + Map updates = updateItemRequest.attributeUpdates(); AttributeValueUpdate attributeValueUpdate = updates.get(BINARY_SET_ATTRIBUTE); - assertEquals(EMPTY_BINARY_SET_AV, attributeValueUpdate.getValue()); - assertEquals("PUT", attributeValueUpdate.getAction()); + assertEquals(EMPTY_BINARY_SET_AV, attributeValueUpdate.value()); + assertEquals("PUT", attributeValueUpdate.actionAsString()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteBufferAttributesTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteBufferAttributesTest.java index 5b0c19c8b995..36c724d53c33 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteBufferAttributesTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/EmptyBinarySetByteBufferAttributesTest.java @@ -25,16 +25,17 @@ import java.util.Map; import java.util.Set; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.AttributeValueUpdate; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; import software.amazon.awssdk.mapper.dynamodb.pojos.BinaryAttributeByteBufferClass; import org.junit.Test; import org.junit.runner.RunWith; @@ -54,7 +55,7 @@ public class EmptyBinarySetByteBufferAttributesTest { private static final String KEY_VALUE = "test-id"; private static final ByteBuffer EMPTY_BINARY = ByteBuffer.wrap(new byte[]{}); private static final Set EMPTY_BINARY_SET; - private static final AttributeValue EMPTY_BINARY_SET_AV = new AttributeValue().withBS(EMPTY_BINARY); + private static final AttributeValue EMPTY_BINARY_SET_AV = AttributeValue.builder().bs(SdkBytes.fromByteBuffer(EMPTY_BINARY)).build(); private static final Map ITEM_MAP; private static final Map KEY_MAP; @@ -65,10 +66,10 @@ public class EmptyBinarySetByteBufferAttributesTest { EMPTY_BINARY_SET.add(EMPTY_BINARY); KEY_MAP = new HashMap<>(); - KEY_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + KEY_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP = new HashMap<>(); - ITEM_MAP.put(KEY_NAME, new AttributeValue().withS(KEY_VALUE)); + ITEM_MAP.put(KEY_NAME, AttributeValue.builder().s(KEY_VALUE).build()); ITEM_MAP.put(BINARY_SET_ATTRIBUTE, EMPTY_BINARY_SET_AV); TEST_OBJECT = new BinaryAttributeByteBufferClass(); @@ -77,7 +78,7 @@ public class EmptyBinarySetByteBufferAttributesTest { } @Mock - private AmazonDynamoDB mockDynamo; + private DynamoDbClient mockDynamo; @Captor private ArgumentCaptor getItemRequestCaptor; @@ -90,17 +91,17 @@ public class EmptyBinarySetByteBufferAttributesTest { @Test public void testLoad() { - when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(new GetItemResult().withItem(ITEM_MAP)); + when(mockDynamo.getItem(any(GetItemRequest.class))).thenReturn(GetItemResponse.builder().item(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); BinaryAttributeByteBufferClass x = dynamoDBMapper.load(BinaryAttributeByteBufferClass.class, - ITEM_MAP.get(KEY_NAME).getS()); - assertEquals(ITEM_MAP.get(KEY_NAME).getS(), x.getKey()); + ITEM_MAP.get(KEY_NAME).s()); + assertEquals(ITEM_MAP.get(KEY_NAME).s(), x.getKey()); assertEquals(EMPTY_BINARY_SET, x.getBinarySetAttribute()); verify(mockDynamo).getItem(getItemRequestCaptor.capture()); GetItemRequest getItemRequest = getItemRequestCaptor.getValue(); - assertEquals(KEY_MAP, getItemRequest.getKey()); + assertEquals(KEY_MAP, getItemRequest.key()); } @Test @@ -113,13 +114,13 @@ public void testSaveUsingPut() { verify(mockDynamo).putItem(putItemRequestCaptor.capture()); PutItemRequest putItemRequest = putItemRequestCaptor.getValue(); - assertEquals(ITEM_MAP, putItemRequest.getItem()); + assertEquals(ITEM_MAP, putItemRequest.item()); } @Test public void testSaveUsingUpdate() { when(mockDynamo.updateItem(any(UpdateItemRequest.class))) - .thenReturn(new UpdateItemResult().withAttributes(ITEM_MAP)); + .thenReturn(UpdateItemResponse.builder().attributes(ITEM_MAP).build()); DynamoDBMapper dynamoDBMapper = new DynamoDBMapper(mockDynamo); dynamoDBMapper.save(TEST_OBJECT, DynamoDBMapperConfig.builder() @@ -128,10 +129,10 @@ public void testSaveUsingUpdate() { verify(mockDynamo).updateItem(updateItemRequestArgumentCaptor.capture()); UpdateItemRequest updateItemRequest = updateItemRequestArgumentCaptor.getValue(); - assertEquals(KEY_MAP, updateItemRequest.getKey()); - Map updates = updateItemRequest.getAttributeUpdates(); + assertEquals(KEY_MAP, updateItemRequest.key()); + Map updates = updateItemRequest.attributeUpdates(); AttributeValueUpdate attributeValueUpdate = updates.get(BINARY_SET_ATTRIBUTE); - assertEquals(EMPTY_BINARY_SET_AV, attributeValueUpdate.getValue()); - assertEquals("PUT", attributeValueUpdate.getAction()); + assertEquals(EMPTY_BINARY_SET_AV, attributeValueUpdate.value()); + assertEquals("PUT", attributeValueUpdate.actionAsString()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ExceptionHandlingIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ExceptionHandlingIntegrationTest.java index da7917d3e04f..574d67b5d658 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ExceptionHandlingIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ExceptionHandlingIntegrationTest.java @@ -31,8 +31,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBRangeKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBVersionAttribute; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; /** * Tests of exception handling @@ -182,8 +182,8 @@ public void testPrivateKeySetter() throws Exception { @Test(expected = DynamoDBMappingException.class) public void testPrivateKeySetterLoad() throws Exception { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withS("abc")); - dynamo.putItem(new PutItemRequest().withTableName("aws-java-sdk-util").withItem(attr)); + attr.put(KEY_NAME, AttributeValue.builder().s("abc").build()); + dynamo.putItem(PutItemRequest.builder().tableName("aws-java-sdk-util").item(attr).build()); DynamoDBMapper util = new DynamoDBMapper(dynamo); util.load(PrivateKeySetter.class, "abc"); } @@ -320,21 +320,21 @@ public void setIntegerProperty(Integer integerProperty) { @Test(expected = DynamoDBMappingException.class) public void testWrongDataType() { Map attr = new HashMap(); - attr.put("integerProperty", new AttributeValue().withS("abc")); - attr.put(KEY_NAME, new AttributeValue().withS("" + startKey++)); - dynamo.putItem(new PutItemRequest().withTableName("aws-java-sdk-util").withItem(attr)); + attr.put("integerProperty", AttributeValue.builder().s("abc").build()); + attr.put(KEY_NAME, AttributeValue.builder().s("" + startKey++).build()); + dynamo.putItem(PutItemRequest.builder().tableName("aws-java-sdk-util").item(attr).build()); DynamoDBMapper util = new DynamoDBMapper(dynamo); - util.load(NumericFields.class, attr.get(KEY_NAME).getS()); + util.load(NumericFields.class, attr.get(KEY_NAME).s()); } @Test(expected = DynamoDBMappingException.class) public void testWrongDataType2() { Map attr = new HashMap(); - attr.put("integerProperty", new AttributeValue().withNS("1", "2", "3")); - attr.put(KEY_NAME, new AttributeValue().withS("" + startKey++)); - dynamo.putItem(new PutItemRequest().withTableName("aws-java-sdk-util").withItem(attr)); + attr.put("integerProperty", AttributeValue.builder().ns("1", "2", "3").build()); + attr.put(KEY_NAME, AttributeValue.builder().s("" + startKey++).build()); + dynamo.putItem(PutItemRequest.builder().tableName("aws-java-sdk-util").item(attr).build()); DynamoDBMapper util = new DynamoDBMapper(dynamo); - util.load(NumericFields.class, attr.get(KEY_NAME).getS()); + util.load(NumericFields.class, attr.get(KEY_NAME).s()); } @DynamoDBTable(tableName = "aws-java-sdk-util") diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/IndexRangeKeyAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/IndexRangeKeyAttributesIntegrationTest.java index 580304e50e9a..cdf203c8744e 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/IndexRangeKeyAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/IndexRangeKeyAttributesIntegrationTest.java @@ -36,10 +36,10 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.ConsistentReads; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMappingException; import software.amazon.awssdk.mapper.dynamodb.DynamoDBQueryExpression; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; /** * Tests that index range keys are properly handled as common attribute @@ -75,17 +75,17 @@ public class IndexRangeKeyAttributesIntegrationTest extends DynamoDBMapperIntegr hashKeyValues.add(hashKeyValue); for (int j = 0; j< rangePerHash; j++) { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withN("" + hashKeyValue)); - attr.put(RANGE_KEY, new AttributeValue().withN("" + j)); + attr.put(KEY_NAME, AttributeValue.builder().n("" + hashKeyValue).build()); + attr.put(RANGE_KEY, AttributeValue.builder().n("" + j).build()); if ( j % indexFooRangeStep == 0) - attr.put(INDEX_FOO_RANGE_KEY, new AttributeValue().withN("" + j)); + attr.put(INDEX_FOO_RANGE_KEY, AttributeValue.builder().n("" + j).build()); if ( j % indexBarRangeStep == 0) - attr.put(INDEX_BAR_RANGE_KEY, new AttributeValue().withN("" + j)); + attr.put(INDEX_BAR_RANGE_KEY, AttributeValue.builder().n("" + j).build()); if ( j % multipleIndexRangeStep == 0) - attr.put(MULTIPLE_INDEX_RANGE_KEY, new AttributeValue().withN("" + j)); - attr.put(FOO_ATTRIBUTE, new AttributeValue().withS(UUID.randomUUID().toString())); - attr.put(BAR_ATTRIBUTE, new AttributeValue().withS(UUID.randomUUID().toString())); - attr.put(VERSION_ATTRIBUTE, new AttributeValue().withN("1")); + attr.put(MULTIPLE_INDEX_RANGE_KEY, AttributeValue.builder().n("" + j).build()); + attr.put(FOO_ATTRIBUTE, AttributeValue.builder().s(UUID.randomUUID().toString()).build()); + attr.put(BAR_ATTRIBUTE, AttributeValue.builder().s(UUID.randomUUID().toString()).build()); + attr.put(VERSION_ATTRIBUTE, AttributeValue.builder().n("1").build()); attrs.add(attr); } @@ -99,7 +99,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_WITH_INDEX_RANGE_ATTRIBUTE, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_WITH_INDEX_RANGE_ATTRIBUTE).item(attr).build()); } mapper = new DynamoDBMapper(dynamo, @@ -112,24 +112,24 @@ public static void setUp() throws Exception { @Test public void testLoad() throws Exception { for ( Map attr : attrs ) { - IndexRangeKeyClass x = mapper.load(newIndexRangeKey(Long.parseLong(attr.get(KEY_NAME).getN()), - Double.parseDouble(attr.get(RANGE_KEY).getN()))); + IndexRangeKeyClass x = mapper.load(newIndexRangeKey(Long.parseLong(attr.get(KEY_NAME).n()), + Double.parseDouble(attr.get(RANGE_KEY).n()))); // Convert all numbers to the most inclusive type for easy // comparison - assertEquals(new BigDecimal(x.getKey()), new BigDecimal(attr.get(KEY_NAME).getN())); - assertEquals(new BigDecimal(x.getRangeKey()), new BigDecimal(attr.get(RANGE_KEY).getN())); + assertEquals(new BigDecimal(x.getKey()), new BigDecimal(attr.get(KEY_NAME).n())); + assertEquals(new BigDecimal(x.getRangeKey()), new BigDecimal(attr.get(RANGE_KEY).n())); if (null == attr.get(INDEX_FOO_RANGE_KEY)) assertNull(x.getIndexFooRangeKeyWithFakeName()); else - assertEquals(new BigDecimal(x.getIndexFooRangeKeyWithFakeName()), new BigDecimal(attr.get(INDEX_FOO_RANGE_KEY).getN())); + assertEquals(new BigDecimal(x.getIndexFooRangeKeyWithFakeName()), new BigDecimal(attr.get(INDEX_FOO_RANGE_KEY).n())); if (null == attr.get(INDEX_BAR_RANGE_KEY)) assertNull(x.getIndexBarRangeKey()); else - assertEquals(new BigDecimal(x.getIndexBarRangeKey()), new BigDecimal(attr.get(INDEX_BAR_RANGE_KEY).getN())); - assertEquals(new BigDecimal(x.getVersion()), new BigDecimal(attr.get(VERSION_ATTRIBUTE).getN())); - assertEquals(x.getFooAttribute(), attr.get(FOO_ATTRIBUTE).getS()); - assertEquals(x.getBarAttribute(), attr.get(BAR_ATTRIBUTE).getS()); + assertEquals(new BigDecimal(x.getIndexBarRangeKey()), new BigDecimal(attr.get(INDEX_BAR_RANGE_KEY).n())); + assertEquals(new BigDecimal(x.getVersion()), new BigDecimal(attr.get(VERSION_ATTRIBUTE).n())); + assertEquals(x.getFooAttribute(), attr.get(FOO_ATTRIBUTE).s()); + assertEquals(x.getBarAttribute(), attr.get(BAR_ATTRIBUTE).s()); } } @@ -215,9 +215,9 @@ public void testQueryWithIndexRangekey() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString()))); + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build())); assertTrue(rangePerHash == result.size()); // check that all attributes are retrieved for (IndexRangeKeyClass itemInFooIndex : result) { @@ -232,9 +232,9 @@ public void testQueryWithIndexRangekey() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(INDEX_FOO_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString()))); + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build())); assertTrue(indexFooRangePerHash == result.size()); // check that only the projected attributes are retrieved for (IndexRangeKeyClass itemInFooIndex : result) { @@ -249,9 +249,9 @@ public void testQueryWithIndexRangekey() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(INDEX_BAR_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString()))); + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build())); assertTrue(indexBarRangePerHash == result.size()); // check that only the projected attributes are retrieved for (IndexRangeKeyClass itemInBarIndex : result) { @@ -273,9 +273,9 @@ public void testInvalidRangeKeyNameException() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition("some_range_key", - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString()))); + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build())); fail("some_range_key is not a valid range key name."); } catch (DynamoDBMappingException e) { System.out.println(e.getMessage()); @@ -296,9 +296,9 @@ public void testInvalidIndexNameException() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(INDEX_BAR_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString())) + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build()) .withIndexName("some_index")); fail("some_index is not a valid index name."); } catch (IllegalArgumentException iae) { @@ -325,9 +325,9 @@ public void testQueryWithRangeKeyForMultipleIndexes() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(MULTIPLE_INDEX_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString())) + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build()) .withIndexName("index_foo_copy")); assertTrue(multipleIndexRangePerHash == result.size()); // check that only the projected attributes are retrieved @@ -339,9 +339,9 @@ public void testQueryWithRangeKeyForMultipleIndexes() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(MULTIPLE_INDEX_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString())) + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build()) .withIndexName("index_bar_copy")); assertTrue(multipleIndexRangePerHash == result.size()); // check that only the projected attributes are retrieved @@ -358,9 +358,9 @@ public void testQueryWithRangeKeyForMultipleIndexes() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(MULTIPLE_INDEX_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString()))); + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build())); fail("No index name is specified when query with a range key shared by multiple indexes"); } catch (IllegalArgumentException iae) { System.out.println(iae.getMessage()); @@ -376,9 +376,9 @@ public void testQueryWithRangeKeyForMultipleIndexes() { new DynamoDBQueryExpression() .withHashKeyValues(hashKeyItem) .withRangeKeyCondition(MULTIPLE_INDEX_RANGE_KEY, - new Condition() - .withAttributeValueList(new AttributeValue().withN("0")) - .withComparisonOperator(ComparisonOperator.GE.toString())) + Condition.builder() + .attributeValueList(AttributeValue.builder().n("0").build()) + .comparisonOperator(ComparisonOperator.GE.toString()).build()) .withIndexName("index_foo")); fail("index_foo is not annotated as part of the localSecondaryIndexNames in " + "the @DynamoDBIndexRangeKey annotation of multipleIndexRangeKey"); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/KeyOnlyPutIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/KeyOnlyPutIntegrationTest.java index 476d0ccd1e9e..e76c1e5f2880 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/KeyOnlyPutIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/KeyOnlyPutIntegrationTest.java @@ -17,9 +17,9 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBSaveExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; public class KeyOnlyPutIntegrationTest extends DynamoDBIntegrationTestBase { @DynamoDBTable(tableName = "aws-java-sdk-util") @@ -108,10 +108,10 @@ public void testKeyOnlyPut() throws Exception { try { DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); Map expected = new HashMap(); - ExpectedAttributeValue expectedVersion = new ExpectedAttributeValue() - .withValue(new AttributeValue() - .withS("SomeNonExistantValue")) - .withExists(true); + ExpectedAttributeValue expectedVersion = ExpectedAttributeValue.builder() + .value(AttributeValue.builder() + .s("SomeNonExistantValue").build()) + .exists(true).build(); expected.put("normalStringAttribute", expectedVersion); saveExpression.setExpected(expected); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperQueryExpressionTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperQueryExpressionTest.java index 65da9fa4a6e5..b5952aaedd7b 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperQueryExpressionTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperQueryExpressionTest.java @@ -1,21 +1,25 @@ package software.amazon.awssdk.mapper.dynamodb.mapper; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Collections; -import java.util.List; +import java.util.HashMap; import java.util.Map; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.ArgumentCaptor; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import software.amazon.awssdk.mapper.dynamodb.DynamoDBRangeKey; -import com.amazonaws.services.dynamodbv2.AbstractAmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBIndexHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBIndexRangeKey; @@ -23,13 +27,11 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; import software.amazon.awssdk.mapper.dynamodb.DynamoDBQueryExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex; -import com.amazonaws.services.dynamodbv2.model.QueryRequest; -import com.amazonaws.services.dynamodbv2.model.QueryResult; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.QueryRequest; +import software.amazon.awssdk.services.dynamodb.model.QueryResponse; /** @@ -38,31 +40,20 @@ public class MapperQueryExpressionTest { private static final String TABLE_NAME = "table_name"; - private static final Condition RANGE_KEY_CONDITION = new Condition() - .withAttributeValueList(new AttributeValue("some value")) - .withComparisonOperator(ComparisonOperator.EQ); + private static final Condition RANGE_KEY_CONDITION = Condition.builder() + .attributeValueList(AttributeValue.builder().s("some value").build()) + .comparisonOperator(ComparisonOperator.EQ) + .build(); - private static CaptureDynamoDB capture; + private static DynamoDbClient mockDynamoDb; private static DynamoDBMapper mapper; - private static final class CaptureDynamoDB extends AbstractAmazonDynamoDB { - private QueryRequest request; - private QueryResult result; - private CaptureDynamoDB(final List> items) { - this.result = new QueryResult(); - this.result.setItems(items); - } - @Override - public QueryResult query(QueryRequest request) { - this.request = request; - return this.result; - } - } - @BeforeClass - public static void setUp() throws SecurityException, NoSuchMethodException { - capture = new CaptureDynamoDB(Collections.>emptyList()); - mapper = new DynamoDBMapper(capture); + public static void setUp() { + mockDynamoDb = mock(DynamoDbClient.class); + when(mockDynamoDb.query(any(QueryRequest.class))) + .thenReturn(QueryResponse.builder().items(Collections.emptyList()).build()); + mapper = new DynamoDBMapper(mockDynamoDb); } @DynamoDBTable(tableName = TABLE_NAME) @@ -123,13 +114,12 @@ public void testHashConditionOnly() { HashOnlyClass.class, new DynamoDBQueryExpression() .withHashKeyValues(new HashOnlyClass("foo", null, null))); - assertTrue(queryRequest.getKeyConditions().size() == 1); - assertEquals("primaryHashKey", queryRequest.getKeyConditions().keySet().iterator().next()); + assertTrue(queryRequest.keyConditions().size() == 1); + assertEquals("primaryHashKey", queryRequest.keyConditions().keySet().iterator().next()); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertNull(queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertNull(queryRequest.indexName()); // Primary hash used for a GSI queryRequest = testCreateQueryRequestFromExpression( @@ -137,26 +127,24 @@ public void testHashConditionOnly() { new DynamoDBQueryExpression() .withHashKeyValues(new HashOnlyClass("foo", null, null)) .withIndexName("GSI-primary-hash")); - assertTrue(queryRequest.getKeyConditions().size() == 1); - assertEquals("primaryHashKey", queryRequest.getKeyConditions().keySet().iterator().next()); + assertTrue(queryRequest.keyConditions().size() == 1); + assertEquals("primaryHashKey", queryRequest.keyConditions().keySet().iterator().next()); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertEquals("GSI-primary-hash", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertEquals("GSI-primary-hash", queryRequest.indexName()); // Primary hash query takes higher priority then index hash query queryRequest = testCreateQueryRequestFromExpression( HashOnlyClass.class, new DynamoDBQueryExpression() .withHashKeyValues(new HashOnlyClass("foo", "bar", null))); - assertTrue(queryRequest.getKeyConditions().size() == 1); - assertEquals("primaryHashKey", queryRequest.getKeyConditions().keySet().iterator().next()); + assertTrue(queryRequest.keyConditions().size() == 1); + assertEquals("primaryHashKey", queryRequest.keyConditions().keySet().iterator().next()); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertNull(queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertNull(queryRequest.indexName()); // Ambiguous query on multiple index hash keys queryRequest = testCreateQueryRequestFromExpression( @@ -178,13 +166,12 @@ public void testHashConditionOnly() { new DynamoDBQueryExpression() .withHashKeyValues(new HashOnlyClass("foo", "bar", null)) .withIndexName("GSI-index-hash-1")); - assertTrue(queryRequest.getKeyConditions().size() == 1); - assertEquals("indexHashKey", queryRequest.getKeyConditions().keySet().iterator().next()); + assertTrue(queryRequest.keyConditions().size() == 1); + assertEquals("indexHashKey", queryRequest.keyConditions().keySet().iterator().next()); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("bar")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("indexHashKey")); - assertEquals("GSI-index-hash-1", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("bar").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("indexHashKey")); + assertEquals("GSI-index-hash-1", queryRequest.indexName()); // Non-existent GSI queryRequest = testCreateQueryRequestFromExpression( @@ -293,15 +280,14 @@ public void testHashAndRangeCondition() { new DynamoDBQueryExpression() .withHashKeyValues(new HashRangeClass("foo", null)) .withRangeKeyCondition("primaryRangeKey", RANGE_KEY_CONDITION)); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryRangeKey")); - assertEquals(RANGE_KEY_CONDITION, queryRequest.getKeyConditions().get("primaryRangeKey")); - assertNull(queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("primaryRangeKey")); + assertEquals(RANGE_KEY_CONDITION, queryRequest.keyConditions().get("primaryRangeKey")); + assertNull(queryRequest.indexName()); // Primary hash + primary range on a LSI queryRequest = testCreateQueryRequestFromExpression( @@ -310,15 +296,14 @@ public void testHashAndRangeCondition() { .withHashKeyValues(new HashRangeClass("foo", null)) .withRangeKeyCondition("primaryRangeKey", RANGE_KEY_CONDITION) .withIndexName("LSI-primary-range")); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryRangeKey")); - assertEquals(RANGE_KEY_CONDITION, queryRequest.getKeyConditions().get("primaryRangeKey")); - assertEquals("LSI-primary-range", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("primaryRangeKey")); + assertEquals(RANGE_KEY_CONDITION, queryRequest.keyConditions().get("primaryRangeKey")); + assertEquals("LSI-primary-range", queryRequest.indexName()); // Primary hash + index range used by multiple LSI. But also a GSI hash + range queryRequest = testCreateQueryRequestFromExpression( @@ -326,15 +311,14 @@ public void testHashAndRangeCondition() { new DynamoDBQueryExpression() .withHashKeyValues(new HashRangeClass("foo", null)) .withRangeKeyCondition("indexRangeKey", RANGE_KEY_CONDITION)); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("indexRangeKey")); - assertEquals(RANGE_KEY_CONDITION, queryRequest.getKeyConditions().get("indexRangeKey")); - assertEquals("GSI-primary-hash-index-range-1", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("indexRangeKey")); + assertEquals(RANGE_KEY_CONDITION, queryRequest.keyConditions().get("indexRangeKey")); + assertEquals("GSI-primary-hash-index-range-1", queryRequest.indexName()); // Primary hash + index range on a LSI @@ -344,15 +328,14 @@ public void testHashAndRangeCondition() { .withHashKeyValues(new HashRangeClass("foo", null)) .withRangeKeyCondition("indexRangeKey", RANGE_KEY_CONDITION) .withIndexName("LSI-index-range-1")); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("primaryHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("indexRangeKey")); - assertEquals(RANGE_KEY_CONDITION, queryRequest.getKeyConditions().get("indexRangeKey")); - assertEquals("LSI-index-range-1", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("primaryHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("indexRangeKey")); + assertEquals(RANGE_KEY_CONDITION, queryRequest.keyConditions().get("indexRangeKey")); + assertEquals("LSI-index-range-1", queryRequest.indexName()); // Non-existent LSI queryRequest = testCreateQueryRequestFromExpression( @@ -378,15 +361,14 @@ public void testHashAndRangeCondition() { new DynamoDBQueryExpression() .withHashKeyValues(new HashRangeClass(null, "foo")) .withRangeKeyCondition("primaryRangeKey", RANGE_KEY_CONDITION)); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("indexHashKey")); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("indexHashKey")); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("indexHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryRangeKey")); - assertEquals(RANGE_KEY_CONDITION, queryRequest.getKeyConditions().get("primaryRangeKey")); - assertEquals("GSI-index-hash-primary-range", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("indexHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("primaryRangeKey")); + assertEquals(RANGE_KEY_CONDITION, queryRequest.keyConditions().get("primaryRangeKey")); + assertEquals("GSI-index-hash-primary-range", queryRequest.indexName()); // Ambiguous query: GSI hash + index range used by multiple GSIs queryRequest = testCreateQueryRequestFromExpression( @@ -403,15 +385,14 @@ public void testHashAndRangeCondition() { .withHashKeyValues(new HashRangeClass(null, "foo")) .withRangeKeyCondition("indexRangeKey", RANGE_KEY_CONDITION) .withIndexName("GSI-index-hash-index-range-2")); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("indexHashKey")); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("indexHashKey")); assertEquals( - new Condition().withAttributeValueList(new AttributeValue("foo")) - .withComparisonOperator(ComparisonOperator.EQ), - queryRequest.getKeyConditions().get("indexHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("indexRangeKey")); - assertEquals(RANGE_KEY_CONDITION, queryRequest.getKeyConditions().get("indexRangeKey")); - assertEquals("GSI-index-hash-index-range-2", queryRequest.getIndexName()); + Condition.builder().attributeValueList(AttributeValue.builder().s("foo").build()).comparisonOperator(ComparisonOperator.EQ).build(), + queryRequest.keyConditions().get("indexHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("indexRangeKey")); + assertEquals(RANGE_KEY_CONDITION, queryRequest.keyConditions().get("indexRangeKey")); + assertEquals("GSI-index-hash-index-range-2", queryRequest.indexName()); // Ambiguous query: (1) primary hash + LSI range OR (2) GSI hash + range queryRequest = testCreateQueryRequestFromExpression( @@ -422,14 +403,14 @@ public void testHashAndRangeCondition() { "Ambiguous query expression: Found multiple valid queries:"); // Multiple range key conditions specified + Map multipleRangeKeyConditions = new HashMap<>(); + multipleRangeKeyConditions.put("primaryRangeKey", RANGE_KEY_CONDITION); + multipleRangeKeyConditions.put("indexRangeKey", RANGE_KEY_CONDITION); queryRequest = testCreateQueryRequestFromExpression( HashRangeClass.class, new DynamoDBQueryExpression() .withHashKeyValues(new HashRangeClass("foo", null)) - .withRangeKeyConditions( - ImmutableMapParameter.of( - "primaryRangeKey", RANGE_KEY_CONDITION, - "indexRangeKey", RANGE_KEY_CONDITION)), + .withRangeKeyConditions(multipleRangeKeyConditions), "Illegal query expression: Conditions on multiple range keys"); // Using an un-annotated range key @@ -485,9 +466,9 @@ public void testHashOnlyQueryOnHashRangeTable() { LSIRangeKeyClass.class, new DynamoDBQueryExpression() .withHashKeyValues(new LSIRangeKeyClass("foo", null))); - assertTrue(queryRequest.getKeyConditions().size() == 1); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); - assertNull(queryRequest.getIndexName()); + assertTrue(queryRequest.keyConditions().size() == 1); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); + assertNull(queryRequest.indexName()); // Hash+Range query on a LSI queryRequest = testCreateQueryRequestFromExpression( @@ -496,10 +477,10 @@ public void testHashOnlyQueryOnHashRangeTable() { .withHashKeyValues(new LSIRangeKeyClass("foo", null)) .withRangeKeyCondition("lsiRangeKey", RANGE_KEY_CONDITION) .withIndexName("LSI")); - assertTrue(queryRequest.getKeyConditions().size() == 2); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); - assertTrue(queryRequest.getKeyConditions().containsKey("lsiRangeKey")); - assertEquals("LSI", queryRequest.getIndexName()); + assertTrue(queryRequest.keyConditions().size() == 2); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); + assertTrue(queryRequest.keyConditions().containsKey("lsiRangeKey")); + assertEquals("LSI", queryRequest.indexName()); // Hash-only query on a LSI queryRequest = testCreateQueryRequestFromExpression( @@ -507,9 +488,9 @@ public void testHashOnlyQueryOnHashRangeTable() { new DynamoDBQueryExpression() .withHashKeyValues(new LSIRangeKeyClass("foo", null)) .withIndexName("LSI")); - assertTrue(queryRequest.getKeyConditions().size() == 1); - assertTrue(queryRequest.getKeyConditions().containsKey("primaryHashKey")); - assertEquals("LSI", queryRequest.getIndexName()); + assertTrue(queryRequest.keyConditions().size() == 1); + assertTrue(queryRequest.keyConditions().containsKey("primaryHashKey")); + assertEquals("LSI", queryRequest.indexName()); } private static QueryRequest testCreateQueryRequestFromExpression( @@ -526,7 +507,9 @@ private static QueryRequest testCreateQueryRequestFromExpression( fail("Exception containing messsage (" + expectedErrorMessage + ") is expected."); } - return capture.request; + ArgumentCaptor captor = ArgumentCaptor.forClass(QueryRequest.class); + verify(mockDynamoDb, atLeastOnce()).query(captor.capture()); + return captor.getValue(); } catch (RuntimeException e) { if (expectedErrorMessage != null && e.getMessage() != null) { assertTrue("Exception message [" + e.getMessage() + "] does not contain " + diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigIntegrationTest.java index b0a3d89e3682..3f6e90a5248d 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigIntegrationTest.java @@ -6,11 +6,10 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; -import com.amazonaws.util.ImmutableMapParameter; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -20,9 +19,9 @@ import org.junit.AfterClass; import org.junit.Test; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; /** * Tests the behavior of save method of DynamoDBMapper under different @@ -373,8 +372,8 @@ public void testAppendSetWithKeyAndNonKeyAttributesSpecifiedRecordInTable() try { dynamoMapper.save(testAppendToScalarItem, appendSetConfig); fail("Should have thrown a 'Type mismatch' service exception."); - } catch (AmazonServiceException ase) { - assertEquals("ValidationException", ase.getErrorCode()); + } catch (AwsServiceException ase) { + assertEquals("ValidationException", ase.awsErrorDetails().errorCode()); } } @@ -497,14 +496,14 @@ public void testClobberWithVersion_SucceedsEvenWhenVersionDoesNotMatch() throws dynamoMapper.save(testItem, clobberConfig); - GetItemResult item = rawGetItem(testItem); - Map expected = ImmutableMapParameter.of( - hashKeyName, new AttributeValue(testItem.getHashKey()), - rangeKeyName, new AttributeValue().withN(testItem.getRangeKey().toString()), - nonKeyAttributeName, new AttributeValue(testItem.getNonKeyAttribute()), - versionAttributeName, new AttributeValue().withN(Long.toString(2L))); + GetItemResponse item = rawGetItem(testItem); + Map expected = new HashMap(); + expected.put(hashKeyName, AttributeValue.builder().s(testItem.getHashKey()).build()); + expected.put(rangeKeyName, AttributeValue.builder().n(testItem.getRangeKey().toString()).build()); + expected.put(nonKeyAttributeName, AttributeValue.builder().s(testItem.getNonKeyAttribute()).build()); + expected.put(versionAttributeName, AttributeValue.builder().n(Long.toString(2L)).build()); - assertEquals(expected, item.getItem()); + assertEquals(expected, item.item()); } /** @@ -520,12 +519,12 @@ public void testPutWithOnlyKeyAttributesSpecifiedRecordInTable() testItem.setNonKeyAttribute(null); dynamoMapper.save(testItem, putConfig); - GetItemResult item = rawGetItem(testItem); - Map expected = ImmutableMapParameter.of( - hashKeyName, new AttributeValue(testItem.getHashKey()), - rangeKeyName, new AttributeValue().withN(testItem.getRangeKey().toString())); + GetItemResponse item = rawGetItem(testItem); + Map expected = new HashMap(); + expected.put(hashKeyName, AttributeValue.builder().s(testItem.getHashKey()).build()); + expected.put(rangeKeyName, AttributeValue.builder().n(testItem.getRangeKey().toString()).build()); - assertEquals(expected, item.getItem()); + assertEquals(expected, item.item()); } @Test @@ -537,13 +536,13 @@ public void testPutWithKeyAndNonKeyAttributesSpecifiedRecordInTable() throws Exc testItem.setNonKeyAttribute("not foo"); dynamoMapper.save(testItem, putConfig); - GetItemResult item = rawGetItem(testItem); - Map expected = ImmutableMapParameter.of( - hashKeyName, new AttributeValue(testItem.getHashKey()), - rangeKeyName, new AttributeValue().withN(testItem.getRangeKey().toString()), - nonKeyAttributeName, new AttributeValue(testItem.getNonKeyAttribute())); + GetItemResponse item = rawGetItem(testItem); + Map expected = new HashMap(); + expected.put(hashKeyName, AttributeValue.builder().s(testItem.getHashKey()).build()); + expected.put(rangeKeyName, AttributeValue.builder().n(testItem.getRangeKey().toString()).build()); + expected.put(nonKeyAttributeName, AttributeValue.builder().s(testItem.getNonKeyAttribute()).build()); - assertEquals(expected, item.getItem()); + assertEquals(expected, item.item()); } @Test @@ -556,13 +555,13 @@ public void testPutWithKeyAndNonKeyAttributesSpecifiedRecordNotInTable() dynamoMapper.save(testItem, putConfig); - GetItemResult item = rawGetItem(testItem); - Map expected = ImmutableMapParameter.of( - hashKeyName, new AttributeValue(testItem.getHashKey()), - rangeKeyName, new AttributeValue().withN(testItem.getRangeKey().toString()), - nonKeyAttributeName, new AttributeValue(testItem.getNonKeyAttribute())); + GetItemResponse item = rawGetItem(testItem); + Map expected = new HashMap(); + expected.put(hashKeyName, AttributeValue.builder().s(testItem.getHashKey()).build()); + expected.put(rangeKeyName, AttributeValue.builder().n(testItem.getRangeKey().toString()).build()); + expected.put(nonKeyAttributeName, AttributeValue.builder().s(testItem.getNonKeyAttribute()).build()); - assertEquals(expected, item.getItem()); + assertEquals(expected, item.item()); } @Test(expected = ConditionalCheckFailedException.class) @@ -582,37 +581,39 @@ public void testPutWithVersion_SucceedsWhenVersionMatches() throws Exception { dynamoMapper.save(testItem, putConfig); - GetItemResult item = rawGetItem(testItem); - Map expected = ImmutableMapParameter.of( - hashKeyName, new AttributeValue(testItem.getHashKey()), - rangeKeyName, new AttributeValue().withN(testItem.getRangeKey().toString()), - nonKeyAttributeName, new AttributeValue(testItem.getNonKeyAttribute()), - versionAttributeName, new AttributeValue().withN(Long.toString(version + 1))); + GetItemResponse item = rawGetItem(testItem); + Map expected = new HashMap(); + expected.put(hashKeyName, AttributeValue.builder().s(testItem.getHashKey()).build()); + expected.put(rangeKeyName, AttributeValue.builder().n(testItem.getRangeKey().toString()).build()); + expected.put(nonKeyAttributeName, AttributeValue.builder().s(testItem.getNonKeyAttribute()).build()); + expected.put(versionAttributeName, AttributeValue.builder().n(Long.toString(version + 1)).build()); - assertEquals(expected, item.getItem()); + assertEquals(expected, item.item()); } - private GetItemResult rawGetItem(TestItem testItem) { + private GetItemResponse rawGetItem(TestItem testItem) { + Map key = new HashMap(); + key.put(hashKeyName, AttributeValue.builder().s(testItem.getHashKey()).build()); + key.put(rangeKeyName, AttributeValue.builder().n(testItem.getRangeKey().toString()).build()); return dynamo.getItem( - new GetItemRequest() - .withTableName(tableName) - .withKey(ImmutableMapParameter.of(hashKeyName, new AttributeValue(testItem.getHashKey()), - rangeKeyName, new AttributeValue().withN(testItem.getRangeKey().toString())))); + GetItemRequest.builder() + .tableName(tableName) + .key(key).build()); } private static TestItem putRandomUniqueItem(String nonKeyAttributeValue, Set stringSetAttributeValue) { String hashKeyValue = UUID.randomUUID().toString(); Long rangeKeyValue = System.currentTimeMillis(); Map item = new HashMap(); - item.put(hashKeyName, new AttributeValue().withS(hashKeyValue)); - item.put(rangeKeyName, new AttributeValue().withN(rangeKeyValue.toString())); + item.put(hashKeyName, AttributeValue.builder().s(hashKeyValue).build()); + item.put(rangeKeyName, AttributeValue.builder().n(rangeKeyValue.toString()).build()); if (null != nonKeyAttributeValue) { - item.put(nonKeyAttributeName, new AttributeValue().withS(nonKeyAttributeValue)); + item.put(nonKeyAttributeName, AttributeValue.builder().s(nonKeyAttributeValue).build()); } if (null != stringSetAttributeValue) { - item.put(stringSetAttributeName, new AttributeValue().withSS(stringSetAttributeValue)); + item.put(stringSetAttributeName, AttributeValue.builder().ss(stringSetAttributeValue).build()); } - dynamo.putItem(new PutItemRequest().withTableName(tableName).withItem(item)); + dynamo.putItem(PutItemRequest.builder().tableName(tableName).item(item).build()); /* Returns the item as a modeled object. */ TestItem testItem = new TestItem(); @@ -627,10 +628,10 @@ private static TestItemWithVersion putRandomUniqueItemWithVersion(Long version) String hashKeyValue = UUID.randomUUID().toString(); Long rangeKeyValue = System.currentTimeMillis(); Map item = new HashMap(); - item.put(hashKeyName, new AttributeValue().withS(hashKeyValue)); - item.put(rangeKeyName, new AttributeValue().withN(rangeKeyValue.toString())); - item.put(versionAttributeName, new AttributeValue().withN(version.toString())); - dynamo.putItem(new PutItemRequest().withTableName(tableName).withItem(item)); + item.put(hashKeyName, AttributeValue.builder().s(hashKeyValue).build()); + item.put(rangeKeyName, AttributeValue.builder().n(rangeKeyValue.toString()).build()); + item.put(versionAttributeName, AttributeValue.builder().n(version.toString()).build()); + dynamo.putItem(PutItemRequest.builder().tableName(tableName).item(item).build()); TestItemWithVersion testItem = new TestItemWithVersion(); testItem.setHashKey(hashKeyValue); testItem.setRangeKey(rangeKeyValue); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigTestBase.java index d5e645474d72..11b7202794df 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/MapperSaveConfigTestBase.java @@ -10,7 +10,6 @@ import static org.junit.Assert.assertNotNull; import software.amazon.awssdk.mapper.dynamodb.test.util.DynamoDBIntegrationTestBase; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBAttribute; import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; @@ -18,15 +17,15 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBRangeKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBVersionAttribute; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.model.TableDescription; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.TableDescription; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; -import com.amazonaws.services.dynamodbv2.util.TableUtils; import java.util.Set; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -80,23 +79,22 @@ public class MapperSaveConfigTestBase extends DynamoDBIntegrationTestBase { protected static final Long WRITE_CAPACITY = 5L; /** Provisioned Throughput for the test table created in Amazon DynamoDB */ - protected static final ProvisionedThroughput DEFAULT_PROVISIONED_THROUGHPUT = new ProvisionedThroughput() - .withReadCapacityUnits(READ_CAPACITY).withWriteCapacityUnits( - WRITE_CAPACITY); + protected static final ProvisionedThroughput DEFAULT_PROVISIONED_THROUGHPUT = ProvisionedThroughput.builder() + .readCapacityUnits(READ_CAPACITY).writeCapacityUnits( + WRITE_CAPACITY).build(); @BeforeClass public static void setUp() throws Exception { - setUpCredentials(); - dynamo = new AmazonDynamoDBClient(credentials); + setUpTestBase(); dynamoMapper = new DynamoDBMapper(dynamo); createTestTable(DEFAULT_PROVISIONED_THROUGHPUT); - TableUtils.waitUntilActive(dynamo, tableName); + dynamo.waiter().waitUntilTableExists(b -> b.tableName(tableName)); } @AfterClass public static void tearDown() { - dynamo.deleteTable(tableName); + dynamo.deleteTable(DeleteTableRequest.builder().tableName(tableName).build()); } @DynamoDBTable(tableName = tableName) @@ -154,38 +152,37 @@ public void setFakeStringSetAttribute(Set stringSetAttribute) { */ protected static void createTestTable( ProvisionedThroughput provisionedThroughput) { - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(tableName) - .withKeySchema( - new KeySchemaElement().withAttributeName( - hashKeyName).withKeyType( - KeyType.HASH)) - .withKeySchema( - new KeySchemaElement().withAttributeName( - rangeKeyName).withKeyType( - KeyType.RANGE)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName( - hashKeyName).withAttributeType( - ScalarAttributeType.S)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName( - rangeKeyName).withAttributeType( - ScalarAttributeType.N)); - createTableRequest.setProvisionedThroughput(provisionedThroughput); + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(tableName) + .keySchema( + KeySchemaElement.builder().attributeName( + hashKeyName).keyType( + KeyType.HASH).build(), + KeySchemaElement.builder().attributeName( + rangeKeyName).keyType( + KeyType.RANGE).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName( + hashKeyName).attributeType( + ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName( + rangeKeyName).attributeType( + ScalarAttributeType.N).build()) + .provisionedThroughput(provisionedThroughput) + .build(); TableDescription createdTableDescription = dynamo.createTable( - createTableRequest).getTableDescription(); + createTableRequest).tableDescription(); System.out.println("Created Table: " + createdTableDescription); - assertEquals(tableName, createdTableDescription.getTableName()); - assertNotNull(createdTableDescription.getTableStatus()); + assertEquals(tableName, createdTableDescription.tableName()); + assertNotNull(createdTableDescription.tableStatus()); assertEquals(hashKeyName, createdTableDescription - .getKeySchema().get(0).getAttributeName()); + .keySchema().get(0).attributeName()); assertEquals(KeyType.HASH.toString(), createdTableDescription - .getKeySchema().get(0).getKeyType()); + .keySchema().get(0).keyTypeAsString()); assertEquals(rangeKeyName, createdTableDescription - .getKeySchema().get(1).getAttributeName()); + .keySchema().get(1).attributeName()); assertEquals(KeyType.RANGE.toString(), createdTableDescription - .getKeySchema().get(1).getKeyType()); + .keySchema().get(1).keyTypeAsString()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/NumericSetAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/NumericSetAttributesIntegrationTest.java index 709d08a3681d..8b9d4297554f 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/NumericSetAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/NumericSetAttributesIntegrationTest.java @@ -34,8 +34,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; /** * Tests string set attributes @@ -62,15 +62,15 @@ public class NumericSetAttributesIntegrationTest extends DynamoDBMapperIntegrati static { for ( int i = 0; i < 5; i++ ) { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withS("" + start++)); - attr.put(INTEGER_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(FLOAT_OBJECT_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(DOUBLE_OBJECT_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(BIG_INTEGER_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(BIG_DECIMAL_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(LONG_OBJECT_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(BYTE_OBJECT_ATTRIBUTE, new AttributeValue().withNS("" + byteStart++, "" + byteStart++, "" + byteStart++)); - attr.put(BOOLEAN_ATTRIBUTE, new AttributeValue().withNS("0", "1")); + attr.put(KEY_NAME, AttributeValue.builder().s("" + start++).build()); + attr.put(INTEGER_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(FLOAT_OBJECT_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(DOUBLE_OBJECT_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(BIG_INTEGER_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(BIG_DECIMAL_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(LONG_OBJECT_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(BYTE_OBJECT_ATTRIBUTE, AttributeValue.builder().ns("" + byteStart++, "" + byteStart++, "" + byteStart++).build()); + attr.put(BOOLEAN_ATTRIBUTE, AttributeValue.builder().ns("0", "1").build()); attrs.add(attr); } }; @@ -81,7 +81,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_NAME, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(attr).build()); } } @@ -90,18 +90,18 @@ public void testLoad() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); for ( Map attr : attrs ) { - NumberSetAttributeClass x = util.load(NumberSetAttributeClass.class, attr.get(KEY_NAME).getS()); - assertEquals(x.getKey(), attr.get(KEY_NAME).getS()); - + NumberSetAttributeClass x = util.load(NumberSetAttributeClass.class, attr.get(KEY_NAME).s()); + assertEquals(x.getKey(), attr.get(KEY_NAME).s()); + // Convert all numbers to the most inclusive type for easy comparison - assertNumericSetsEquals(x.getBigDecimalAttribute(), attr.get(BIG_DECIMAL_ATTRIBUTE).getNS()); - assertNumericSetsEquals(x.getBigIntegerAttribute(), attr.get(BIG_INTEGER_ATTRIBUTE).getNS()); - assertNumericSetsEquals(x.getFloatObjectAttribute(), attr.get(FLOAT_OBJECT_ATTRIBUTE).getNS()); - assertNumericSetsEquals(x.getDoubleObjectAttribute(), attr.get(DOUBLE_OBJECT_ATTRIBUTE).getNS()); - assertNumericSetsEquals(x.getIntegerAttribute(), attr.get(INTEGER_ATTRIBUTE).getNS()); - assertNumericSetsEquals(x.getLongObjectAttribute(), attr.get(LONG_OBJECT_ATTRIBUTE).getNS()); - assertNumericSetsEquals(x.getByteObjectAttribute(), attr.get(BYTE_OBJECT_ATTRIBUTE).getNS()); - assertSetsEqual(toSet("0", "1"), attr.get(BOOLEAN_ATTRIBUTE).getNS()); + assertNumericSetsEquals(x.getBigDecimalAttribute(), attr.get(BIG_DECIMAL_ATTRIBUTE).ns()); + assertNumericSetsEquals(x.getBigIntegerAttribute(), attr.get(BIG_INTEGER_ATTRIBUTE).ns()); + assertNumericSetsEquals(x.getFloatObjectAttribute(), attr.get(FLOAT_OBJECT_ATTRIBUTE).ns()); + assertNumericSetsEquals(x.getDoubleObjectAttribute(), attr.get(DOUBLE_OBJECT_ATTRIBUTE).ns()); + assertNumericSetsEquals(x.getIntegerAttribute(), attr.get(INTEGER_ATTRIBUTE).ns()); + assertNumericSetsEquals(x.getLongObjectAttribute(), attr.get(LONG_OBJECT_ATTRIBUTE).ns()); + assertNumericSetsEquals(x.getByteObjectAttribute(), attr.get(BYTE_OBJECT_ATTRIBUTE).ns()); + assertSetsEqual(toSet("0", "1"), attr.get(BOOLEAN_ATTRIBUTE).ns()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/QueryIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/QueryIntegrationTest.java index cc761e0e5017..24f1586f8035 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/QueryIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/QueryIntegrationTest.java @@ -11,10 +11,10 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.ConsistentReads; import software.amazon.awssdk.mapper.dynamodb.DynamoDBQueryExpression; import software.amazon.awssdk.mapper.dynamodb.QueryResultPage; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.Select; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.Select; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import java.math.BigDecimal; import java.util.ArrayList; @@ -64,9 +64,9 @@ public void testQueryWithPrimaryRangeKey() throws Exception { .withHashKeyValues(hashKeyObject) .withRangeKeyCondition( "rangeKey", - new Condition() - .withComparisonOperator(ComparisonOperator.GT) - .withAttributeValueList(new AttributeValue().withN("1.0"))) + Condition.builder() + .comparisonOperator(ComparisonOperator.GT) + .attributeValueList(AttributeValue.builder().n("1.0").build()).build()) .withLimit(11); List list = mapper.query(RangeKeyClass.class, queryExpression); @@ -106,10 +106,10 @@ public void testQueryFilter() { // A random filter condition to be applied to the query. Random random = new Random(); int randomFilterValue = random.nextInt(TEST_ITEM_NUMBER); - Condition filterCondition = new Condition() - .withComparisonOperator(ComparisonOperator.LT) - .withAttributeValueList( - new AttributeValue().withN(Integer.toString(randomFilterValue))); + Condition filterCondition = Condition.builder() + .comparisonOperator(ComparisonOperator.LT) + .attributeValueList( + AttributeValue.builder().n(Integer.toString(randomFilterValue)).build()).build(); /* * (1) Apply the filter on the range key, in form of key condition @@ -148,8 +148,8 @@ public void testUnnecessaryIndexNameException() { keyObject.setKey(hashKey); DynamoDBQueryExpression queryExpression = new DynamoDBQueryExpression().withHashKeyValues(keyObject); queryExpression.withRangeKeyCondition("rangeKey", - new Condition().withComparisonOperator(ComparisonOperator.GT.toString()).withAttributeValueList( - new AttributeValue().withN("1.0"))).withLimit(11) + Condition.builder().comparisonOperator(ComparisonOperator.GT.toString()).attributeValueList( + AttributeValue.builder().n("1.0").build()).build()).withLimit(11) .withIndexName("some_index"); mapper.query(RangeKeyClass.class, queryExpression); fail("User should not provide index name when making query with the primary range key"); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/RangeKeyAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/RangeKeyAttributesIntegrationTest.java index f080ecbea816..096a6510403b 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/RangeKeyAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/RangeKeyAttributesIntegrationTest.java @@ -28,8 +28,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; /** @@ -55,13 +55,13 @@ public class RangeKeyAttributesIntegrationTest extends DynamoDBMapperIntegration static { for ( int i = 0; i < 5; i++ ) { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withN("" + startKey++)); - attr.put(RANGE_KEY, new AttributeValue().withN("" + start++)); - attr.put(INTEGER_ATTRIBUTE, new AttributeValue().withNS("" + start++, "" + start++, "" + start++)); - attr.put(BIG_DECIMAL_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(STRING_ATTRIBUTE, new AttributeValue().withS("" + start++)); - attr.put(STRING_SET_ATTRIBUTE, new AttributeValue().withSS("" + start++, "" + start++, "" + start++)); - attr.put(VERSION_ATTRIBUTE, new AttributeValue().withN("1")); + attr.put(KEY_NAME, AttributeValue.builder().n("" + startKey++).build()); + attr.put(RANGE_KEY, AttributeValue.builder().n("" + start++).build()); + attr.put(INTEGER_ATTRIBUTE, AttributeValue.builder().ns("" + start++, "" + start++, "" + start++).build()); + attr.put(BIG_DECIMAL_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(STRING_ATTRIBUTE, AttributeValue.builder().s("" + start++).build()); + attr.put(STRING_SET_ATTRIBUTE, AttributeValue.builder().ss("" + start++, "" + start++, "" + start++).build()); + attr.put(VERSION_ATTRIBUTE, AttributeValue.builder().n("1").build()); attrs.add(attr); } @@ -73,7 +73,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_WITH_RANGE_ATTRIBUTE, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_WITH_RANGE_ATTRIBUTE).item(attr).build()); } } @@ -82,18 +82,18 @@ public void testLoad() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); for ( Map attr : attrs ) { - RangeKeyClass x = util.load(newRangeKey(Long.parseLong(attr.get(KEY_NAME).getN()), - Double.parseDouble(attr.get(RANGE_KEY).getN()))); + RangeKeyClass x = util.load(newRangeKey(Long.parseLong(attr.get(KEY_NAME).n()), + Double.parseDouble(attr.get(RANGE_KEY).n()))); // Convert all numbers to the most inclusive type for easy // comparison - assertEquals(new BigDecimal(x.getKey()), new BigDecimal(attr.get(KEY_NAME).getN())); - assertEquals(new BigDecimal(x.getRangeKey()), new BigDecimal(attr.get(RANGE_KEY).getN())); - assertEquals(new BigDecimal(x.getVersion()), new BigDecimal(attr.get(VERSION_ATTRIBUTE).getN())); - assertEquals(x.getBigDecimalAttribute(), new BigDecimal(attr.get(BIG_DECIMAL_ATTRIBUTE).getN())); - assertNumericSetsEquals(x.getIntegerAttribute(), attr.get(INTEGER_ATTRIBUTE).getNS()); - assertEquals(x.getStringAttribute(), attr.get(STRING_ATTRIBUTE).getS()); - assertSetsEqual(x.getStringSetAttribute(), toSet(attr.get(STRING_SET_ATTRIBUTE).getSS())); + assertEquals(new BigDecimal(x.getKey()), new BigDecimal(attr.get(KEY_NAME).n())); + assertEquals(new BigDecimal(x.getRangeKey()), new BigDecimal(attr.get(RANGE_KEY).n())); + assertEquals(new BigDecimal(x.getVersion()), new BigDecimal(attr.get(VERSION_ATTRIBUTE).n())); + assertEquals(x.getBigDecimalAttribute(), new BigDecimal(attr.get(BIG_DECIMAL_ATTRIBUTE).n())); + assertNumericSetsEquals(x.getIntegerAttribute(), attr.get(INTEGER_ATTRIBUTE).ns()); + assertEquals(x.getStringAttribute(), attr.get(STRING_ATTRIBUTE).s()); + assertSetsEqual(x.getStringSetAttribute(), toSet(attr.get(STRING_SET_ATTRIBUTE).ss())); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScalarAttributeIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScalarAttributeIntegrationTest.java index 2cc5eef2f762..fb8b7d8fad80 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScalarAttributeIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScalarAttributeIntegrationTest.java @@ -17,7 +17,7 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBScalarAttribute; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; import software.amazon.awssdk.mapper.dynamodb.pojos.AutoKeyAndVal; import java.util.UUID; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleNumericAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleNumericAttributesIntegrationTest.java index c372a14f8843..90dca463f368 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleNumericAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleNumericAttributesIntegrationTest.java @@ -32,10 +32,10 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; /** * Tests numeric attributes @@ -70,23 +70,23 @@ public class SimpleNumericAttributesIntegrationTest extends DynamoDBMapperIntegr static { for ( int i = 0; i < 5; i++ ) { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withS("" + start++)); - attr.put(INT_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(INTEGER_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(FLOAT_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(FLOAT_OBJECT_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(DOUBLE_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(DOUBLE_OBJECT_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(BIG_INTEGER_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(BIG_DECIMAL_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(LONG_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(LONG_OBJECT_ATTRIBUTE, new AttributeValue().withN("" + start++)); - attr.put(BYTE_ATTRIBUTE, new AttributeValue().withN("" + byteStart++)); - attr.put(BYTE_OBJECT_ATTRIBUTE, new AttributeValue().withN("" + byteStart++)); - attr.put(BOOLEAN_ATTRIBUTE, new AttributeValue().withN(start++ % 2 == 0 ? "1" : "0")); - attr.put(BOOLEAN_OBJECT_ATTRIBUTE, new AttributeValue().withN(start++ % 2 == 0 ? "1" : "0")); - attr.put(SHORT_ATTRIBUTE, new AttributeValue().withN("" + byteStart++)); - attr.put(SHORT_OBJECT_ATTRIBUTE, new AttributeValue().withN("" + byteStart++)); + attr.put(KEY_NAME, AttributeValue.builder().s("" + start++).build()); + attr.put(INT_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(INTEGER_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(FLOAT_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(FLOAT_OBJECT_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(DOUBLE_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(DOUBLE_OBJECT_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(BIG_INTEGER_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(BIG_DECIMAL_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(LONG_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(LONG_OBJECT_ATTRIBUTE, AttributeValue.builder().n("" + start++).build()); + attr.put(BYTE_ATTRIBUTE, AttributeValue.builder().n("" + byteStart++).build()); + attr.put(BYTE_OBJECT_ATTRIBUTE, AttributeValue.builder().n("" + byteStart++).build()); + attr.put(BOOLEAN_ATTRIBUTE, AttributeValue.builder().n(start++ % 2 == 0 ? "1" : "0").build()); + attr.put(BOOLEAN_OBJECT_ATTRIBUTE, AttributeValue.builder().n(start++ % 2 == 0 ? "1" : "0").build()); + attr.put(SHORT_ATTRIBUTE, AttributeValue.builder().n("" + byteStart++).build()); + attr.put(SHORT_OBJECT_ATTRIBUTE, AttributeValue.builder().n("" + byteStart++).build()); attrs.add(attr); } }; @@ -97,7 +97,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_NAME, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(attr).build()); } } @@ -112,26 +112,26 @@ public void testLoad() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); for ( Map attr : attrs ) { - NumberAttributeClass x = util.load(getKeyObject(attr.get(KEY_NAME).getS())); - assertEquals(x.getKey(), attr.get(KEY_NAME).getS()); - + NumberAttributeClass x = util.load(getKeyObject(attr.get(KEY_NAME).s())); + assertEquals(x.getKey(), attr.get(KEY_NAME).s()); + // Convert all numbers to the most inclusive type for easy comparison - assertEquals(x.getBigDecimalAttribute(), new BigDecimal(attr.get(BIG_DECIMAL_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getBigIntegerAttribute()), new BigDecimal(attr.get(BIG_INTEGER_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getFloatAttribute()), new BigDecimal(attr.get(FLOAT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getFloatObjectAttribute()), new BigDecimal(attr.get(FLOAT_OBJECT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getDoubleAttribute()), new BigDecimal(attr.get(DOUBLE_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getDoubleObjectAttribute()), new BigDecimal(attr.get(DOUBLE_OBJECT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getIntAttribute()), new BigDecimal(attr.get(INT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getIntegerAttribute()), new BigDecimal(attr.get(INTEGER_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getLongAttribute()), new BigDecimal(attr.get(LONG_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getLongObjectAttribute()), new BigDecimal(attr.get(LONG_OBJECT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getByteAttribute()), new BigDecimal(attr.get(BYTE_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getByteObjectAttribute()), new BigDecimal(attr.get(BYTE_OBJECT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getShortAttribute()), new BigDecimal(attr.get(SHORT_ATTRIBUTE).getN())); - assertEquals(new BigDecimal(x.getShortObjectAttribute()), new BigDecimal(attr.get(SHORT_OBJECT_ATTRIBUTE).getN())); - assertEquals(x.isBooleanAttribute(), attr.get(BOOLEAN_ATTRIBUTE).getN().equals("1")); - assertEquals(x.getBooleanObjectAttribute(), attr.get(BOOLEAN_OBJECT_ATTRIBUTE).getN().equals("1")); + assertEquals(x.getBigDecimalAttribute(), new BigDecimal(attr.get(BIG_DECIMAL_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getBigIntegerAttribute()), new BigDecimal(attr.get(BIG_INTEGER_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getFloatAttribute()), new BigDecimal(attr.get(FLOAT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getFloatObjectAttribute()), new BigDecimal(attr.get(FLOAT_OBJECT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getDoubleAttribute()), new BigDecimal(attr.get(DOUBLE_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getDoubleObjectAttribute()), new BigDecimal(attr.get(DOUBLE_OBJECT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getIntAttribute()), new BigDecimal(attr.get(INT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getIntegerAttribute()), new BigDecimal(attr.get(INTEGER_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getLongAttribute()), new BigDecimal(attr.get(LONG_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getLongObjectAttribute()), new BigDecimal(attr.get(LONG_OBJECT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getByteAttribute()), new BigDecimal(attr.get(BYTE_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getByteObjectAttribute()), new BigDecimal(attr.get(BYTE_OBJECT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getShortAttribute()), new BigDecimal(attr.get(SHORT_ATTRIBUTE).n())); + assertEquals(new BigDecimal(x.getShortObjectAttribute()), new BigDecimal(attr.get(SHORT_OBJECT_ATTRIBUTE).n())); + assertEquals(x.isBooleanAttribute(), attr.get(BOOLEAN_ATTRIBUTE).n().equals("1")); + assertEquals(x.getBooleanObjectAttribute(), attr.get(BOOLEAN_OBJECT_ATTRIBUTE).n().equals("1")); } // Test loading an object that doesn't exist @@ -233,12 +233,12 @@ public void performanceTest() throws Exception { DynamoDBMapper mapper = new DynamoDBMapper(dynamo); mapper.save(obj); - GetItemResult item = dynamo.getItem(new GetItemRequest().withTableName("aws-java-sdk-util").withKey( - getMapKey(KEY_NAME, new AttributeValue().withS(obj.getKey())))); - + GetItemResponse item = dynamo.getItem(GetItemRequest.builder().tableName("aws-java-sdk-util").key( + getMapKey(KEY_NAME, AttributeValue.builder().s(obj.getKey()).build())).build()); + long start = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { - mapper.marshallIntoObject(NumberAttributeClass.class, item.getItem()); + mapper.marshallIntoObject(NumberAttributeClass.class, item.item()); } long end = System.currentTimeMillis(); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleStringAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleStringAttributesIntegrationTest.java index f9605d73c94a..dbe1bc8582e2 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleStringAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/SimpleStringAttributesIntegrationTest.java @@ -32,8 +32,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.ConsistentReads; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.SaveBehavior; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; /** @@ -49,9 +49,9 @@ public class SimpleStringAttributesIntegrationTest extends DynamoDBMapperIntegra static { for ( int i = 0; i < 5; i++ ) { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withS("" + startKey++)); - attr.put(STRING_ATTRIBUTE, new AttributeValue().withS("" + startKey++)); - attr.put(ORIGINAL_NAME_ATTRIBUTE, new AttributeValue().withS("" + startKey++)); + attr.put(KEY_NAME, AttributeValue.builder().s("" + startKey++).build()); + attr.put(STRING_ATTRIBUTE, AttributeValue.builder().s("" + startKey++).build()); + attr.put(ORIGINAL_NAME_ATTRIBUTE, AttributeValue.builder().s("" + startKey++).build()); attrs.add(attr); } }; @@ -62,7 +62,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_NAME, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(attr).build()); } } @@ -71,10 +71,10 @@ public void testLoad() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); for ( Map attr : attrs ) { - StringAttributeClass x = util.load(StringAttributeClass.class, attr.get(KEY_NAME).getS()); - assertEquals(x.getKey(), attr.get(KEY_NAME).getS()); - assertEquals(x.getStringAttribute(), attr.get(STRING_ATTRIBUTE).getS()); - assertEquals(x.getRenamedAttribute(), attr.get(ORIGINAL_NAME_ATTRIBUTE).getS()); + StringAttributeClass x = util.load(StringAttributeClass.class, attr.get(KEY_NAME).s()); + assertEquals(x.getKey(), attr.get(KEY_NAME).s()); + assertEquals(x.getStringAttribute(), attr.get(STRING_ATTRIBUTE).s()); + assertEquals(x.getRenamedAttribute(), attr.get(ORIGINAL_NAME_ATTRIBUTE).s()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/StringSetAttributesIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/StringSetAttributesIntegrationTest.java index 40cd6a729cff..8468df64f3d0 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/StringSetAttributesIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/StringSetAttributesIntegrationTest.java @@ -27,8 +27,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.StringSetAttributeClass; @@ -46,10 +46,10 @@ public class StringSetAttributesIntegrationTest extends DynamoDBMapperIntegratio static { for ( int i = 0; i < 5; i++ ) { Map attr = new HashMap(); - attr.put(KEY_NAME, new AttributeValue().withS("" + startKey++)); - attr.put(STRING_SET_ATTRIBUTE, new AttributeValue().withSS("" + ++startKey, "" + ++startKey, "" + ++startKey)); - attr.put(ORIGINAL_NAME_ATTRIBUTE, new AttributeValue().withSS("" + ++startKey, "" + ++startKey, "" + ++startKey)); - attr.put(EXTRA_ATTRIBUTE, new AttributeValue().withSS("" + ++startKey, "" + ++startKey, "" + ++startKey)); + attr.put(KEY_NAME, AttributeValue.builder().s("" + startKey++).build()); + attr.put(STRING_SET_ATTRIBUTE, AttributeValue.builder().ss("" + ++startKey, "" + ++startKey, "" + ++startKey).build()); + attr.put(ORIGINAL_NAME_ATTRIBUTE, AttributeValue.builder().ss("" + ++startKey, "" + ++startKey, "" + ++startKey).build()); + attr.put(EXTRA_ATTRIBUTE, AttributeValue.builder().ss("" + ++startKey, "" + ++startKey, "" + ++startKey).build()); attrs.add(attr); } }; @@ -60,7 +60,7 @@ public static void setUp() throws Exception { // Insert the data for ( Map attr : attrs ) { - dynamo.putItem(new PutItemRequest(TABLE_NAME, attr)); + dynamo.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(attr).build()); } } @@ -69,10 +69,10 @@ public void testLoad() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); for ( Map attr : attrs ) { - StringSetAttributeClass x = util.load(StringSetAttributeClass.class, attr.get(KEY_NAME).getS()); - assertEquals(x.getKey(), attr.get(KEY_NAME).getS()); - assertSetsEqual(x.getStringSetAttribute(), toSet(attr.get(STRING_SET_ATTRIBUTE).getSS())); - assertSetsEqual(x.getStringSetAttributeRenamed(), toSet(attr.get(ORIGINAL_NAME_ATTRIBUTE).getSS())); + StringSetAttributeClass x = util.load(StringSetAttributeClass.class, attr.get(KEY_NAME).s()); + assertEquals(x.getKey(), attr.get(KEY_NAME).s()); + assertSetsEqual(x.getStringSetAttribute(), toSet(attr.get(STRING_SET_ATTRIBUTE).ss())); + assertSetsEqual(x.getStringSetAttributeRenamed(), toSet(attr.get(ORIGINAL_NAME_ATTRIBUTE).ss())); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TableMapperIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TableMapperIntegrationTest.java index 553054170fa3..8dd6468046c3 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TableMapperIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TableMapperIntegrationTest.java @@ -24,7 +24,7 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTableMapper; import software.amazon.awssdk.mapper.dynamodb.pojos.AutoKeyAndVal; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; import java.util.Arrays; import java.util.Collections; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadExpressionTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadExpressionTest.java index a700906f1aff..d96954994f87 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadExpressionTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadExpressionTest.java @@ -22,7 +22,7 @@ import static software.amazon.awssdk.mapper.dynamodb.TestObjectCreator.TransactionLoadTestDataRequest; import static org.junit.Assert.assertEquals; -import com.amazonaws.AmazonServiceException; +import software.amazon.awssdk.awscore.exception.AwsServiceException; import org.junit.Test; public class TransactionLoadExpressionTest extends TransactionsTestBase { @@ -81,8 +81,8 @@ public void testWithOneLoadExpressionContainingReservedWord() { try { executeAndValidateTransactionLoad(testData.getTransactionLoadRequest(), testData.getExpectedObjects()); - } catch (AmazonServiceException ex) { - assertEquals("ValidationException", ex.getErrorCode()); + } catch (AwsServiceException ex) { + assertEquals("ValidationException", ex.awsErrorDetails().errorCode()); } } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadMixedTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadMixedTest.java index f29171c5b839..566a6f4af999 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadMixedTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadMixedTest.java @@ -48,8 +48,8 @@ import software.amazon.awssdk.mapper.dynamodb.TransactionLoadRequest; import software.amazon.awssdk.mapper.dynamodb.pojos.AllSupportedAnnotationsClass; import software.amazon.awssdk.mapper.dynamodb.pojos.AllSupportedDataTypesClass; -import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyBothAutoGenerated; import software.amazon.awssdk.mapper.dynamodb.pojos.SchemaViolatingTestItem; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadTableMapperTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadTableMapperTest.java index 94f8ecf56ed0..716061dbfdbe 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadTableMapperTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionLoadTableMapperTest.java @@ -36,7 +36,7 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMappingException; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTableMapper; import software.amazon.awssdk.mapper.dynamodb.TransactionLoadRequest; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.SchemaViolatingTestItem; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteConditionExpressionTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteConditionExpressionTest.java index a282347cb2d7..28d3fca94fd9 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteConditionExpressionTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteConditionExpressionTest.java @@ -26,10 +26,10 @@ import java.util.List; import java.util.Map; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.CancellationReason; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.CancellationReason; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; @@ -271,9 +271,9 @@ public void testMultipleOperationsWithOneOfEachHavingReservedWordExpression() { executeAndValidateTransactionWrite(transactionWriteTestData.getTransactionWriteRequest(), transactionWriteTestData.getExpectedObjectKeys(), transactionWriteTestData.getExpectedObjects()); - fail("Expected AmazonServiceException but no exception thrown"); - } catch (AmazonServiceException ase) { - assertEquals("ValidationException", ase.getErrorCode()); + fail("Expected AwsServiceException but no exception thrown"); + } catch (AwsServiceException ase) { + assertEquals("ValidationException", ase.awsErrorDetails().errorCode()); } } @@ -281,21 +281,21 @@ private static Map generateAttributeItemFromObject(Objec Map expectedResponseValueMap = new HashMap(); if (obj.getClass().equals(StringAttributeClass.class)) { StringAttributeClass stringAttributeClassObject = (StringAttributeClass) obj; - expectedResponseValueMap.put("originalName", new AttributeValue(stringAttributeClassObject.getRenamedAttribute())); - expectedResponseValueMap.put("stringAttribute", new AttributeValue(stringAttributeClassObject.getStringAttribute())); - expectedResponseValueMap.put("key", new AttributeValue(stringAttributeClassObject.getKey())); + expectedResponseValueMap.put("originalName", AttributeValue.builder().s(stringAttributeClassObject.getRenamedAttribute()).build()); + expectedResponseValueMap.put("stringAttribute", AttributeValue.builder().s(stringAttributeClassObject.getStringAttribute()).build()); + expectedResponseValueMap.put("key", AttributeValue.builder().s(stringAttributeClassObject.getKey()).build()); } else if (obj.getClass().equals(TestItem.class)) { TestItem testItemObject = (TestItem) obj; - expectedResponseValueMap.put("hashKey", new AttributeValue(testItemObject.getHashKey())); - expectedResponseValueMap.put("rangeKey", new AttributeValue().withN(testItemObject.getRangeKey().toString())); - expectedResponseValueMap.put("stringAttribute", new AttributeValue(testItemObject.getStringAttribute())); - expectedResponseValueMap.put("nonKeyAttribute", new AttributeValue(testItemObject.getNonKeyAttribute())); - expectedResponseValueMap.put("stringSetAttribute", new AttributeValue().withSS(testItemObject.getStringSetAttribute())); + expectedResponseValueMap.put("hashKey", AttributeValue.builder().s(testItemObject.getHashKey()).build()); + expectedResponseValueMap.put("rangeKey", AttributeValue.builder().n(testItemObject.getRangeKey().toString()).build()); + expectedResponseValueMap.put("stringAttribute", AttributeValue.builder().s(testItemObject.getStringAttribute()).build()); + expectedResponseValueMap.put("nonKeyAttribute", AttributeValue.builder().s(testItemObject.getNonKeyAttribute()).build()); + expectedResponseValueMap.put("stringSetAttribute", AttributeValue.builder().ss(testItemObject.getStringSetAttribute()).build()); } else if (obj.getClass().equals(HashKeyRangeKeyClass.class)) { HashKeyRangeKeyClass hashKeyRangeKeyClassObject = (HashKeyRangeKeyClass) obj; - expectedResponseValueMap.put("hashKey", new AttributeValue().withN(Long.toString(hashKeyRangeKeyClassObject.getHashKey()))); - expectedResponseValueMap.put("rangeKey", new AttributeValue().withN(Double.toString(hashKeyRangeKeyClassObject.getRangeKey()))); - expectedResponseValueMap.put("stringAttribute", new AttributeValue(hashKeyRangeKeyClassObject.getStringAttribute())); + expectedResponseValueMap.put("hashKey", AttributeValue.builder().n(Long.toString(hashKeyRangeKeyClassObject.getHashKey())).build()); + expectedResponseValueMap.put("rangeKey", AttributeValue.builder().n(Double.toString(hashKeyRangeKeyClassObject.getRangeKey())).build()); + expectedResponseValueMap.put("stringAttribute", AttributeValue.builder().s(hashKeyRangeKeyClassObject.getStringAttribute()).build()); } else { throw new IllegalArgumentException("Unsupported class passed in: " + obj.getClass()); } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMiscellaneousTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMiscellaneousTest.java index 4120e73727ce..0f7476970678 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMiscellaneousTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMiscellaneousTest.java @@ -40,7 +40,7 @@ import java.util.Map; import java.util.UUID; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.TestObjectCreator; import software.amazon.awssdk.mapper.dynamodb.TestObjectCreator.TransactionWriteTestRequest; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; @@ -50,17 +50,17 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBTransactionWriteExpression; import software.amazon.awssdk.mapper.dynamodb.PaginatedQueryList; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex; -import com.amazonaws.services.dynamodbv2.model.IdempotentParameterMismatchException; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.Projection; -import com.amazonaws.services.dynamodbv2.model.ProjectionType; -import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.GlobalSecondaryIndex; +import software.amazon.awssdk.services.dynamodb.model.IdempotentParameterMismatchException; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; import software.amazon.awssdk.mapper.dynamodb.pojos.AllSupportedAnnotationsClass; import software.amazon.awssdk.mapper.dynamodb.pojos.AllSupportedDataTypesClass; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyClass; @@ -68,7 +68,6 @@ import software.amazon.awssdk.mapper.dynamodb.pojos.SlimAttributeNamesClass; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; -import com.amazonaws.services.dynamodbv2.util.TableUtils; import org.junit.Test; public class TransactionWriteMiscellaneousTest extends TransactionsTestBase { @@ -449,8 +448,8 @@ public void testUpdatesThatFailWithTokenCollision() { attributeNameMap.put("#14b10", "C"); attributeNameMap.put("#14b102850", "C"); Map attributeValueMap = new HashMap(); - attributeValueMap.put(":attr1", new AttributeValue(objectToBeUpdated1.getC())); - attributeValueMap.put(":attr2", new AttributeValue("randomString")); + attributeValueMap.put(":attr1", AttributeValue.builder().s(objectToBeUpdated1.getC()).build()); + attributeValueMap.put(":attr2", AttributeValue.builder().s("randomString").build()); writeExpression1.withExpressionAttributeValues(attributeValueMap); writeExpression1.withExpressionAttributeNames(attributeNameMap); updateTransactionWriteOperationsWithNewObjectAndExpression(transactionWriteOperations, objectToBeUpdated1, writeExpression1, 3); @@ -469,27 +468,34 @@ public void testUpdatesThatFailWithTokenCollision() { } } - private static void createGsiTestTable(AmazonDynamoDB dynamo, String tableName) throws InterruptedException { - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(tableName) - .withKeySchema(new KeySchemaElement("key", KeyType.HASH), - new KeySchemaElement("rangeKey", KeyType.RANGE)) - .withGlobalSecondaryIndexes(new GlobalSecondaryIndex() - .withIndexName(SDK_STRING_RANGE_TABLE_GSI_NAME) - .withKeySchema( - new KeySchemaElement("gis-hash-key", KeyType.HASH), - new KeySchemaElement("gis-range-key", KeyType.RANGE)) - .withProjection( - new Projection() - .withProjectionType(ProjectionType.ALL)) - .withProvisionedThroughput(TestObjectCreator.DEFAULT_PROVISIONED_THROUGHPUT)) - .withAttributeDefinitions(new AttributeDefinition("key", ScalarAttributeType.S), - new AttributeDefinition("rangeKey", ScalarAttributeType.S), - new AttributeDefinition("gis-hash-key", ScalarAttributeType.S), - new AttributeDefinition("gis-range-key", ScalarAttributeType.S)) - .withProvisionedThroughput(TestObjectCreator.DEFAULT_PROVISIONED_THROUGHPUT); - if (TableUtils.createTableIfNotExists(dynamo, createTableRequest)) { - TableUtils.waitUntilActive(dynamo, tableName); + private static void createGsiTestTable(DynamoDbClient dynamo, String tableName) throws InterruptedException { + CreateTableRequest createTableRequest = + CreateTableRequest.builder() + .tableName(tableName) + .keySchema(KeySchemaElement.builder().attributeName("key").keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName("rangeKey").keyType(KeyType.RANGE).build()) + .globalSecondaryIndexes( + GlobalSecondaryIndex.builder() + .indexName(SDK_STRING_RANGE_TABLE_GSI_NAME) + .keySchema( + KeySchemaElement.builder().attributeName("gis-hash-key").keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName("gis-range-key").keyType(KeyType.RANGE).build()) + .projection( + Projection.builder().projectionType(ProjectionType.ALL).build()) + .provisionedThroughput(TestObjectCreator.DEFAULT_PROVISIONED_THROUGHPUT) + .build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName("key").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("rangeKey").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("gis-hash-key").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("gis-range-key").attributeType(ScalarAttributeType.S).build()) + .provisionedThroughput(TestObjectCreator.DEFAULT_PROVISIONED_THROUGHPUT) + .build(); + try { + dynamo.createTable(createTableRequest); + dynamo.waiter().waitUntilTableExists(b -> b.tableName(tableName)); + } catch (software.amazon.awssdk.services.dynamodb.model.ResourceInUseException e) { + // Table already exists. } } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMixedTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMixedTest.java index adb34f7b05cb..60e5e74585db 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMixedTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteMixedTest.java @@ -57,8 +57,9 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConverter; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConverterFactory; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.mapper.dynamodb.pojos.CustomBooleanClass; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyAutoGenerated; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyBothAutoGenerated; @@ -205,10 +206,10 @@ public void testWithAttributeTransformer() throws InterruptedException { private Integer validateAdditionalAttributeAndReturnNew(final String tableName, final StringAttributeSubClass object, Integer previousAttribute) { Map key = new HashMap(); - key.put("key", new AttributeValue(object.getKey())); - GetItemResult item = dynamo.getItem(tableName, key); - assertTrue(item.getItem().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); - Integer currentAttribute = Integer.parseInt(item.getItem().get(ADDITIONAL_ATTRIBUTE_NAME).getN()); + key.put("key", AttributeValue.builder().s(object.getKey()).build()); + GetItemResponse item = dynamo.getItem(GetItemRequest.builder().tableName(tableName).key(key).build()); + assertTrue(item.item().containsKey(ADDITIONAL_ATTRIBUTE_NAME)); + Integer currentAttribute = Integer.parseInt(item.item().get(ADDITIONAL_ATTRIBUTE_NAME).n()); assertNotEquals(currentAttribute, previousAttribute); return currentAttribute; } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteSanityTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteSanityTest.java index 96f35a030fb9..67bac78fa744 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteSanityTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteSanityTest.java @@ -32,7 +32,7 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBTransactionWriteExpression; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteTableMapperTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteTableMapperTest.java index d6a03f868ba4..c72776aac290 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteTableMapperTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteTableMapperTest.java @@ -37,9 +37,9 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBTransactionWriteExpression; import software.amazon.awssdk.mapper.dynamodb.TransactionLoadRequest; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.CancellationReason; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.CancellationReason; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.StringAttributeClass; import software.amazon.awssdk.mapper.dynamodb.pojos.TestItem; import org.junit.BeforeClass; @@ -283,9 +283,9 @@ private void validateItem(Map item, Object expectedObjec throw new IllegalArgumentException("Unsupported expectedObject type: " + expectedObject.getClass()); } StringAttributeClass expectedStringAttributeObject = (StringAttributeClass) expectedObject; - assertEquals(expectedStringAttributeObject.getKey(), item.get("key").getS()); - assertEquals(expectedStringAttributeObject.getStringAttribute(), item.get("stringAttribute").getS()); - assertEquals(expectedStringAttributeObject.getRenamedAttribute(), item.get("originalName").getS()); + assertEquals(expectedStringAttributeObject.getKey(), item.get("key").s()); + assertEquals(expectedStringAttributeObject.getStringAttribute(), item.get("stringAttribute").s()); + assertEquals(expectedStringAttributeObject.getRenamedAttribute(), item.get("originalName").s()); } @Override @@ -315,12 +315,12 @@ protected void executeAndValidateTransactionWrite(DynamoDBTableMapper tableMappe actualResponseObjects = tableMapper.transactionLoad(transactionLoadRequest); break; } catch (TransactionCanceledException tce) { - List cancellationReasons = tce.getCancellationReasons(); + List cancellationReasons = tce.cancellationReasons(); Set uniqueCancellationReasonCodes = new HashSet(); for (CancellationReason cancellationReason: cancellationReasons) { - uniqueCancellationReasonCodes.add(cancellationReason.getCode()); + uniqueCancellationReasonCodes.add(cancellationReason.code()); } - if (uniqueCancellationReasonCodes.size() != 1 || !"TransactionConflict".equals(cancellationReasons.get(0).getCode())) { + if (uniqueCancellationReasonCodes.size() != 1 || !"TransactionConflict".equals(cancellationReasons.get(0).code())) { fail("transactionLoad failed with TransactionCanceledException having non-TransactionConflict cancellation reason(s): " + tce); } // Sleep for some time before re-trying transactionLoad diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteVersionAttributeTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteVersionAttributeTest.java index 5e1a9c6429be..700344482bab 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteVersionAttributeTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionWriteVersionAttributeTest.java @@ -20,11 +20,11 @@ import static software.amazon.awssdk.mapper.dynamodb.TestObjectCreator.getUniqueRangeKeyObject; import static org.junit.Assert.assertEquals; -import com.amazonaws.SdkClientException; +import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.mapper.dynamodb.TestObjectCreator; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTransactionWriteExpression; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.MultiVersionRangeKeyClass; import software.amazon.awssdk.mapper.dynamodb.pojos.RangeKeyClass; import org.junit.Rule; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionsTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionsTestBase.java index 004017a549f3..842d1832c345 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionsTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TransactionsTestBase.java @@ -24,16 +24,15 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.LocalDynamoDBTestBase; import java.util.List; -import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperIntegrationTestBase; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; import software.amazon.awssdk.mapper.dynamodb.TransactionLoadRequest; import software.amazon.awssdk.mapper.dynamodb.TransactionWriteRequest; -import com.amazonaws.services.dynamodbv2.model.TransactionCanceledException; +import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyAutoGenerated; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyBothAutoGenerated; import software.amazon.awssdk.mapper.dynamodb.pojos.HashKeyRangeKeyClass; @@ -82,7 +81,7 @@ public String getTableName(Class clazz, DynamoDBMapperConfig config) { }; protected static DynamoDBMapper dynamoMapper; - protected static AmazonDynamoDB dynamo; + protected static DynamoDbClient dynamo; @BeforeClass public static void setUp() throws Exception { diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypeConvertedJsonTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypeConvertedJsonTest.java index 4d5362d646b4..b4f83bce6250 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypeConvertedJsonTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypeConvertedJsonTest.java @@ -14,15 +14,17 @@ */ package software.amazon.awssdk.mapper.dynamodb.mapper; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import java.util.HashMap; +import java.util.Map; + +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConvertedJson; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,17 +41,17 @@ public class TypeConvertedJsonTest { private static final String HASH_KEY = "1234"; @Mock - private AmazonDynamoDB ddb; + private DynamoDbClient ddb; @Test public void responseWithUnmappedField_IgnoresUnknownFieldAndUnmarshallsCorrectly() { final DynamoDBMapper mapper = new DynamoDBMapper(ddb); + Map item = new HashMap<>(); + item.put("hashKey", AttributeValue.builder().s(HASH_KEY).build()); + item.put("jsonMappedPojo", AttributeValue.builder().s( + "{\"knownField\": \"knownValue\", \"unknownField\": \"unknownValue\"}").build()); when(ddb.getItem(any(GetItemRequest.class))) - .thenReturn(new GetItemResult().withItem( - ImmutableMapParameter.of("hashKey", new AttributeValue(HASH_KEY), - "jsonMappedPojo", new AttributeValue( - "{\"knownField\": \"knownValue\", \"unknownField\": \"unknownValue\"}") - ))); + .thenReturn(GetItemResponse.builder().item(item).build()); final TopLevelPojo pojo = mapper.load(new TopLevelPojo().setHashKey(HASH_KEY)); assertEquals("knownValue", pojo.getJsonMappedPojo().getKnownField()); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypedIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypedIntegrationTest.java index d2ff89856c30..d51193113a7e 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypedIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/TypedIntegrationTest.java @@ -22,7 +22,7 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTyped; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.mapper.dynamodb.pojos.AutoKeyAndVal; import java.util.HashMap; @@ -139,10 +139,10 @@ public void setVal(final AttributeValue val) { @Test public void testNativeMap() { final Map map = new HashMap(); - map.put("A", new AttributeValue().withN("123")); + map.put("A", AttributeValue.builder().n("123").build()); final KeyAndNativeValue object = new KeyAndNativeValue(); - object.setVal(new AttributeValue().withM(map)); + object.setVal(AttributeValue.builder().m(map).build()); assertBeforeAndAfterChange(false, object); } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/V2CompatibleBooleansTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/V2CompatibleBooleansTest.java index 0d356c1c2150..ca3f9548e524 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/V2CompatibleBooleansTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/V2CompatibleBooleansTest.java @@ -14,7 +14,10 @@ */ package software.amazon.awssdk.mapper.dynamodb.mapper; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import java.util.HashMap; +import java.util.Map; + +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.mapper.dynamodb.ConversionSchema; import software.amazon.awssdk.mapper.dynamodb.ConversionSchemas; import software.amazon.awssdk.mapper.dynamodb.DynamoDBAttribute; @@ -25,12 +28,11 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMappingException; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTyped; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.GetItemRequest; -import com.amazonaws.services.dynamodbv2.model.GetItemResult; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemResult; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; import org.junit.Before; import org.junit.Test; @@ -59,7 +61,7 @@ public class V2CompatibleBooleansTest { private static final String HASH_KEY = "1234"; @Mock - private AmazonDynamoDB ddb; + private DynamoDbClient ddb; /** * Mapper with default config. @@ -88,7 +90,7 @@ public void setup() { v1Mapper = buildMapper(ConversionSchemas.V1); v2Mapper = buildMapper(ConversionSchemas.V2); // Just stub dummy response for all save related tests - when(ddb.updateItem(any(UpdateItemRequest.class))).thenReturn(new UpdateItemResult()); + when(ddb.updateItem(any(UpdateItemRequest.class))).thenReturn(UpdateItemResponse.builder().build()); } private DynamoDBMapper buildMapper(ConversionSchema schema) { @@ -103,25 +105,25 @@ private DynamoDBMapper buildMapper(ConversionSchema schema) { @Test public void saveBooleanUsingDefaultConverters_MarshallsIntoNumber() { defaultMapper.save(new UnitTestPojo().setHashKey(HASH_KEY).setBooleanAttr(true)); - verifyAttributeUpdatedWithValue("booleanAttr", new AttributeValue().withN("1")); + verifyAttributeUpdatedWithValue("booleanAttr", AttributeValue.builder().n("1").build()); } @Test public void saveBooleanUsingV1Schema_MarshallsIntoNumber() { v1Mapper.save(new UnitTestPojo().setHashKey(HASH_KEY).setBooleanAttr(true)); - verifyAttributeUpdatedWithValue("booleanAttr", new AttributeValue().withN("1")); + verifyAttributeUpdatedWithValue("booleanAttr", AttributeValue.builder().n("1").build()); } @Test public void saveBooleanUsingV2Compat_MarshallsIntoNumber() { v2CompatMapper.save(new UnitTestPojo().setHashKey(HASH_KEY).setBooleanAttr(true)); - verifyAttributeUpdatedWithValue("booleanAttr", new AttributeValue().withN("1")); + verifyAttributeUpdatedWithValue("booleanAttr", AttributeValue.builder().n("1").build()); } @Test public void saveBooleanUsingV2Schema_MarshallsIntoNativeBool() { v2Mapper.save(new UnitTestPojo().setHashKey(HASH_KEY).setBooleanAttr(true)); - verifyAttributeUpdatedWithValue("booleanAttr", new AttributeValue().withBOOL(true)); + verifyAttributeUpdatedWithValue("booleanAttr", AttributeValue.builder().bool(true).build()); } /** @@ -150,7 +152,7 @@ public void saveCoercedNativeBooleanUsingV2_MarshallsIntoNativeBool() { private void saveCoercedNativeBoolean_MarshallsIntoNativeBoolean(DynamoDBMapper mapper) { mapper.save(new UnitTestPojo().setNativeBoolean(true).setHashKey(HASH_KEY)); - verifyAttributeUpdatedWithValue("nativeBoolean", new AttributeValue().withBOOL(true)); + verifyAttributeUpdatedWithValue("nativeBoolean", AttributeValue.builder().bool(true).build()); } /** @@ -178,7 +180,7 @@ public void saveCoercedNumericBooleanUsingV2_MarshallsIntoNumericBool() { private void saveCoercedNumericBoolean_MarshallsIntoNumericBoolean(DynamoDBMapper mapper) { mapper.save(new UnitTestPojo().setNumericBoolean(true).setHashKey(HASH_KEY)); - verifyAttributeUpdatedWithValue("numericBoolean", new AttributeValue().withN("1")); + verifyAttributeUpdatedWithValue("numericBoolean", AttributeValue.builder().n("1").build()); } @Test @@ -186,8 +188,8 @@ public void saveBooleanListUsingDefaultConverters_MarshallsIntoListOfNumbers() { defaultMapper.save(new UnitTestPojoWithList() .setBooleanList(Arrays.asList(Boolean.FALSE, Boolean.TRUE)) .setHashKey(HASH_KEY)); - verifyAttributeUpdatedWithValue("booleanList", new AttributeValue().withL(new AttributeValue().withN("0"), - new AttributeValue().withN("1"))); + verifyAttributeUpdatedWithValue("booleanList", AttributeValue.builder().l(AttributeValue.builder().n("0").build(), + AttributeValue.builder().n("1").build()).build()); } /** @@ -199,40 +201,40 @@ public void saveBooleanListUsingDefaultConverters_MarshallsIntoListOfNumbers() { private void verifyAttributeUpdatedWithValue(String attributeName, AttributeValue expected) { ArgumentCaptor updateItemRequestCaptor = ArgumentCaptor.forClass(UpdateItemRequest.class); verify(ddb).updateItem(updateItemRequestCaptor.capture()); - assertEquals(expected, updateItemRequestCaptor.getValue().getAttributeUpdates().get(attributeName).getValue()); + assertEquals(expected, updateItemRequestCaptor.getValue().attributeUpdates().get(attributeName).value()); } @Test public void loadNumericBooleanUsingDefaultConverters_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withN("1")); + stubGetItemRequest("booleanAttr", AttributeValue.builder().n("1").build()); final UnitTestPojo pojo = loadPojo(defaultMapper); assertTrue(pojo.getBooleanAttr()); } @Test public void loadNumericBooleanUsingV1Schema_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withN("1")); + stubGetItemRequest("booleanAttr", AttributeValue.builder().n("1").build()); final UnitTestPojo pojo = loadPojo(v1Mapper); assertTrue(pojo.getBooleanAttr()); } @Test public void loadNumericBooleanUsingV2CompatSchema_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withN("1")); + stubGetItemRequest("booleanAttr", AttributeValue.builder().n("1").build()); final UnitTestPojo pojo = loadPojo(v2CompatMapper); assertTrue(pojo.getBooleanAttr()); } @Test public void loadNumericBooleanUsingV2_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withN("1")); + stubGetItemRequest("booleanAttr", AttributeValue.builder().n("1").build()); final UnitTestPojo pojo = loadPojo(v2Mapper); assertTrue(pojo.getBooleanAttr()); } @Test public void loadNativeBooleanUsingDefaultConverters_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withBOOL(true)); + stubGetItemRequest("booleanAttr", AttributeValue.builder().bool(true).build()); final UnitTestPojo pojo = loadPojo(defaultMapper); assertTrue(pojo.getBooleanAttr()); } @@ -242,7 +244,7 @@ public void loadNativeBooleanUsingDefaultConverters_UnmarshallsCorrectly() { */ @Test(expected = DynamoDBMappingException.class) public void loadNativeBooleanUsingV1Schema_FailsToUnmarshall() { - stubGetItemRequest("booleanAttr", new AttributeValue().withBOOL(true)); + stubGetItemRequest("booleanAttr", AttributeValue.builder().bool(true).build()); loadPojo(v1Mapper); } @@ -251,30 +253,30 @@ public void loadNativeBooleanUsingV1Schema_FailsToUnmarshall() { */ @Test public void loadCoercedNativeBooleanUsingV1Schema_UnmarshallsCorrectly() { - stubGetItemRequest("nativeBoolean", new AttributeValue().withBOOL(true)); + stubGetItemRequest("nativeBoolean", AttributeValue.builder().bool(true).build()); final UnitTestPojo pojo = loadPojo(v1Mapper); assertTrue(pojo.getNativeBoolean()); } @Test public void loadNativeBooleanUsingV2CompatSchema_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withBOOL(true)); + stubGetItemRequest("booleanAttr", AttributeValue.builder().bool(true).build()); final UnitTestPojo pojo = loadPojo(v2CompatMapper); assertTrue(pojo.getBooleanAttr()); } @Test public void loadNativeBooleanUsingV2_UnmarshallsCorrectly() { - stubGetItemRequest("booleanAttr", new AttributeValue().withBOOL(true)); + stubGetItemRequest("booleanAttr", AttributeValue.builder().bool(true).build()); final UnitTestPojo pojo = loadPojo(v2Mapper); assertTrue(pojo.getBooleanAttr()); } @Test public void loadNativeBooleanListUsingDefaultConverters_UnmarshallsCorrectly() { - stubGetItemRequest("booleanList", new AttributeValue() - .withL(new AttributeValue().withBOOL(true), - new AttributeValue().withBOOL(false))); + stubGetItemRequest("booleanList", AttributeValue.builder() + .l(AttributeValue.builder().bool(true).build(), + AttributeValue.builder().bool(false).build()).build()); final UnitTestPojoWithList pojo = loadListPojo(defaultMapper); assertTrue(pojo.getBooleanList().get(0)); @@ -283,9 +285,9 @@ public void loadNativeBooleanListUsingDefaultConverters_UnmarshallsCorrectly() { @Test public void loadNumericBooleanListUsingDefaultConverters_UnmarshallsCorrectly() { - stubGetItemRequest("booleanList", new AttributeValue() - .withL(new AttributeValue().withN("1"), - new AttributeValue().withN("0"))); + stubGetItemRequest("booleanList", AttributeValue.builder() + .l(AttributeValue.builder().n("1").build(), + AttributeValue.builder().n("0").build()).build()); final UnitTestPojoWithList pojo = loadListPojo(defaultMapper); assertTrue(pojo.getBooleanList().get(0)); @@ -313,15 +315,16 @@ private void stubGetItemRequest(String attributeName, AttributeValue attributeVa } /** - * Create a {@link GetItemResult} with the hash key value ({@value #HASH_KEY} and the additional attribute. + * Create a {@link GetItemResponse} with the hash key value ({@value #HASH_KEY} and the additional attribute. * - * @param attributeName Additional attribute to include in created {@link GetItemResult}. + * @param attributeName Additional attribute to include in created {@link GetItemResponse}. * @param attributeValue Value of additional attribute. */ - private GetItemResult createGetItemResult(String attributeName, AttributeValue attributeValue) { - return new GetItemResult().withItem( - ImmutableMapParameter.of("hashKey", new AttributeValue(HASH_KEY), - attributeName, attributeValue)); + private GetItemResponse createGetItemResult(String attributeName, AttributeValue attributeValue) { + Map item = new HashMap<>(); + item.put("hashKey", AttributeValue.builder().s(HASH_KEY).build()); + item.put(attributeName, attributeValue); + return GetItemResponse.builder().item(item).build(); } @DynamoDBTable(tableName = "UnitTestTable") diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/VersionAttributeUpdateIntegrationTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/VersionAttributeUpdateIntegrationTest.java index dd1236505ee4..cf4438e8c09c 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/VersionAttributeUpdateIntegrationTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/VersionAttributeUpdateIntegrationTest.java @@ -32,11 +32,10 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBSaveExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; import software.amazon.awssdk.mapper.dynamodb.DynamoDBVersionAttribute; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; @@ -253,9 +252,9 @@ public void testBigIntegerVersion() { try { DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression(); Map expected = new HashMap(); - ExpectedAttributeValue expectedVersion = new ExpectedAttributeValue() - .withValue(new AttributeValue() - .withN(obj.getVersion().add(BigInteger.valueOf(1)).toString())); + ExpectedAttributeValue expectedVersion = ExpectedAttributeValue.builder() + .value(AttributeValue.builder() + .n(obj.getVersion().add(BigInteger.valueOf(1)).toString()).build()).build(); expected.put("version", expectedVersion); saveExpression.setExpected(expected); util.save(obj, saveExpression); @@ -367,9 +366,9 @@ public void testIntegerVersion() { try { DynamoDBDeleteExpression deleteExpression = new DynamoDBDeleteExpression(); Map expected = new HashMap(); - ExpectedAttributeValue expectedVersion = new ExpectedAttributeValue() - .withValue(new AttributeValue() - .withN("2")); //version is still 2 in db + ExpectedAttributeValue expectedVersion = ExpectedAttributeValue.builder() + .value(AttributeValue.builder() + .n("2").build()).build(); //version is still 2 in db expected.put("version", expectedVersion); deleteExpression.setExpected(expected); util.delete(obj, deleteExpression); @@ -394,7 +393,7 @@ public void testVersionedAttributeWithUserProvidedExpectedConditions() { // for auto-generated keys. DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression() .withExpected(Collections.singletonMap( - "otherAttribute", new ExpectedAttributeValue(false))) + "otherAttribute", ExpectedAttributeValue.builder().exists(false).build())) .withConditionalOperator(ConditionalOperator.AND); // The save should succeed since the user provided conditions are joined by AND. mapper.save(versionedObject, saveExpression); @@ -406,7 +405,7 @@ public void testVersionedAttributeWithUserProvidedExpectedConditions() { // delete should also work DynamoDBDeleteExpression deleteExpression = new DynamoDBDeleteExpression() .withExpected(Collections.singletonMap( - "otherAttribute", new ExpectedAttributeValue(false))) + "otherAttribute", ExpectedAttributeValue.builder().exists(false).build())) .withConditionalOperator(ConditionalOperator.AND); mapper.delete(versionedObject, deleteExpression); @@ -425,16 +424,12 @@ public void testVersionedAttributeWithUserProvidedExpectedConditions() { // User-provided OR conditions should work if they completely override // the generated conditions for the version field. - Map goodConditions = - ImmutableMapParameter.of( - "otherAttribute", new ExpectedAttributeValue(false), - "version", new ExpectedAttributeValue(false) - ); - Map badConditions = - ImmutableMapParameter.of( - "otherAttribute", new ExpectedAttributeValue(new AttributeValue("non-existent-value")), - "version", new ExpectedAttributeValue(new AttributeValue().withN("-1")) - ); + Map goodConditions = new HashMap(); + goodConditions.put("otherAttribute", ExpectedAttributeValue.builder().exists(false).build()); + goodConditions.put("version", ExpectedAttributeValue.builder().exists(false).build()); + Map badConditions = new HashMap(); + badConditions.put("otherAttribute", ExpectedAttributeValue.builder().value(AttributeValue.builder().s("non-existent-value").build()).build()); + badConditions.put("version", ExpectedAttributeValue.builder().value(AttributeValue.builder().n("-1").build()).build()); IntegerVersionField newObj = getUniqueObject(new IntegerVersionField()); saveExpression.setExpected(badConditions); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/AllSupportedAnnotationsClass.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/AllSupportedAnnotationsClass.java index 09f256757470..d2d77626d6c5 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/AllSupportedAnnotationsClass.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/AllSupportedAnnotationsClass.java @@ -32,7 +32,7 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConvertedJson; import software.amazon.awssdk.mapper.dynamodb.DynamoDBTypeConvertedEpochDate; -import com.amazonaws.services.dynamodbv2.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.KeyType; import java.util.Date; import java.util.UUID; diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/CrossSDKVerificationClass.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/CrossSDKVerificationClass.java deleted file mode 100644 index 6de86bce9ed6..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/pojos/CrossSDKVerificationClass.java +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2013 Amazon Technologies, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://aws.amazon.com/apache2.0 - * - * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES - * OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and - * limitations under the License. - */ -package software.amazon.awssdk.mapper.dynamodb.pojos; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Calendar; -import java.util.Date; -import java.util.Set; - -import software.amazon.awssdk.mapper.dynamodb.DynamoDBHashKey; -import software.amazon.awssdk.mapper.dynamodb.DynamoDBRangeKey; -import software.amazon.awssdk.mapper.dynamodb.DynamoDBTable; -import software.amazon.awssdk.mapper.dynamodb.DynamoDBVersionAttribute; - -/** - * Exhaustive exercise of DynamoDB domain mapping, exercising every supported - * data type. - */ -@DynamoDBTable(tableName = "aws-xsdk") -public class CrossSDKVerificationClass { - - private String key; - private String rangeKey; - private Long version; - private String lastUpdater; - - private Integer integerAttribute; - private Long longAttribute; - private Double doubleAttribute; - private Float floatAttribute; - private BigDecimal bigDecimalAttribute; - private BigInteger bigIntegerAttribute; - private Byte byteAttribute; - private Date dateAttribute; - private Calendar calendarAttribute; - private Boolean booleanAttribute; - - private Set stringSetAttribute; - private Set integerSetAttribute; - private Set doubleSetAttribute; - private Set floatSetAttribute; - private Set bigDecimalSetAttribute; - private Set bigIntegerSetAttribute; - private Set longSetAttribute; - private Set byteSetAttribute; - private Set dateSetAttribute; - private Set calendarSetAttribute; - - // these are kind of pointless, but here for completeness - private Set booleanSetAttribute; - - @DynamoDBHashKey - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - @DynamoDBRangeKey - public String getRangeKey() { - return rangeKey; - } - - public void setRangeKey(String rangeKey) { - this.rangeKey = rangeKey; - } - - @DynamoDBVersionAttribute - public Long getVersion() { - return version; - } - - public void setVersion(Long version) { - this.version = version; - } - - public String getLastUpdater() { - return lastUpdater; - } - - public void setLastUpdater(String lastUpdater) { - this.lastUpdater = lastUpdater; - } - - public Integer getIntegerAttribute() { - return integerAttribute; - } - - public void setIntegerAttribute(Integer integerAttribute) { - this.integerAttribute = integerAttribute; - } - - public Long getLongAttribute() { - return longAttribute; - } - - public void setLongAttribute(Long longAttribute) { - this.longAttribute = longAttribute; - } - - public Double getDoubleAttribute() { - return doubleAttribute; - } - - public void setDoubleAttribute(Double doubleAttribute) { - this.doubleAttribute = doubleAttribute; - } - - public Float getFloatAttribute() { - return floatAttribute; - } - - public void setFloatAttribute(Float floatAttribute) { - this.floatAttribute = floatAttribute; - } - - public BigDecimal getBigDecimalAttribute() { - return bigDecimalAttribute; - } - - public void setBigDecimalAttribute(BigDecimal bigDecimalAttribute) { - this.bigDecimalAttribute = bigDecimalAttribute; - } - - public BigInteger getBigIntegerAttribute() { - return bigIntegerAttribute; - } - - public void setBigIntegerAttribute(BigInteger bigIntegerAttribute) { - this.bigIntegerAttribute = bigIntegerAttribute; - } - - public Byte getByteAttribute() { - return byteAttribute; - } - - public void setByteAttribute(Byte byteAttribute) { - this.byteAttribute = byteAttribute; - } - - public Date getDateAttribute() { - return dateAttribute; - } - - public void setDateAttribute(Date dateAttribute) { - this.dateAttribute = dateAttribute; - } - - public Calendar getCalendarAttribute() { - return calendarAttribute; - } - - public void setCalendarAttribute(Calendar calendarAttribute) { - this.calendarAttribute = calendarAttribute; - } - - public Boolean getBooleanAttribute() { - return booleanAttribute; - } - - public void setBooleanAttribute(Boolean booleanAttribute) { - this.booleanAttribute = booleanAttribute; - } - - public Set getIntegerSetAttribute() { - return integerSetAttribute; - } - - public void setIntegerSetAttribute(Set integerSetAttribute) { - this.integerSetAttribute = integerSetAttribute; - } - - public Set getDoubleSetAttribute() { - return doubleSetAttribute; - } - - public void setDoubleSetAttribute(Set doubleSetAttribute) { - this.doubleSetAttribute = doubleSetAttribute; - } - - public Set getFloatSetAttribute() { - return floatSetAttribute; - } - - public void setFloatSetAttribute(Set floatSetAttribute) { - this.floatSetAttribute = floatSetAttribute; - } - - public Set getBigDecimalSetAttribute() { - return bigDecimalSetAttribute; - } - - public void setBigDecimalSetAttribute(Set bigDecimalSetAttribute) { - this.bigDecimalSetAttribute = bigDecimalSetAttribute; - } - - public Set getBigIntegerSetAttribute() { - return bigIntegerSetAttribute; - } - - public void setBigIntegerSetAttribute(Set bigIntegerSetAttribute) { - this.bigIntegerSetAttribute = bigIntegerSetAttribute; - } - - public Set getLongSetAttribute() { - return longSetAttribute; - } - - public void setLongSetAttribute(Set longSetAttribute) { - this.longSetAttribute = longSetAttribute; - } - - public Set getByteSetAttribute() { - return byteSetAttribute; - } - - public void setByteSetAttribute(Set byteSetAttribute) { - this.byteSetAttribute = byteSetAttribute; - } - - public Set getDateSetAttribute() { - return dateSetAttribute; - } - - public void setDateSetAttribute(Set dateSetAttribute) { - this.dateSetAttribute = dateSetAttribute; - } - - public Set getCalendarSetAttribute() { - return calendarSetAttribute; - } - - public void setCalendarSetAttribute(Set calendarSetAttribute) { - this.calendarSetAttribute = calendarSetAttribute; - } - - public Set getBooleanSetAttribute() { - return booleanSetAttribute; - } - - public void setBooleanSetAttribute(Set booleanSetAttribute) { - this.booleanSetAttribute = booleanSetAttribute; - } - - public Set getStringSetAttribute() { - return stringSetAttribute; - } - - public void setStringSetAttribute(Set stringSetAttribute) { - this.stringSetAttribute = stringSetAttribute; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((bigDecimalAttribute == null) ? 0 : bigDecimalAttribute.hashCode()); - result = prime * result + ((bigDecimalSetAttribute == null) ? 0 : bigDecimalSetAttribute.hashCode()); - result = prime * result + ((bigIntegerAttribute == null) ? 0 : bigIntegerAttribute.hashCode()); - result = prime * result + ((bigIntegerSetAttribute == null) ? 0 : bigIntegerSetAttribute.hashCode()); - result = prime * result + ((booleanAttribute == null) ? 0 : booleanAttribute.hashCode()); - result = prime * result + ((booleanSetAttribute == null) ? 0 : booleanSetAttribute.hashCode()); - result = prime * result + ((byteAttribute == null) ? 0 : byteAttribute.hashCode()); - result = prime * result + ((byteSetAttribute == null) ? 0 : byteSetAttribute.hashCode()); - result = prime * result + ((calendarAttribute == null) ? 0 : calendarAttribute.hashCode()); - result = prime * result + ((calendarSetAttribute == null) ? 0 : calendarSetAttribute.hashCode()); - result = prime * result + ((dateAttribute == null) ? 0 : dateAttribute.hashCode()); - result = prime * result + ((dateSetAttribute == null) ? 0 : dateSetAttribute.hashCode()); - result = prime * result + ((doubleAttribute == null) ? 0 : doubleAttribute.hashCode()); - result = prime * result + ((doubleSetAttribute == null) ? 0 : doubleSetAttribute.hashCode()); - result = prime * result + ((floatAttribute == null) ? 0 : floatAttribute.hashCode()); - result = prime * result + ((floatSetAttribute == null) ? 0 : floatSetAttribute.hashCode()); - result = prime * result + ((integerAttribute == null) ? 0 : integerAttribute.hashCode()); - result = prime * result + ((integerSetAttribute == null) ? 0 : integerSetAttribute.hashCode()); - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((lastUpdater == null) ? 0 : lastUpdater.hashCode()); - result = prime * result + ((longAttribute == null) ? 0 : longAttribute.hashCode()); - result = prime * result + ((longSetAttribute == null) ? 0 : longSetAttribute.hashCode()); - result = prime * result + ((rangeKey == null) ? 0 : rangeKey.hashCode()); - result = prime * result + ((stringSetAttribute == null) ? 0 : stringSetAttribute.hashCode()); - result = prime * result + ((version == null) ? 0 : version.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if ( this == obj ) - return true; - if ( obj == null ) - return false; - if ( getClass() != obj.getClass() ) - return false; - CrossSDKVerificationClass other = (CrossSDKVerificationClass) obj; - if ( bigDecimalAttribute == null ) { - if ( other.bigDecimalAttribute != null ) - return false; - } else if ( !bigDecimalAttribute.equals(other.bigDecimalAttribute) ) - return false; - if ( bigDecimalSetAttribute == null ) { - if ( other.bigDecimalSetAttribute != null ) - return false; - } else if ( !bigDecimalSetAttribute.equals(other.bigDecimalSetAttribute) ) - return false; - if ( bigIntegerAttribute == null ) { - if ( other.bigIntegerAttribute != null ) - return false; - } else if ( !bigIntegerAttribute.equals(other.bigIntegerAttribute) ) - return false; - if ( bigIntegerSetAttribute == null ) { - if ( other.bigIntegerSetAttribute != null ) - return false; - } else if ( !bigIntegerSetAttribute.equals(other.bigIntegerSetAttribute) ) - return false; - if ( booleanAttribute == null ) { - if ( other.booleanAttribute != null ) - return false; - } else if ( !booleanAttribute.equals(other.booleanAttribute) ) - return false; - if ( booleanSetAttribute == null ) { - if ( other.booleanSetAttribute != null ) - return false; - } else if ( !booleanSetAttribute.equals(other.booleanSetAttribute) ) - return false; - if ( byteAttribute == null ) { - if ( other.byteAttribute != null ) - return false; - } else if ( !byteAttribute.equals(other.byteAttribute) ) - return false; - if ( byteSetAttribute == null ) { - if ( other.byteSetAttribute != null ) - return false; - } else if ( !byteSetAttribute.equals(other.byteSetAttribute) ) - return false; - if ( calendarAttribute == null ) { - if ( other.calendarAttribute != null ) - return false; - } else if ( !calendarAttribute.equals(other.calendarAttribute) ) - return false; - if ( calendarSetAttribute == null ) { - if ( other.calendarSetAttribute != null ) - return false; - } else if ( !calendarSetAttribute.equals(other.calendarSetAttribute) ) - return false; - if ( dateAttribute == null ) { - if ( other.dateAttribute != null ) - return false; - } else if ( !dateAttribute.equals(other.dateAttribute) ) - return false; - if ( dateSetAttribute == null ) { - if ( other.dateSetAttribute != null ) - return false; - } else if ( !dateSetAttribute.equals(other.dateSetAttribute) ) - return false; - if ( doubleAttribute == null ) { - if ( other.doubleAttribute != null ) - return false; - } else if ( !doubleAttribute.equals(other.doubleAttribute) ) - return false; - if ( doubleSetAttribute == null ) { - if ( other.doubleSetAttribute != null ) - return false; - } else if ( !doubleSetAttribute.equals(other.doubleSetAttribute) ) - return false; - if ( floatAttribute == null ) { - if ( other.floatAttribute != null ) - return false; - } else if ( !floatAttribute.equals(other.floatAttribute) ) - return false; - if ( floatSetAttribute == null ) { - if ( other.floatSetAttribute != null ) - return false; - } else if ( !floatSetAttribute.equals(other.floatSetAttribute) ) - return false; - if ( integerAttribute == null ) { - if ( other.integerAttribute != null ) - return false; - } else if ( !integerAttribute.equals(other.integerAttribute) ) - return false; - if ( integerSetAttribute == null ) { - if ( other.integerSetAttribute != null ) - return false; - } else if ( !integerSetAttribute.equals(other.integerSetAttribute) ) - return false; - if ( key == null ) { - if ( other.key != null ) - return false; - } else if ( !key.equals(other.key) ) - return false; - if ( lastUpdater == null ) { - if ( other.lastUpdater != null ) - return false; - } else if ( !lastUpdater.equals(other.lastUpdater) ) - return false; - if ( longAttribute == null ) { - if ( other.longAttribute != null ) - return false; - } else if ( !longAttribute.equals(other.longAttribute) ) - return false; - if ( longSetAttribute == null ) { - if ( other.longSetAttribute != null ) - return false; - } else if ( !longSetAttribute.equals(other.longSetAttribute) ) - return false; - if ( rangeKey == null ) { - if ( other.rangeKey != null ) - return false; - } else if ( !rangeKey.equals(other.rangeKey) ) - return false; - if ( stringSetAttribute == null ) { - if ( other.stringSetAttribute != null ) - return false; - } else if ( !stringSetAttribute.equals(other.stringSetAttribute) ) - return false; - if ( version == null ) { - if ( other.version != null ) - return false; - } else if ( !version.equals(other.version) ) - return false; - return true; - } - -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java index 1667eb41a42b..d9545a37b53f 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeRequestTest.java @@ -19,22 +19,10 @@ import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.s; import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.verify; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.Request; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; -import com.amazonaws.handlers.RequestHandler2; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.ExpectedAttributeValue; -import com.amazonaws.services.dynamodbv2.model.Select; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -49,6 +37,15 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; import org.junit.runners.Parameterized.Parameters; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.exception.AbortedException; +import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.mapper.dynamodb.DynamoDBDeleteExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; @@ -69,6 +66,12 @@ import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.RangeItem; import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.StringItem; import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.VersionedItem; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.ExpectedAttributeValue; +import software.amazon.awssdk.services.dynamodb.model.Select; import software.amazon.awssdk.utils.IoUtils; /** Captures each mapper call's marshalled request (X-Amz-Target + JSON body) and asserts it against a committed fixture. */ @@ -199,11 +202,11 @@ public static List cases() { c.add(new Case(Operation.UPDATE_ITEM, "save-with-expected-expression", m -> m.save(stringItem("hello"), new DynamoDBSaveExpression() - .withExpectedEntry("value", new ExpectedAttributeValue().withExists(false))))); + .withExpectedEntry("value", ExpectedAttributeValue.builder().exists(false).build())))); c.add(new Case(Operation.DELETE_ITEM, "delete-with-expected-expression", m -> m.delete(stringItem("hello"), new DynamoDBDeleteExpression() - .withExpectedEntry("value", new ExpectedAttributeValue().withValue(s("hello")))))); + .withExpectedEntry("value", ExpectedAttributeValue.builder().value(s("hello")).build())))); c.add(new Case(Operation.DELETE_ITEM, "delete-with-condition-expression", m -> m.delete(stringItem("hello"), new DynamoDBDeleteExpression() .withConditionExpression("attribute_exists(#v)") @@ -212,9 +215,10 @@ public static List cases() { c.add(new Case(Operation.QUERY, "range-condition-limit-desc", m -> { RangeItem key = new RangeItem(); key.setId(HASH_KEY); - Condition rangeCond = new Condition() - .withComparisonOperator(ComparisonOperator.GT) - .withAttributeValueList(n("5")); + Condition rangeCond = Condition.builder() + .comparisonOperator(ComparisonOperator.GT) + .attributeValueList(n("5")) + .build(); m.query(RangeItem.class, new DynamoDBQueryExpression() .withHashKeyValues(key) .withRangeKeyCondition("range", rangeCond) @@ -234,9 +238,10 @@ public static List cases() { key.setId(HASH_KEY); m.query(StringItem.class, new DynamoDBQueryExpression() .withHashKeyValues(key) - .withQueryFilterEntry("value", new Condition() - .withComparisonOperator(ComparisonOperator.EQ) - .withAttributeValueList(s("hello")))); + .withQueryFilterEntry("value", Condition.builder() + .comparisonOperator(ComparisonOperator.EQ) + .attributeValueList(s("hello")) + .build())); })); c.add(new Case(Operation.QUERY, "exclusive-start-key", m -> { StringItem key = new StringItem(); @@ -264,9 +269,10 @@ public static List cases() { c.add(new Case(Operation.SCAN, "filtered-limited", m -> m.scan(StringItem.class, new DynamoDBScanExpression() - .withFilterConditionEntry("value", new Condition() - .withComparisonOperator(ComparisonOperator.EQ) - .withAttributeValueList(s("hello"))) + .withFilterConditionEntry("value", Condition.builder() + .comparisonOperator(ComparisonOperator.EQ) + .attributeValueList(s("hello")) + .build()) .withLimit(25)))); c.add(new Case(Operation.SCAN, "consistent-read", m -> m.scan(StringItem.class, new DynamoDBScanExpression().withConsistentRead(true)))); @@ -328,29 +334,35 @@ public void matchesFixture() { verify(testCase.operation.fixture, testCase.name, captureRequest(testCase.action)); } - // Captures the marshalled request as "target\nbody"; the v2 port swaps this for an ExecutionInterceptor. + // Captures the marshalled request as "target\nbody" via an afterMarshalling interceptor that aborts before transmission. private static String captureRequest(MapperAction action) { String[] captured = new String[1]; - RequestHandler2 handler = new RequestHandler2() { + ExecutionInterceptor handler = new ExecutionInterceptor() { @Override - public void beforeRequest(Request request) { - String target = request.getHeaders().get(TARGET_HEADER); - captured[0] = target + "\n" + readContent(request.getContent()); + public void afterMarshalling(Context.AfterMarshalling context, ExecutionAttributes executionAttributes) { + String target = context.httpRequest().firstMatchingHeader(TARGET_HEADER) + .orElseThrow(() -> new IllegalStateException("Marshalled request had no " + TARGET_HEADER + " header")); + captured[0] = target + "\n" + readContent(context.requestBody().orElse(null)); throw new StopSignal(); } }; - AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() - .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("akid", "skid"))) - .withEndpointConfiguration(new EndpointConfiguration("http://localhost:8000", "us-east-1")) - .withRequestHandlers(handler) + DynamoDbClient client = DynamoDbClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost:8000")) + .overrideConfiguration(c -> c.addExecutionInterceptor(handler)) .build(); DynamoDBMapper mapper = new DynamoDBMapper(client); try { action.run(mapper); } catch (StopSignal expected) { // request captured; network intentionally aborted - } catch (AmazonServiceException e) { - throw new IllegalStateException("Request reached the network instead of being captured", e); + } catch (AbortedException expected) { + // the core wraps the interceptor throw before transmission; request already captured + } catch (SdkException e) { + if (findStopSignal(e) == null) { + throw new IllegalStateException("Request reached the network instead of being captured", e); + } } if (captured[0] == null) { throw new IllegalStateException("No DynamoDB request was marshalled by the action"); @@ -358,17 +370,27 @@ public void beforeRequest(Request request) { return captured[0]; } + // The core may wrap an interceptor-thrown exception; walk the cause chain for our StopSignal. + private static StopSignal findStopSignal(Throwable t) { + for (Throwable c = t; c != null; c = c.getCause()) { + if (c instanceof StopSignal) { + return (StopSignal) c; + } + } + return null; + } + private static final class StopSignal extends RuntimeException { StopSignal() { super(null, null, false, false); } } - private static String readContent(InputStream content) { - if (content == null) { + private static String readContent(RequestBody body) { + if (body == null) { throw new IllegalStateException("Marshalled request had no body"); } - try { + try (InputStream content = body.contentStreamProvider().newStream()) { return new String(IoUtils.toByteArray(content), StandardCharsets.UTF_8); } catch (IOException e) { throw new UncheckedIOException(e); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java index fde3ea236e16..45ae81a733ac 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseTest.java @@ -26,7 +26,6 @@ import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.ss; import static software.amazon.awssdk.mapper.dynamodb.shape.ShapeSupport.verify; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.MapperFeature; @@ -42,6 +41,8 @@ import org.junit.runners.Parameterized.Parameters; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.AllTypesItem; import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.StringItem; @@ -50,7 +51,7 @@ public class ShapeResponseTest { private static final String FIXTURE = "unmarshall_item_fixture.json"; - private static final DynamoDBMapper MAPPER = new DynamoDBMapper((com.amazonaws.services.dynamodbv2.AmazonDynamoDB) null); + private static final DynamoDBMapper MAPPER = new DynamoDBMapper((DynamoDbClient) null); // NON_NULL keeps the fixture to the reconstructed attributes; alphabetical sort pins the reflection-ordered fields. private static final ObjectMapper READ_JSON = new ObjectMapper() diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java index 0cff63c122fa..b57b164f7572 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeSupport.java @@ -16,7 +16,6 @@ import static org.junit.Assert.assertEquals; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -25,6 +24,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.utils.IoUtils; // Fixture assertion and AttributeValue builders shared by ShapeRequestTest and ShapeResponseTest. @@ -71,27 +71,27 @@ static Map item(String attr, AttributeValue value) { } static AttributeValue s(String v) { - return new AttributeValue().withS(v); + return AttributeValue.builder().s(v).build(); } static AttributeValue n(String v) { - return new AttributeValue().withN(v); + return AttributeValue.builder().n(v).build(); } static AttributeValue bool(boolean v) { - return new AttributeValue().withBOOL(v); + return AttributeValue.builder().bool(v).build(); } static AttributeValue ss(String... v) { - return new AttributeValue().withSS(v); + return AttributeValue.builder().ss(v).build(); } static AttributeValue ns(String... v) { - return new AttributeValue().withNS(v); + return AttributeValue.builder().ns(v).build(); } static AttributeValue l(AttributeValue... v) { - return new AttributeValue().withL(v); + return AttributeValue.builder().l(v).build(); } @SafeVarargs @@ -100,7 +100,7 @@ static AttributeValue m(Map.Entry... entries) { for (Map.Entry e : entries) { map.put(e.getKey(), e.getValue()); } - return new AttributeValue().withM(map); + return AttributeValue.builder().m(map).build(); } static Map.Entry entry(String k, AttributeValue v) { diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/AWSTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/AWSTestBase.java index a791f6308eb9..5200df6e39f9 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/AWSTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/AWSTestBase.java @@ -19,19 +19,19 @@ import java.io.IOException; import java.io.InputStream; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSCredentialsProviderChain; -import com.amazonaws.auth.EnvironmentVariableCredentialsProvider; -import com.amazonaws.auth.PropertiesFileCredentialsProvider; -import com.amazonaws.auth.SystemPropertiesCredentialsProvider; -import com.amazonaws.auth.profile.ProfileCredentialsProvider; +import software.amazon.awssdk.auth.credentials.AwsCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.auth.credentials.EnvironmentVariableCredentialsProvider; +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +import software.amazon.awssdk.auth.credentials.SystemPropertyCredentialsProvider; +import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.mapper.dynamodb.test.util.InputStreamUtils; import software.amazon.awssdk.mapper.dynamodb.test.util.SdkAsserts; -import com.amazonaws.util.IOUtils; +import software.amazon.awssdk.utils.IoUtils; import java.util.concurrent.TimeUnit; -import com.amazonaws.util.StringUtils; +import software.amazon.awssdk.utils.StringUtils; import org.junit.Rule; public abstract class AWSTestBase { @@ -43,13 +43,12 @@ public abstract class AWSTestBase { * @deprecated Extend from {@link AWSIntegrationTestBase} to access credentials */ @Deprecated - public static AWSCredentials credentials; + public static AwsCredentials credentials; - /** Default Properties Credentials file path */ - private static final String propertiesFilePath = System.getProperty("user.home") - + "/.aws/awsTestAccount.properties"; - - private static final String TEST_CREDENTIALS_PROFILE_NAME = "aws-java-sdk-test"; + // Matches the profile that v2's shared AwsIntegrationTestBase/AwsTestBase resolve, and the profile the + // catapult release/PR buildspec writes credentials under (alongside [default]). See + // test/service-test-utils AwsIntegrationTestBase and AwsSdkJava2CatapultCDK test-specs. + private static final String TEST_CREDENTIALS_PROFILE_NAME = "aws-test-account"; /** * ToD test can be configured to use Role ARN and will pull them from STS. These credentials are then available @@ -59,7 +58,7 @@ public abstract class AWSTestBase { private static final String TOD_CREDENTIAL_PATH = System.getenv("TOD_CUSTOMER_CREDENTIAL_PATH"); - private static final AWSCredentialsProviderChain chain = createChain(); + private static final AwsCredentialsProviderChain chain = createChain(); @Rule public RetryRule retry = new RetryRule(3, 2, TimeUnit.SECONDS); @@ -71,7 +70,7 @@ public abstract class AWSTestBase { public static void setUpCredentials() { if (credentials == null) { try { - credentials = chain.getCredentials(); + credentials = chain.resolveCredentials(); } catch (Exception ignored) { } } @@ -93,7 +92,7 @@ protected void setRetryRule(RetryRule rule) { protected String getResourceAsString(String location) { try { InputStream resourceStream = getClass().getResourceAsStream(location); - String resourceAsString = IOUtils.toString(resourceStream); + String resourceAsString = IoUtils.toUtf8String(resourceStream); resourceStream.close(); return resourceAsString; } catch (Exception e) { @@ -185,23 +184,22 @@ protected boolean doesFileEqualStream(File expectedFile, InputStream inputStream * @deprecated Use static imports for custom asserts in {@link SdkAsserts} instead */ @Deprecated - protected void assertValidException(AmazonServiceException e) { + protected void assertValidException(AwsServiceException e) { SdkAsserts.assertValidException(e); } - private static AWSCredentialsProviderChain createChain() { - if (StringUtils.isNullOrEmpty(TOD_CREDENTIAL_PATH)) { - return new AWSCredentialsProviderChain( - new PropertiesFileCredentialsProvider(propertiesFilePath), - new ProfileCredentialsProvider(TEST_CREDENTIALS_PROFILE_NAME), - new EnvironmentVariableCredentialsProvider(), - new SystemPropertiesCredentialsProvider()); + private static AwsCredentialsProviderChain createChain() { + if (StringUtils.isBlank(TOD_CREDENTIAL_PATH)) { + // Mirror v2's shared AwsIntegrationTestBase: the aws-test-account profile first, then the default + // provider chain (env vars, system properties, the [default] profile, and container/instance creds). + return AwsCredentialsProviderChain.of( + ProfileCredentialsProvider.create(TEST_CREDENTIALS_PROFILE_NAME), + DefaultCredentialsProvider.create()); } - return new AWSCredentialsProviderChain( - new ProfileCredentialsProvider(TOD_CREDENTIAL_PATH, "default"), - new PropertiesFileCredentialsProvider(propertiesFilePath), - new ProfileCredentialsProvider(TEST_CREDENTIALS_PROFILE_NAME), - new EnvironmentVariableCredentialsProvider(), - new SystemPropertiesCredentialsProvider()); + return AwsCredentialsProviderChain.of( + ProfileCredentialsProvider.create("default"), + ProfileCredentialsProvider.create(TEST_CREDENTIALS_PROFILE_NAME), + EnvironmentVariableCredentialsProvider.create(), + SystemPropertyCredentialsProvider.create()); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/retry/RetryRule.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/retry/RetryRule.java index 9683f88c7e1c..25c820efb314 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/retry/RetryRule.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/retry/RetryRule.java @@ -14,7 +14,7 @@ */ package software.amazon.awssdk.mapper.dynamodb.test.retry; -import com.amazonaws.util.ValidationUtils; +import software.amazon.awssdk.utils.Validate; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; @@ -34,7 +34,7 @@ public RetryRule(int maxRetryAttempts) { public RetryRule(int maxRetryAttempts, long delay, TimeUnit timeUnit) { this.maxRetryAttempts = maxRetryAttempts; this.delay = delay; - this.timeUnit = ValidationUtils.assertNotNull(timeUnit, "timeUnit"); + this.timeUnit = Validate.paramNotNull(timeUnit, "timeUnit"); } @Override diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBIntegrationTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBIntegrationTestBase.java index 03435d905ed5..683fd3c83c01 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBIntegrationTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBIntegrationTestBase.java @@ -16,19 +16,18 @@ import org.junit.BeforeClass; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ListTablesResult; -import com.amazonaws.services.dynamodbv2.model.LocalSecondaryIndex; -import com.amazonaws.services.dynamodbv2.model.Projection; -import com.amazonaws.services.dynamodbv2.model.ProjectionType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.util.TableUtils; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse; +import software.amazon.awssdk.services.dynamodb.model.LocalSecondaryIndex; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; public class DynamoDBIntegrationTestBase extends DynamoDBTestBase { @@ -42,23 +41,36 @@ public class DynamoDBIntegrationTestBase extends DynamoDBTestBase { @BeforeClass public static void setUp() throws Exception { - setUpCredentials(); - dynamo = new AmazonDynamoDBClient(credentials); - dynamo.setEndpoint(ENDPOINT); + setUpTestBase(); // Create a table String keyName = KEY_NAME; - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_NAME) - .withKeySchema(new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(keyName).withAttributeType( - ScalarAttributeType.S)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(10L) - .withWriteCapacityUnits(5L)); - - if (TableUtils.createTableIfNotExists(dynamo, createTableRequest)) { - TableUtils.waitUntilActive(dynamo, TABLE_NAME); + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(TABLE_NAME) + .keySchema(KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName(keyName) + .attributeType(ScalarAttributeType.S).build()) + .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L) + .writeCapacityUnits(5L).build()) + .build(); + + if (createTableIfNotExists(createTableRequest)) { + dynamo.waiter().waitUntilTableExists(b -> b.tableName(TABLE_NAME)); + } + } + + /** + * Creates the table if it does not already exist. Returns true if a create was issued, + * false if the table already existed. + */ + private static boolean createTableIfNotExists(CreateTableRequest createTableRequest) { + try { + dynamo.createTable(createTableRequest); + return true; + } catch (ResourceInUseException e) { + // Table already exists. + return false; } } @@ -67,9 +79,9 @@ public static void setUp() throws Exception { * reserved for the region. */ public static void deleteAllTables() { - ListTablesResult listTables = dynamo.listTables(); - for (String name : listTables.getTableNames()) { - dynamo.deleteTable(new DeleteTableRequest().withTableName(name)); + ListTablesResponse listTables = dynamo.listTables(); + for (String name : listTables.tableNames()) { + dynamo.deleteTable(DeleteTableRequest.builder().tableName(name).build()); } } @@ -78,27 +90,28 @@ protected static void setUpTableWithRangeAttribute() throws Exception { String keyName = DynamoDBIntegrationTestBase.KEY_NAME; String rangeKeyAttributeName = "rangeKey"; - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_WITH_RANGE_ATTRIBUTE) - .withKeySchema(new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(rangeKeyAttributeName).withKeyType(KeyType.RANGE)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(keyName).withAttributeType( - ScalarAttributeType.N), - new AttributeDefinition().withAttributeName(rangeKeyAttributeName).withAttributeType( - ScalarAttributeType.N)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(10L) - .withWriteCapacityUnits(5L)); - - if (TableUtils.createTableIfNotExists(dynamo, createTableRequest)) { - TableUtils.waitUntilActive(dynamo, TABLE_WITH_RANGE_ATTRIBUTE); + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(TABLE_WITH_RANGE_ATTRIBUTE) + .keySchema(KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(rangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName(keyName) + .attributeType(ScalarAttributeType.N).build(), + AttributeDefinition.builder().attributeName(rangeKeyAttributeName) + .attributeType(ScalarAttributeType.N).build()) + .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L) + .writeCapacityUnits(5L).build()) + .build(); + + if (createTableIfNotExists(createTableRequest)) { + dynamo.waiter().waitUntilTableExists(b -> b.tableName(TABLE_WITH_RANGE_ATTRIBUTE)); } } protected static void setUpTableWithIndexRangeAttribute(boolean recreateTable) throws Exception { setUp(); if (recreateTable) { - dynamo.deleteTable(new DeleteTableRequest().withTableName(TABLE_WITH_INDEX_RANGE_ATTRIBUTE)); + dynamo.deleteTable(DeleteTableRequest.builder().tableName(TABLE_WITH_INDEX_RANGE_ATTRIBUTE).build()); waitForTableToBecomeDeleted(TABLE_WITH_INDEX_RANGE_ATTRIBUTE); } @@ -114,55 +127,60 @@ protected static void setUpTableWithIndexRangeAttribute(boolean recreateTable) t String indexFooCopyName = "index_foo_copy"; String indexBarCopyName = "index_bar_copy"; - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_WITH_INDEX_RANGE_ATTRIBUTE) - .withKeySchema( - new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(rangeKeyAttributeName).withKeyType(KeyType.RANGE)) - .withLocalSecondaryIndexes( - new LocalSecondaryIndex() - .withIndexName(indexFooName) - .withKeySchema( - new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(indexFooRangeKeyAttributeName).withKeyType(KeyType.RANGE)) - .withProjection(new Projection() - .withProjectionType(ProjectionType.INCLUDE) - .withNonKeyAttributes(fooAttributeName)), - new LocalSecondaryIndex() - .withIndexName(indexBarName) - .withKeySchema( - new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(indexBarRangeKeyAttributeName).withKeyType(KeyType.RANGE)) - .withProjection(new Projection() - .withProjectionType(ProjectionType.INCLUDE) - .withNonKeyAttributes(barAttributeName)), - new LocalSecondaryIndex() - .withIndexName(indexFooCopyName) - .withKeySchema( - new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(multipleIndexRangeKeyAttributeName).withKeyType(KeyType.RANGE)) - .withProjection(new Projection() - .withProjectionType(ProjectionType.INCLUDE) - .withNonKeyAttributes(fooAttributeName)), - new LocalSecondaryIndex() - .withIndexName(indexBarCopyName) - .withKeySchema( - new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH), - new KeySchemaElement().withAttributeName(multipleIndexRangeKeyAttributeName).withKeyType(KeyType.RANGE)) - .withProjection(new Projection() - .withProjectionType(ProjectionType.INCLUDE) - .withNonKeyAttributes(barAttributeName))) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(keyName).withAttributeType(ScalarAttributeType.N), - new AttributeDefinition().withAttributeName(rangeKeyAttributeName).withAttributeType(ScalarAttributeType.N), - new AttributeDefinition().withAttributeName(indexFooRangeKeyAttributeName).withAttributeType(ScalarAttributeType.N), - new AttributeDefinition().withAttributeName(indexBarRangeKeyAttributeName).withAttributeType(ScalarAttributeType.N), - new AttributeDefinition().withAttributeName(multipleIndexRangeKeyAttributeName).withAttributeType(ScalarAttributeType.N)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(10L) - .withWriteCapacityUnits(5L)); - - if (TableUtils.createTableIfNotExists(dynamo, createTableRequest)) { - TableUtils.waitUntilActive(dynamo, TABLE_WITH_INDEX_RANGE_ATTRIBUTE); + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(TABLE_WITH_INDEX_RANGE_ATTRIBUTE) + .keySchema( + KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(rangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .localSecondaryIndexes( + LocalSecondaryIndex.builder() + .indexName(indexFooName) + .keySchema( + KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(indexFooRangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .projection(Projection.builder() + .projectionType(ProjectionType.INCLUDE) + .nonKeyAttributes(fooAttributeName).build()) + .build(), + LocalSecondaryIndex.builder() + .indexName(indexBarName) + .keySchema( + KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(indexBarRangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .projection(Projection.builder() + .projectionType(ProjectionType.INCLUDE) + .nonKeyAttributes(barAttributeName).build()) + .build(), + LocalSecondaryIndex.builder() + .indexName(indexFooCopyName) + .keySchema( + KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(multipleIndexRangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .projection(Projection.builder() + .projectionType(ProjectionType.INCLUDE) + .nonKeyAttributes(fooAttributeName).build()) + .build(), + LocalSecondaryIndex.builder() + .indexName(indexBarCopyName) + .keySchema( + KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build(), + KeySchemaElement.builder().attributeName(multipleIndexRangeKeyAttributeName).keyType(KeyType.RANGE).build()) + .projection(Projection.builder() + .projectionType(ProjectionType.INCLUDE) + .nonKeyAttributes(barAttributeName).build()) + .build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName(keyName).attributeType(ScalarAttributeType.N).build(), + AttributeDefinition.builder().attributeName(rangeKeyAttributeName).attributeType(ScalarAttributeType.N).build(), + AttributeDefinition.builder().attributeName(indexFooRangeKeyAttributeName).attributeType(ScalarAttributeType.N).build(), + AttributeDefinition.builder().attributeName(indexBarRangeKeyAttributeName).attributeType(ScalarAttributeType.N).build(), + AttributeDefinition.builder().attributeName(multipleIndexRangeKeyAttributeName).attributeType(ScalarAttributeType.N).build()) + .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L) + .writeCapacityUnits(5L).build()) + .build(); + + if (createTableIfNotExists(createTableRequest)) { + dynamo.waiter().waitUntilTableExists(b -> b.tableName(TABLE_WITH_INDEX_RANGE_ATTRIBUTE)); } } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBTestBase.java index bc29a0caa2d6..03ce574935b1 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBTestBase.java @@ -24,21 +24,23 @@ import java.util.Map; import java.util.Set; -import com.amazonaws.AmazonClientException; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest; -import com.amazonaws.services.dynamodbv2.model.TableDescription; -import com.amazonaws.services.dynamodbv2.model.TableStatus; +import java.net.URI; + +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.TableDescription; +import software.amazon.awssdk.services.dynamodb.model.TableStatus; import software.amazon.awssdk.mapper.dynamodb.test.AWSTestBase; public class DynamoDBTestBase extends AWSTestBase { protected static final String ENDPOINT = "http://dynamodb.us-east-1.amazonaws.com/"; - protected static AmazonDynamoDBClient dynamo; + protected static DynamoDbClient dynamo; /** * Gets a map of key values for the single hash key attribute value given. @@ -53,14 +55,17 @@ public static void setUpTestBase() { try { setUpCredentials(); } catch (Exception e) { - throw new AmazonClientException("Unable to load credential property file.", e); + throw SdkClientException.create("Unable to load credential property file.", e); } - - dynamo = new AmazonDynamoDBClient(credentials); - dynamo.setEndpoint(ENDPOINT); + + dynamo = DynamoDbClient.builder() + .credentialsProvider(StaticCredentialsProvider.create(credentials)) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(ENDPOINT)) + .build(); } - public static AmazonDynamoDB getClient() { + public static DynamoDbClient getClient() { if (dynamo == null) { setUpTestBase(); } @@ -71,7 +76,7 @@ protected static void waitForTableToBecomeDeleted(String tableName) { waitForTableToBecomeDeleted(dynamo, tableName); } - public static void waitForTableToBecomeDeleted(AmazonDynamoDB dynamo, String tableName) { + public static void waitForTableToBecomeDeleted(DynamoDbClient dynamo, String tableName) { System.out.println("Waiting for " + tableName + " to become Deleted..."); long startTime = System.currentTimeMillis(); @@ -82,15 +87,14 @@ public static void waitForTableToBecomeDeleted(AmazonDynamoDB dynamo, String tab } catch ( Exception e ) { } try { - DescribeTableRequest request = new DescribeTableRequest().withTableName(tableName); - TableDescription table = dynamo.describeTable(request).getTable(); + TableDescription table = dynamo.describeTable(b -> b.tableName(tableName)).table(); - String tableStatus = table.getTableStatus(); + TableStatus tableStatus = table.tableStatus(); System.out.println(" - current state: " + tableStatus); - if ( tableStatus.equals(TableStatus.DELETING.toString()) ) + if ( tableStatus == TableStatus.DELETING ) continue; - } catch ( AmazonServiceException ase ) { - if ( ase.getErrorCode().equalsIgnoreCase("ResourceNotFoundException") == true ){ + } catch ( AwsServiceException ase ) { + if ( "ResourceNotFoundException".equalsIgnoreCase(ase.awsErrorDetails().errorCode()) ){ System.out.println("successfully deleted"); return; } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBUnitTestBase.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBUnitTestBase.java index 134ff42e7688..ef48c44caf0d 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBUnitTestBase.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/DynamoDBUnitTestBase.java @@ -15,21 +15,24 @@ */ package software.amazon.awssdk.mapper.dynamodb.test.util; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.local.embedded.DynamoDBEmbedded; +import com.amazonaws.services.dynamodbv2.local.shared.access.AmazonDynamoDBLocal; import org.junit.AfterClass; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; public class DynamoDBUnitTestBase extends DynamoDBTestBase { - protected static AmazonDynamoDB dynamoDB; + protected static AmazonDynamoDBLocal embedded; + protected static DynamoDbClient dynamoDB; public static void setUp() { - dynamoDB = DynamoDBEmbedded.create().amazonDynamoDB(); + embedded = DynamoDBEmbedded.create(); + dynamoDB = embedded.dynamoDbClient(); } @AfterClass public static void shutDown() { - dynamoDB.shutdown(); + embedded.shutdown(); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/InputStreamUtils.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/InputStreamUtils.java index 54b3517511a9..e3925d722b39 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/InputStreamUtils.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/InputStreamUtils.java @@ -21,7 +21,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import com.amazonaws.util.IOUtils; +import software.amazon.awssdk.utils.IoUtils; public class InputStreamUtils { @@ -59,7 +59,7 @@ public static byte[] drainInputStream(InputStream inputStream) { } catch (IOException e) { throw new RuntimeException(e); } finally { - IOUtils.closeQuietly(byteArrayOutputStream, null); + IoUtils.closeQuietly(byteArrayOutputStream, null); } } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/ProgressListenerWithEventCodeVerification.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/ProgressListenerWithEventCodeVerification.java deleted file mode 100644 index edf4fcedb133..000000000000 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/ProgressListenerWithEventCodeVerification.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2010-2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ -package software.amazon.awssdk.mapper.dynamodb.test.util; - -import com.amazonaws.event.ProgressEvent; -import com.amazonaws.event.ProgressEventType; -import com.amazonaws.event.SyncProgressListener; -/** - * Validates the events received by the progress listener. - */ -public class ProgressListenerWithEventCodeVerification extends - SyncProgressListener { - private final ProgressEventType[] types; - private int count; - - public ProgressListenerWithEventCodeVerification(ProgressEventType... types) { - this.types = types.clone(); - } - - @Override - public void progressChanged(ProgressEvent progressEvent) { - ProgressEventType type = progressEvent.getEventType(); - if (type.isByteCountEvent()) - return; - if (type != types[count]) { - throw new AssertionError("Expect event type " - + types[count] + " but got " - + progressEvent.getEventType()); - } - count++; - } - - public void reset() { - count = 0; - } -} diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/SdkAsserts.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/SdkAsserts.java index 3dac4eb0677b..e688d9152b9d 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/SdkAsserts.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/test/util/SdkAsserts.java @@ -30,9 +30,9 @@ import org.junit.Assert; -import com.amazonaws.AmazonClientException; -import com.amazonaws.AmazonServiceException; -import com.amazonaws.util.IOUtils; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.utils.IoUtils; public class SdkAsserts { @@ -194,10 +194,10 @@ public static boolean doesStreamEqualStream(InputStream expected, InputStream ac return Arrays.equals(expectedDigest, actualDigest); } catch (NoSuchAlgorithmException nse) { - throw new AmazonClientException(nse.getMessage(), nse); + throw SdkClientException.create(nse.getMessage(), nse); } finally { - IOUtils.closeQuietly(expected, null); - IOUtils.closeQuietly(actual, null); + IoUtils.closeQuietly(expected, null); + IoUtils.closeQuietly(actual, null); } } @@ -220,24 +220,25 @@ public static boolean doesFileEqualStream(File expectedFile, InputStream inputSt } /** - * Asserts that the specified AmazonServiceException is valid, meaning it has a non-empty, + * Asserts that the specified AwsServiceException is valid, meaning it has a non-empty, * non-null value for its message, requestId, etc. * * @param e * The exception to validate. */ - public static void assertValidException(AmazonServiceException e) { - assertNotNull(e.getRequestId()); - assertTrue(e.getRequestId().trim().length() > 0); + public static void assertValidException(AwsServiceException e) { + assertNotNull(e.requestId()); + assertTrue(e.requestId().trim().length() > 0); assertNotNull(e.getMessage()); assertTrue(e.getMessage().trim().length() > 0); - assertNotNull(e.getErrorCode()); - assertTrue(e.getErrorCode().trim().length() > 0); + assertNotNull(e.awsErrorDetails().errorCode()); + assertTrue(e.awsErrorDetails().errorCode().trim().length() > 0); - assertNotNull(e.getServiceName()); - assertTrue(e.getServiceName().startsWith("Amazon") || e.getServiceName().startsWith("AWS")); + assertNotNull(e.awsErrorDetails().serviceName()); + assertTrue(e.awsErrorDetails().serviceName().startsWith("Amazon") + || e.awsErrorDetails().serviceName().startsWith("AWS")); } } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/AttributeAdder.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/AttributeAdder.java index bf9b9487753e..049c4a3f460d 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/AttributeAdder.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/AttributeAdder.java @@ -17,7 +17,7 @@ package software.amazon.awssdk.mapper.dynamodb.utils; import software.amazon.awssdk.mapper.dynamodb.AttributeTransformer; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import java.util.HashMap; import java.util.Map; @@ -35,7 +35,7 @@ public AttributeAdder(String attributeName, int start) { @Override public Map transform(final Parameters parameters) { Map rval = new HashMap(parameters.getAttributeValues()); - rval.put(additionalAttribute, new AttributeValue().withN(String.valueOf(start++))); + rval.put(additionalAttribute, AttributeValue.builder().n(String.valueOf(start++)).build()); return rval; } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/NullAttributeAdder.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/NullAttributeAdder.java index 02a7034cf596..cf525e37bed4 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/NullAttributeAdder.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/utils/NullAttributeAdder.java @@ -17,7 +17,7 @@ package software.amazon.awssdk.mapper.dynamodb.utils; import software.amazon.awssdk.mapper.dynamodb.AttributeTransformer; -import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import java.util.HashMap; import java.util.Map; From 13ad4c3e1376ac689f65c2749d7d42b1f2cb3464 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 13 Aug 2026 11:43:38 -0700 Subject: [PATCH 3/5] Add test coverage --- .../mapper/dynamodb/DynamoDBMapper.java | 2 - .../mapper/dynamodb/IDynamoDBMapper.java | 36 ++--- .../dynamodb/BatchLoadRetryStrategyTest.java | 24 ++++ .../dynamodb/PaginatedScanTaskTest.java | 45 ++++++ .../shape/ShapeResponseBehaviorTest.java | 133 ++++++++++++++++++ 5 files changed, 217 insertions(+), 23 deletions(-) create mode 100644 services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java index be2d94e0339e..f2327dd596c4 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java @@ -1004,8 +1004,6 @@ private Map transformAttributeUpdates( AttributeValueUpdate update = updateValues.get(entry.getKey()); if (update != null) { - // v2 model types are immutable; replace the update's value - // with the transformed AttributeValue rather than mutating. updateValues.put(entry.getKey(), update.toBuilder().value(entry.getValue()).build()); } else { diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/IDynamoDBMapper.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/IDynamoDBMapper.java index 3ee09808c77a..dba27bf1f635 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/IDynamoDBMapper.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/IDynamoDBMapper.java @@ -19,14 +19,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.PaginationLoadingStrategy; import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapperConfig.SaveBehavior; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import com.amazonaws.services.dynamodbv2.model.BatchGetItemRequest; -import com.amazonaws.services.dynamodbv2.model.BatchWriteItemRequest; import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; -import com.amazonaws.services.dynamodbv2.model.PutItemRequest; -import com.amazonaws.services.dynamodbv2.model.TransactGetItemsRequest; -import com.amazonaws.services.dynamodbv2.model.TransactWriteItemsRequest; -import com.amazonaws.services.dynamodbv2.model.UpdateItemRequest; import com.amazonaws.services.s3.model.Region; import java.util.List; @@ -165,8 +159,8 @@ public interface IDynamoDBMapper { /** * Saves an item in DynamoDB. The service method used is determined by the * {@link DynamoDBMapperConfig#getSaveBehavior()} value, to use either - * {@link AmazonDynamoDB#putItem(PutItemRequest)} or - * {@link AmazonDynamoDB#updateItem(UpdateItemRequest)}: + * {@link AmazonDynamoDB#putItem} or + * {@link AmazonDynamoDB#updateItem}: *
    *
  • UPDATE (default) : UPDATE will not affect unmodeled attributes on a save operation * and a null value for the modeled attribute will remove it from that item in DynamoDB. Because @@ -223,7 +217,7 @@ public interface IDynamoDBMapper { void delete(T object, DynamoDBDeleteExpression deleteExpression, DynamoDBMapperConfig config); /** - * Transactionally writes objects specified by transactionWriteRequest by calling {@link AmazonDynamoDB#transactWriteItems(TransactWriteItemsRequest)} API. + * Transactionally writes objects specified by transactionWriteRequest by calling {@link AmazonDynamoDB#transactWriteItems} API. * Changes to objects which are put or updated are applied in-memory. Such in-memory updates are NOT thread safe. *

    * This method ignores any SaveBehavior set on the mapper. Whether an object is put or updated is solely determined by the @@ -248,7 +242,7 @@ public interface IDynamoDBMapper { void transactionWrite(TransactionWriteRequest transactionWriteRequest); /** - * Transactionally writes objects specified by transactionWriteRequest by calling {@link AmazonDynamoDB#transactWriteItems(TransactWriteItemsRequest)} API. + * Transactionally writes objects specified by transactionWriteRequest by calling {@link AmazonDynamoDB#transactWriteItems} API. * Changes to objects which are put or updated are applied in-memory. Such in-memory updates are NOT thread safe. *

    * This method ignores any SaveBehavior set on the mapper. Whether an object is put or updated is solely determined by the @@ -278,7 +272,7 @@ public interface IDynamoDBMapper { void transactionWrite(TransactionWriteRequest transactionWriteRequest, DynamoDBMapperConfig config); /** - * Transactionally loads objects specified by transactionLoadRequest by calling {@link AmazonDynamoDB#transactGetItems(TransactGetItemsRequest)} API. + * Transactionally loads objects specified by transactionLoadRequest by calling {@link AmazonDynamoDB#transactGetItems} API. *

    * Any exceptions from underlying API are thrown as is. For more information, please refer * https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html @@ -292,7 +286,7 @@ public interface IDynamoDBMapper { List transactionLoad(TransactionLoadRequest transactionLoadRequest); /** - * Transactionally loads objects specified by transactionLoadRequest by calling {@link AmazonDynamoDB#transactGetItems(TransactGetItemsRequest)} API. + * Transactionally loads objects specified by transactionLoadRequest by calling {@link AmazonDynamoDB#transactGetItems} API. *

    * Any exceptions from underlying API are thrown as is. For more information, please refer * https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html @@ -312,7 +306,7 @@ public interface IDynamoDBMapper { /** * Deletes the objects given using one or more calls to the - * {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. No version checks are + * {@link AmazonDynamoDB#batchWriteItem} API. No version checks are * performed, as required by the API. * * @see DynamoDBMapper#batchWrite(Iterable, Iterable) @@ -321,7 +315,7 @@ public interface IDynamoDBMapper { /** * Deletes the objects given using one or more calls to the - * {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. No version checks are + * {@link AmazonDynamoDB#batchWriteItem} API. No version checks are * performed, as required by the API. * * @see DynamoDBMapper#batchWrite(Iterable, Iterable) @@ -330,7 +324,7 @@ public interface IDynamoDBMapper { /** * Saves the objects given using one or more calls to the - * {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. No version checks are + * {@link AmazonDynamoDB#batchWriteItem} API. No version checks are * performed, as required by the API. *

    * This method ignores any SaveBehavior set on the mapper, and always behaves as if @@ -348,7 +342,7 @@ public interface IDynamoDBMapper { /** * Saves the objects given using one or more calls to the - * {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. No version checks are + * {@link AmazonDynamoDB#batchWriteItem} API. No version checks are * performed, as required by the API. *

    * This method ignores any SaveBehavior set on the mapper, and always behaves as if @@ -366,7 +360,7 @@ public interface IDynamoDBMapper { /** * Saves and deletes the objects given using one or more calls to the - * {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. No version checks are + * {@link AmazonDynamoDB#batchWriteItem} API. No version checks are * performed, as required by the API. *

    * This method ignores any SaveBehavior set on the mapper, and always behaves as if @@ -389,7 +383,7 @@ public interface IDynamoDBMapper { /** * Saves and deletes the objects given using one or more calls to the - * {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. Use mapper config to + * {@link AmazonDynamoDB#batchWriteItem} API. Use mapper config to * control the retry strategy when UnprocessedItems are returned by the BatchWriteItem API *

    * This method fails to save the batch if the size of an individual object in the batch exceeds @@ -404,10 +398,10 @@ public interface IDynamoDBMapper { * * @param objectsToWrite * A list of objects to save to DynamoDB. No version checks are performed, as - * required by the {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} API. + * required by the {@link AmazonDynamoDB#batchWriteItem} API. * @param objectsToDelete * A list of objects to delete from DynamoDB. No version checks are performed, - * as required by the {@link AmazonDynamoDB#batchWriteItem(BatchWriteItemRequest)} + * as required by the {@link AmazonDynamoDB#batchWriteItem} * API. * @param config * Only {@link DynamoDBMapperConfig#getTableNameOverride()} and @@ -458,7 +452,7 @@ List batchWrite(Iterable objectsToWrite, /** * Retrieves the attributes for multiple items from multiple tables using their primary keys. - * {@link AmazonDynamoDB#batchGetItem(BatchGetItemRequest)} API. + * {@link AmazonDynamoDB#batchGetItem} API. * * @return A map of the loaded objects. Each key in the map is the name of a DynamoDB table. * Each value in the map is a list of objects that have been loaded from that table. All diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java index 6a2ec541696c..13a92c89ef88 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/BatchLoadRetryStrategyTest.java @@ -32,6 +32,7 @@ import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @@ -160,6 +161,29 @@ public void testDelayOnPartialFailure_DefaultRetry() { assertTrue(defaultRetryStrategy.getDelayBeforeNextRetry(context) > 0); } + @Test + public void testBatchLoad_splitsAtHundredKeyBoundary() { + when(ddbMock.batchGetItem(any(BatchGetItemRequest.class))).thenReturn(buildDefaultGetItemResult()); + mapper = new DynamoDBMapper(ddbMock); + + List manyItems = new ArrayList(); + for (int i = 0; i < 101; i++) { + manyItems.add(new Item("hash" + i)); + } + + mapper.batchLoad(manyItems); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BatchGetItemRequest.class); + verify(ddbMock, times(2)).batchGetItem(captor.capture()); + + List requests = captor.getAllValues(); + KeysAndAttributes firstChunk = requests.get(0).requestItems().get(TABLE_NAME); + KeysAndAttributes secondChunk = requests.get(1).requestItems().get(TABLE_NAME); + + assertEquals("first chunk fills the 100-key boundary", 100, firstChunk.keys().size()); + assertEquals("second chunk carries the remaining key", 1, secondChunk.keys().size()); + } + private DynamoDBMapperConfig getConfigWithCustomBatchLoadRetryStrategy(final BatchLoadRetryStrategy batchReadRetryStrategy) { return new DynamoDBMapperConfig.Builder().withBatchLoadRetryStrategy(batchReadRetryStrategy).build(); } diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java index 9b5cd6b23881..3df8208834bd 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/PaginatedScanTaskTest.java @@ -23,11 +23,13 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -36,9 +38,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) @@ -88,6 +93,46 @@ public void segmentFailsToScan_ExecutorServiceIsShutdown() throws InterruptedExc assertTrue(executorService.isShutdown()); } + /** + * A segment that returns a last-evaluated key must be scanned again with that key as the exclusive + * start key of its next page, otherwise the segment re-scans from the beginning. Drives one segment + * across two pages and asserts its second request resumes from the first page's last-evaluated key. + */ + @Test + public void segmentWithLastEvaluatedKey_scansNextPageFromThatKey() throws InterruptedException { + Map lastKey = + Collections.singletonMap("id", AttributeValue.builder().s("page1-last").build()); + + // Segment 0 spans two pages; the rest complete in one. + when(dynamoDB.scan(isSegmentNumber(0))) + .thenReturn(ScanResponse.builder().items(generateItems()).lastEvaluatedKey(lastKey).build()) + .thenReturn(ScanResponse.builder().items(generateItems()).build()); + stubSuccessfulScan(1); + stubSuccessfulScan(2); + stubSuccessfulScan(3); + stubSuccessfulScan(4); + + while (!parallelScanTask.isAllSegmentScanFinished()) { + parallelScanTask.getNextBatchOfScanResults(); + } + + ArgumentCaptor captor = ArgumentCaptor.forClass(ScanRequest.class); + verify(dynamoDB, atLeastOnce()).scan(captor.capture()); + + List segmentZeroRequests = new ArrayList(); + for (ScanRequest request : captor.getAllValues()) { + if (request.segment() == 0) { + segmentZeroRequests.add(request); + } + } + + assertEquals("segment 0 should have been scanned twice", 2, segmentZeroRequests.size()); + assertTrue("page 1 must not carry an exclusive start key", + segmentZeroRequests.get(0).exclusiveStartKey().isEmpty()); + assertEquals("page 2 must resume from page 1's last-evaluated key", + lastKey, segmentZeroRequests.get(1).exclusiveStartKey()); + } + /** * Stub a successful scan of a segment with a precanned item to return. * diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java new file mode 100644 index 000000000000..eade341f04f1 --- /dev/null +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java @@ -0,0 +1,133 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package software.amazon.awssdk.mapper.dynamodb.shape; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBQueryExpression; +import software.amazon.awssdk.mapper.dynamodb.DynamoDBScanExpression; +import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.StringItem; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.services.dynamodb.model.PutItemResponse; +import software.amazon.awssdk.services.dynamodb.model.QueryRequest; +import software.amazon.awssdk.services.dynamodb.model.QueryResponse; +import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.awssdk.services.dynamodb.model.ScanResponse; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; + +/** + * Mock behavioral tests for the mapper's response handling control flow. Where ShapeRequestTest pins the marshalled request + * and ShapeResponseTest pins attribute map to POJO unmarshalling + */ +public class ShapeResponseBehaviorTest { + + private static final String HASH_KEY = "1234"; + + private DynamoDbClient ddb; + private DynamoDBMapper mapper; + + @Before + public void setup() { + ddb = mock(DynamoDbClient.class); + mapper = new DynamoDBMapper(ddb); + } + + @Test + public void load_returnsNull_whenItemEmpty() { + when(ddb.getItem(any(GetItemRequest.class))).thenReturn(GetItemResponse.builder().build()); + assertNull(mapper.load(key())); + } + + @Test + public void save_reissuesAsPutItem_whenUpdateReturnsNoAttributes() { + when(ddb.updateItem(any(UpdateItemRequest.class))).thenReturn(UpdateItemResponse.builder().build()); + when(ddb.putItem(any(PutItemRequest.class))).thenReturn(PutItemResponse.builder().build()); + + mapper.save(key()); + + ArgumentCaptor putCaptor = ArgumentCaptor.forClass(PutItemRequest.class); + verify(ddb).putItem(putCaptor.capture()); + assertEquals(HASH_KEY, putCaptor.getValue().item().get("id").s()); + } + + @Test + public void count_sumsAcrossPages_andStopsOnEmptyLastKey() { + Map lastKey = Collections.singletonMap("id", AttributeValue.builder().s(HASH_KEY).build()); + when(ddb.scan(any(ScanRequest.class))) + .thenReturn(ScanResponse.builder().count(3).lastEvaluatedKey(lastKey).build()) + .thenReturn(ScanResponse.builder().count(2).build()); + + assertEquals(5, mapper.count(StringItem.class, new DynamoDBScanExpression())); + verify(ddb, times(2)).scan(any(ScanRequest.class)); + + ArgumentCaptor scanCaptor = ArgumentCaptor.forClass(ScanRequest.class); + verify(ddb, times(2)).scan(scanCaptor.capture()); + assertEquals(lastKey, scanCaptor.getAllValues().get(1).exclusiveStartKey()); + } + + @Test + public void query_lazyPagination_fetchesNextPageUsingLastKey() { + Map lastKey = Collections.singletonMap("id", AttributeValue.builder().s(HASH_KEY).build()); + when(ddb.query(any(QueryRequest.class))) + .thenReturn(QueryResponse.builder().items(item("a")).lastEvaluatedKey(lastKey).build()) + .thenReturn(QueryResponse.builder().items(item("b")).build()); + + Iterator it = mapper.query(StringItem.class, + new DynamoDBQueryExpression().withHashKeyValues(key())).iterator(); + + int seen = 0; + while (it.hasNext()) { + it.next(); + seen++; + } + assertEquals(2, seen); + verify(ddb, times(2)).query(any(QueryRequest.class)); + + ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(QueryRequest.class); + verify(ddb, times(2)).query(queryCaptor.capture()); + assertEquals(lastKey, queryCaptor.getAllValues().get(1).exclusiveStartKey()); + } + + private static StringItem key() { + StringItem item = new StringItem(); + item.setId(HASH_KEY); + return item; + } + + private static Map item(String id) { + Map m = new HashMap<>(); + m.put("id", AttributeValue.builder().s(id).build()); + return m; + } +} From 06a6d586ebd9fd41e50899982a56ab3653e30b01 Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 13 Aug 2026 12:10:09 -0700 Subject: [PATCH 4/5] Add missing coverage --- .../mapper/dynamodb/DynamoDBMapper.java | 10 ++++++-- .../shape/ShapeResponseBehaviorTest.java | 23 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java index f2327dd596c4..e337b22a9da1 100644 --- a/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java +++ b/services-custom/dynamodb-mapper/src/main/java/software/amazon/awssdk/mapper/dynamodb/DynamoDBMapper.java @@ -1497,6 +1497,12 @@ private static boolean isNullOrEmpty(List list) { return list == null || list.isEmpty(); } + /** Normalizes v2's empty (non-null) final-page LastEvaluatedKey back to null per the ResultPage contract. */ + private static Map lastEvaluatedKeyOrNull(boolean hasLastEvaluatedKey, + Map lastEvaluatedKey) { + return hasLastEvaluatedKey && !lastEvaluatedKey.isEmpty() ? lastEvaluatedKey : null; + } + /** * Determnes if any of the primary keys require auto-generation. */ @@ -1600,7 +1606,7 @@ public ScanResultPage scanPage(Class clazz, toParameters(scanResult.items(), clazz, scanRequest.tableName(), config); result.setResults(marshallIntoObjects(parameters)); - result.setLastEvaluatedKey(scanResult.lastEvaluatedKey()); + result.setLastEvaluatedKey(lastEvaluatedKeyOrNull(scanResult.hasLastEvaluatedKey(), scanResult.lastEvaluatedKey())); result.setCount(scanResult.count()); result.setScannedCount(scanResult.scannedCount()); result.setConsumedCapacity(scanResult.consumedCapacity()); @@ -1635,7 +1641,7 @@ public QueryResultPage queryPage(Class clazz, toParameters(queryResult.items(), clazz, queryRequest.tableName(), config); result.setResults(marshallIntoObjects(parameters)); - result.setLastEvaluatedKey(queryResult.lastEvaluatedKey()); + result.setLastEvaluatedKey(lastEvaluatedKeyOrNull(queryResult.hasLastEvaluatedKey(), queryResult.lastEvaluatedKey())); result.setCount(queryResult.count()); result.setScannedCount(queryResult.scannedCount()); result.setConsumedCapacity(queryResult.consumedCapacity()); diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java index eade341f04f1..08a157af8cb3 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/shape/ShapeResponseBehaviorTest.java @@ -32,6 +32,8 @@ import software.amazon.awssdk.mapper.dynamodb.DynamoDBMapper; import software.amazon.awssdk.mapper.dynamodb.DynamoDBQueryExpression; import software.amazon.awssdk.mapper.dynamodb.DynamoDBScanExpression; +import software.amazon.awssdk.mapper.dynamodb.QueryResultPage; +import software.amazon.awssdk.mapper.dynamodb.ScanResultPage; import software.amazon.awssdk.mapper.dynamodb.shape.ShapeItems.StringItem; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @@ -119,6 +121,27 @@ public void query_lazyPagination_fetchesNextPageUsingLastKey() { assertEquals(lastKey, queryCaptor.getAllValues().get(1).exclusiveStartKey()); } + @Test + public void queryPage_lastEvaluatedKeyIsNull_whenServiceReturnsEmptyKey() { + when(ddb.query(any(QueryRequest.class))) + .thenReturn(QueryResponse.builder().items(item("a")).build()); + + QueryResultPage page = mapper.queryPage(StringItem.class, + new DynamoDBQueryExpression().withHashKeyValues(key())); + + assertNull(page.getLastEvaluatedKey()); + } + + @Test + public void scanPage_lastEvaluatedKeyIsNull_whenServiceReturnsEmptyKey() { + when(ddb.scan(any(ScanRequest.class))) + .thenReturn(ScanResponse.builder().items(item("a")).build()); + + ScanResultPage page = mapper.scanPage(StringItem.class, new DynamoDBScanExpression()); + + assertNull(page.getLastEvaluatedKey()); + } + private static StringItem key() { StringItem item = new StringItem(); item.setId(HASH_KEY); From 7fde9599cdcae5ae62a276e6855c5e64466b5d3a Mon Sep 17 00:00:00 2001 From: RanVaknin <50976344+RanVaknin@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:10:53 -0700 Subject: [PATCH 5/5] Migrate dangling ScanTest --- services-custom/dynamodb-mapper/pom.xml | 1 - .../mapper/dynamodb/mapper/ScanTest.java | 82 +++++++++++-------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/services-custom/dynamodb-mapper/pom.xml b/services-custom/dynamodb-mapper/pom.xml index 7e7416899dc3..ff1807c60feb 100644 --- a/services-custom/dynamodb-mapper/pom.xml +++ b/services-custom/dynamodb-mapper/pom.xml @@ -64,7 +64,6 @@ software/amazon/awssdk/mapper/dynamodb/mapper/GenerateCreateTableRequestTest.java software/amazon/awssdk/mapper/dynamodb/mapper/HashKeyOnlyTableWithGSITest.java software/amazon/awssdk/mapper/dynamodb/mapper/MapperLoadingStrategyConfigTest.java - software/amazon/awssdk/mapper/dynamodb/mapper/ScanTest.java software/amazon/awssdk/mapper/dynamodb/test/AWSIntegrationTestBase.java software/amazon/awssdk/mapper/dynamodb/test/resources/DynamoDBTableResource.java software/amazon/awssdk/mapper/dynamodb/test/resources/ResourceCentricBlockJUnit4ClassRunner.java diff --git a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScanTest.java b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScanTest.java index d5a8275a4345..534c94fa5bba 100644 --- a/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScanTest.java +++ b/services-custom/dynamodb-mapper/src/test/java/software/amazon/awssdk/mapper/dynamodb/mapper/ScanTest.java @@ -5,12 +5,12 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import software.amazon.awssdk.mapper.dynamodb.LocalDynamoDBTestBase; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; @@ -24,17 +24,17 @@ import software.amazon.awssdk.mapper.dynamodb.PaginatedParallelScanList; import software.amazon.awssdk.mapper.dynamodb.PaginatedScanList; import software.amazon.awssdk.mapper.dynamodb.ScanResultPage; -import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; -import com.amazonaws.services.dynamodbv2.model.ComparisonOperator; -import com.amazonaws.services.dynamodbv2.model.Condition; -import com.amazonaws.services.dynamodbv2.model.ConditionalOperator; -import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; -import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; -import com.amazonaws.services.dynamodbv2.model.KeyType; -import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; -import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; -import com.amazonaws.services.dynamodbv2.util.TableUtils; -import com.amazonaws.util.ImmutableMapParameter; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; +import software.amazon.awssdk.services.dynamodb.model.ComparisonOperator; +import software.amazon.awssdk.services.dynamodb.model.Condition; +import software.amazon.awssdk.services.dynamodb.model.ConditionalOperator; +import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; +import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; +import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; +import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; /** * Integration tests for the scan operation on DynamoDBMapper. */ @@ -47,7 +47,7 @@ public class ScanTest extends LocalDynamoDBTestBase { */ private static final int SCAN_LIMIT = 10; private static final int PARALLEL_SCAN_SEGMENTS = 3; - private static AmazonDynamoDB dynamo; + private static DynamoDbClient dynamo; private static void createTestData() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); @@ -59,30 +59,42 @@ private static void createTestData() throws Exception { @BeforeClass public static void setUpTestData() throws Exception { dynamo = client(); - String keyName = "id"; - CreateTableRequest createTableRequest = new CreateTableRequest() - .withTableName(TABLE_NAME) - .withKeySchema(new KeySchemaElement().withAttributeName(keyName).withKeyType(KeyType.HASH)) - .withAttributeDefinitions( - new AttributeDefinition().withAttributeName(keyName).withAttributeType( - ScalarAttributeType.S)); - createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(10L) - .withWriteCapacityUnits(5L)); - - TableUtils.createTableIfNotExists(dynamo, createTableRequest); - TableUtils.waitUntilActive(dynamo, TABLE_NAME); + String keyName = "id"; + CreateTableRequest createTableRequest = CreateTableRequest.builder() + .tableName(TABLE_NAME) + .keySchema(KeySchemaElement.builder().attributeName(keyName).keyType(KeyType.HASH).build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName(keyName) + .attributeType(ScalarAttributeType.S).build()) + .provisionedThroughput(ProvisionedThroughput.builder().readCapacityUnits(10L) + .writeCapacityUnits(5L).build()) + .build(); + + if (createTableIfNotExists(createTableRequest)) { + dynamo.waiter().waitUntilTableExists(b -> b.tableName(TABLE_NAME)); + } createTestData(); } + private static boolean createTableIfNotExists(CreateTableRequest createTableRequest) { + try { + dynamo.createTable(createTableRequest); + return true; + } catch (ResourceInUseException e) { + // Table already exists. + return false; + } + } + @Test public void testScan() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression().withLimit(SCAN_LIMIT); - scanExpression.addFilterCondition("value", new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); - scanExpression.addFilterCondition("extraData", new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); + scanExpression.addFilterCondition("value", Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); + scanExpression.addFilterCondition("extraData", Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); List list = util.scan(SimpleClass.class, scanExpression); int count = 0; @@ -111,12 +123,12 @@ public void testScan() throws Exception { public void testScanWithConditionalOperator() { DynamoDBMapper mapper = new DynamoDBMapper(dynamo); + Map scanFilter = new HashMap<>(); + scanFilter.put("value", Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); + scanFilter.put("non-existent-field", Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression() .withLimit(SCAN_LIMIT) - .withScanFilter(ImmutableMapParameter.of( - "value", new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL), - "non-existent-field", new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL) - )) + .withScanFilter(scanFilter) .withConditionalOperator(ConditionalOperator.AND); List andConditionResult = mapper.scan(SimpleClass.class, scanExpression); @@ -132,8 +144,8 @@ public void testParallelScan() throws Exception { DynamoDBMapper util = new DynamoDBMapper(dynamo); DynamoDBScanExpression scanExpression = new DynamoDBScanExpression().withLimit(SCAN_LIMIT); - scanExpression.addFilterCondition("value", new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); - scanExpression.addFilterCondition("extraData", new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); + scanExpression.addFilterCondition("value", Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); + scanExpression.addFilterCondition("extraData", Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); PaginatedParallelScanList parallelScanList = util.parallelScan(SimpleClass.class, scanExpression, PARALLEL_SCAN_SEGMENTS); int count = 0; @@ -168,9 +180,9 @@ public void testScanPage() throws Exception { DynamoDBScanExpression scanExpression = new DynamoDBScanExpression(); scanExpression.addFilterCondition("value", - new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); + Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); scanExpression.addFilterCondition("extraData", - new Condition().withComparisonOperator(ComparisonOperator.NOT_NULL.toString())); + Condition.builder().comparisonOperator(ComparisonOperator.NOT_NULL).build()); int limit = 3; scanExpression.setLimit(limit); ScanResultPage result = util.scanPage(SimpleClass.class, scanExpression);