diff --git a/.changes/next-release/feature-AWSDynamoDBEnhancedClient-1172ef6.json b/.changes/next-release/feature-AWSDynamoDBEnhancedClient-1172ef6.json
new file mode 100644
index 000000000000..3ab0d23792b1
--- /dev/null
+++ b/.changes/next-release/feature-AWSDynamoDBEnhancedClient-1172ef6.json
@@ -0,0 +1,6 @@
+{
+ "type": "feature",
+ "category": "AWS DynamoDB Enhanced Client",
+ "description": "Refactoring `AutoGeneratedUuidExtension` to accepted UUID supplier to make possible using other UUID versions.",
+ "contributor": "marcusvoltolim"
+}
diff --git a/services-custom/dynamodb-enhanced/pom.xml b/services-custom/dynamodb-enhanced/pom.xml
index 8ad0e81c8551..af64a7294eb5 100644
--- a/services-custom/dynamodb-enhanced/pom.xml
+++ b/services-custom/dynamodb-enhanced/pom.xml
@@ -30,6 +30,7 @@
${project.parent.version}1.8
+ 5.1.0
@@ -233,5 +234,12 @@
sotest
+
+ com.fasterxml.uuid
+ java-uuid-generator
+ ${fasterxml-uuid.version}
+ test
+
+
diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtension.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtension.java
index d92db8c60bbd..caf087a92abd 100644
--- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtension.java
+++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtension.java
@@ -21,6 +21,8 @@
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
+import java.util.function.Supplier;
+import software.amazon.awssdk.annotations.NotThreadSafe;
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType;
@@ -33,27 +35,22 @@
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.utils.Validate;
-
/**
* This extension facilitates the automatic generation of a unique UUID (Universally Unique Identifier) for a specified attribute
* every time a new record is written to the database. The generated UUID is obtained using the
- * {@link java.util.UUID#randomUUID()} method.
+ * {@link java.util.UUID#randomUUID()} method by default or a custom UUID supplier instance provided by the user.
*
* This extension is not loaded by default when you instantiate a
* {@link software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient}. Therefore, you need to specify it in a custom
* extension when creating the enhanced client.
*
* Example to add AutoGeneratedUuidExtension along with default extensions is
- * {@snippet :
- * DynamoDbEnhancedClient.builder().extensions(Stream.concat(ExtensionResolver.defaultExtensions().stream(),
- * Stream.of(AutoGeneratedUuidExtension.create())).collect(Collectors.toList())).build();
- *}
+ * {@code DynamoDbEnhancedClient.builder().extensions(Stream.concat(ExtensionResolver.defaultExtensions().stream(),
+ * Stream.of(AutoGeneratedUuidExtension.create())).collect(Collectors.toList())).build();}
*
*
* Example to just add AutoGeneratedUuidExtension without default extensions is
- * {@snippet :
- * DynamoDbEnhancedClient.builder().extensions(AutoGeneratedUuidExtension.create()).build();
- *}
+ * {@code DynamoDbEnhancedClient.builder().extensions(AutoGeneratedUuidExtension.create())).build();}
*
*
* To utilize the auto-generated UUID feature, first, create a field in your model that will store the UUID for the attribute.
@@ -61,46 +58,48 @@
* using the {@link software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema}, then you should use the
* {@link software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbAutoGeneratedUuid} annotation. If you are using
* the {@link software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema}, then you should use the
- * {@link
- * software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension.AttributeTags#autoGeneratedUuidAttribute()}
- * static attribute tag.
+ * {@link AttributeTags#autoGeneratedUuidAttribute()} static attribute tag.
*
*
* Every time a new record is successfully put into the database, the specified attribute will be automatically populated with a
- * unique UUID generated using {@link java.util.UUID#randomUUID()}. If the UUID needs to be created only for `putItem` and should
- * not be generated for an `updateItem`, then
+ * unique UUID generated using {@link java.util.UUID#randomUUID()}.
+ *
+ * If the UUID needs to be created only for `putItem` and should not be generated for an `updateItem`, then
* {@link software.amazon.awssdk.enhanced.dynamodb.mapper.UpdateBehavior#WRITE_IF_NOT_EXISTS} must be along with
- * {@link DynamoDbUpdateBehavior}
- *
+ * {@link DynamoDbUpdateBehavior}.
*
*/
@SdkPublicApi
@ThreadSafe
public final class AutoGeneratedUuidExtension implements DynamoDbEnhancedClientExtension {
- private static final String CUSTOM_METADATA_KEY =
- "software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension:AutoGeneratedUuidAttribute";
- private static final AutoGeneratedUuidAttribute AUTO_GENERATED_UUID_ATTRIBUTE = new AutoGeneratedUuidAttribute();
+
+ private static final String CUSTOM_METADATA_KEY = "AutoGeneratedUuidExtension:AutoGeneratedUuidAttribute";
+ private static final StaticAttributeTag AUTO_GENERATED_UUID_ATTRIBUTE = new AutoGeneratedUuidAttribute();
+
+ private final Supplier uuidSupplier;
private AutoGeneratedUuidExtension() {
+ this.uuidSupplier = UUID::randomUUID;
+ }
+
+ private AutoGeneratedUuidExtension(Builder builder) {
+ this.uuidSupplier = builder.uuidSupplier == null ? UUID::randomUUID : builder.uuidSupplier;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public Builder toBuilder() {
+ return builder().uuidSupplier(this.uuidSupplier);
}
- /**
- * @return an Instance of {@link AutoGeneratedUuidExtension}
- */
public static AutoGeneratedUuidExtension create() {
return new AutoGeneratedUuidExtension();
}
- /**
- * Modifies the WriteModification UUID string with the attribute updated with the extension.
- *
- * @param context The {@link DynamoDbExtensionContext.BeforeWrite} context containing the state of the execution.
- * @return WriteModification String updated with attribute updated with Extension.
- */
@Override
public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite context) {
-
-
Collection customMetadataObject = context.tableMetadata()
.customMetadataObject(CUSTOM_METADATA_KEY, Collection.class)
.orElse(null);
@@ -116,9 +115,8 @@ public WriteModification beforeWrite(DynamoDbExtensionContext.BeforeWrite contex
.build();
}
- private void insertUuidInItemToTransform(Map itemToTransform,
- String key) {
- itemToTransform.put(key, AttributeValue.builder().s(UUID.randomUUID().toString()).build());
+ private void insertUuidInItemToTransform(Map itemToTransform, String key) {
+ itemToTransform.put(key, AttributeValue.builder().s(uuidSupplier.get().toString()).build());
}
public static final class AttributeTags {
@@ -126,22 +124,16 @@ public static final class AttributeTags {
private AttributeTags() {
}
- /**
- * Tags which indicate that the given attribute is supported wih Auto Generated UUID Record Extension.
- *
- * @return Tag name for AutoGenerated UUID Records
- */
public static StaticAttributeTag autoGeneratedUuidAttribute() {
return AUTO_GENERATED_UUID_ATTRIBUTE;
}
+
}
private static class AutoGeneratedUuidAttribute implements StaticAttributeTag {
@Override
- public void validateType(String attributeName, EnhancedType type,
- AttributeValueType attributeValueType) {
-
+ public void validateType(String attributeName, EnhancedType type, AttributeValueType attributeValueType) {
Validate.notNull(type, "type is null");
Validate.notNull(type.rawClass(), "rawClass is null");
Validate.notNull(attributeValueType, "attributeValueType is null");
@@ -159,5 +151,34 @@ public Consumer modifyMetadata(String attributeName
return metadata -> metadata.addCustomMetadataObject(CUSTOM_METADATA_KEY, Collections.singleton(attributeName))
.markAttributeAsKey(attributeName, attributeValueType);
}
+
+ }
+
+ @NotThreadSafe
+ public static final class Builder {
+
+ private Supplier uuidSupplier;
+
+ private Builder() {
+ }
+
+ /**
+ * Sets the UUID supplier instance , else {@link UUID#randomUUID()} is used by default. Every time a new UUID is generated
+ * this supplier will be used to get the current UUID. If a custom supplier is not specified, the default randomUUID
+ * supplier will be used.
+ *
+ * @param uuidSupplier Supplier instance to set the current UUID.
+ * @return This builder for method chaining.
+ */
+ public Builder uuidSupplier(Supplier uuidSupplier) {
+ this.uuidSupplier = uuidSupplier;
+ return this;
+ }
+
+ public AutoGeneratedUuidExtension build() {
+ return new AutoGeneratedUuidExtension(this);
+ }
+
}
-}
\ No newline at end of file
+
+}
diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtensionTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtensionTest.java
index cc69f503d50f..072b80809fa3 100644
--- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtensionTest.java
+++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedUuidExtensionTest.java
@@ -16,14 +16,21 @@
package software.amazon.awssdk.enhanced.dynamodb.extensions;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.params.provider.EnumSource.Mode.INCLUDE;
+import static software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute;
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey;
+import com.fasterxml.uuid.Generators;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.regex.Pattern;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
import software.amazon.awssdk.enhanced.dynamodb.OperationContext;
import software.amazon.awssdk.enhanced.dynamodb.TableMetadata;
import software.amazon.awssdk.enhanced.dynamodb.internal.extensions.DefaultDynamoDbExtensionContext;
@@ -32,132 +39,195 @@
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
-public class AutoGeneratedUuidExtensionTest {
-
- private static final String UUID_REGEX =
- "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
-
- private static final Pattern UUID_PATTERN = Pattern.compile(UUID_REGEX);
-
- private static final String RECORD_ID = "id123";
-
- private static final String TABLE_NAME = "table-name";
- private static final OperationContext PRIMARY_CONTEXT =
- DefaultOperationContext.create(TABLE_NAME, TableMetadata.primaryIndexName());
-
- private final AutoGeneratedUuidExtension atomicCounterExtension = AutoGeneratedUuidExtension.create();
+class AutoGeneratedUuidExtensionTest {
+
+ private static final Pattern UUID_PATTERN = Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
+ private static final String RECORD_ID = "id-123";
+ private static final OperationContext PRIMARY_CONTEXT = DefaultOperationContext.create("table-name", TableMetadata.primaryIndexName());
+
+ private static final StaticTableSchema ITEM_WITH_UUID_MAPPER = StaticTableSchema
+ .builder(ItemWithUuid.class)
+ .newItemSupplier(ItemWithUuid::new)
+ .addAttribute(String.class, a -> a.name("id")
+ .getter(ItemWithUuid::getId)
+ .setter(ItemWithUuid::setId)
+ .addTag(primaryPartitionKey()))
+ .addAttribute(String.class, a -> a.name("uuidAttribute")
+ .getter(ItemWithUuid::getUuidAttribute)
+ .setter(ItemWithUuid::setUuidAttribute)
+ .addTag(autoGeneratedUuidAttribute())
+ )
+ .addAttribute(String.class, a -> a.name("simpleString")
+ .getter(ItemWithUuid::getSimpleString)
+ .setter(ItemWithUuid::setSimpleString))
+ .build();
+
+
+ @Nested
+ class WithDefaultUuidSupplier {
+
+ private final AutoGeneratedUuidExtension extension = AutoGeneratedUuidExtension.create();
+
+ private void assertUUIDv4(String uuid) {
+ assertEquals(4, UUID.fromString(uuid).version());
+ }
+ @EnumSource(value = OperationName.class, names = {"PUT_ITEM", "UPDATE_ITEM"}, mode = INCLUDE)
+ @ParameterizedTest
+ void beforeWrite_setNewUUID_whenHasNoUuidInItem(OperationName operation) {
+ ItemWithUuid item = new ItemWithUuid();
+ item.setId(RECORD_ID);
+ item.setUuidAttribute(UUID.randomUUID().toString());
+
+ Map items = ITEM_WITH_UUID_MAPPER.itemToMap(item, true);
+ assertThat(items).hasSize(2);
+
+ WriteModification result = extension.beforeWrite(DefaultDynamoDbExtensionContext
+ .builder()
+ .items(items)
+ .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
+ .operationName(operation)
+ .operationContext(PRIMARY_CONTEXT).build());
+
+ assertThat(result.transformedItem())
+ .hasSize(2)
+ .containsEntry("id", AttributeValue.fromS(RECORD_ID))
+ .extractingByKey("uuidAttribute")
+ .satisfies(uuid -> assertThat(uuid.s())
+ .matches(UUID_PATTERN)
+ .isNotEqualTo(item.getUuidAttribute())
+ .satisfies(this::assertUUIDv4));
+
+ assertThat(result.additionalConditionalExpression())
+ .isNull();
+ assertThat(result.updateExpression())
+ .isNull();
+ }
- private static final StaticTableSchema ITEM_WITH_UUID_MAPPER =
- StaticTableSchema.builder(ItemWithUuid.class)
- .newItemSupplier(ItemWithUuid::new)
- .addAttribute(String.class, a -> a.name("id")
- .getter(ItemWithUuid::getId)
- .setter(ItemWithUuid::setId)
- .addTag(primaryPartitionKey()))
- .addAttribute(String.class, a -> a.name("uuidAttribute")
- .getter(ItemWithUuid::getUuidAttribute)
- .setter(ItemWithUuid::setUuidAttribute)
- .addTag(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())
- )
- .addAttribute(String.class, a -> a.name("simpleString")
- .getter(ItemWithUuid::getSimpleString)
- .setter(ItemWithUuid::setSimpleString))
- .build();
+ @EnumSource(value = OperationName.class, names = {"PUT_ITEM", "UPDATE_ITEM"}, mode = INCLUDE)
+ @ParameterizedTest
+ void beforeWrite_setNewUUID_whenHasUuidInItem(OperationName operation) {
+ ItemWithUuid item = new ItemWithUuid();
+ item.setId(RECORD_ID);
+ item.setUuidAttribute(null);
+
+ Map items = ITEM_WITH_UUID_MAPPER.itemToMap(item, true);
+ assertThat(items).hasSize(1);
+
+ WriteModification result = extension.beforeWrite(DefaultDynamoDbExtensionContext
+ .builder()
+ .items(items)
+ .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
+ .operationName(operation)
+ .operationContext(PRIMARY_CONTEXT).build());
+
+ assertThat(result.transformedItem())
+ .hasSize(2)
+ .containsEntry("id", AttributeValue.fromS(RECORD_ID))
+ .extractingByKey("uuidAttribute")
+ .satisfies(uuid -> assertThat(uuid.s())
+ .matches(UUID_PATTERN)
+ .isNotEqualTo(item.getUuidAttribute())
+ .satisfies(this::assertUUIDv4));
+
+ assertThat(result.additionalConditionalExpression())
+ .isNull();
+ assertThat(result.updateExpression())
+ .isNull();
+ }
+ }
- @Test
- public void beforeWrite_updateItemOperation_hasUuidInItem_doesNotCreateUpdateExpressionAndFilters() {
- ItemWithUuid SimpleItem = new ItemWithUuid();
- SimpleItem.setId(RECORD_ID);
- String uuidAttribute = String.valueOf(UUID.randomUUID());
- SimpleItem.setUuidAttribute(uuidAttribute);
-
- Map items = ITEM_WITH_UUID_MAPPER.itemToMap(SimpleItem, true);
- assertThat(items).hasSize(2);
-
- WriteModification result =
- atomicCounterExtension.beforeWrite(DefaultDynamoDbExtensionContext.builder()
- .items(items)
- .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
- .operationName(OperationName.UPDATE_ITEM)
- .operationContext(PRIMARY_CONTEXT).build());
-
- Map transformedItem = result.transformedItem();
- assertThat(transformedItem).isNotNull().hasSize(2);
- assertThat(transformedItem).containsEntry("id", AttributeValue.fromS(RECORD_ID));
- isValidUuid(transformedItem.get("uuidAttribute").s());
- assertThat(result.updateExpression()).isNull();
+ @Nested
+ class WithCustomUuidSupplier {
- }
+ private void assertUUIDv7(String uuid) {
+ assertEquals(7, UUID.fromString(uuid).version());
+ }
- @Test
- public void beforeWrite_updateItemOperation_hasNoUuidInItem_doesNotCreatesUpdateExpressionAndFilters() {
- ItemWithUuid SimpleItem = new ItemWithUuid();
- SimpleItem.setId(RECORD_ID);
-
- Map items = ITEM_WITH_UUID_MAPPER.itemToMap(SimpleItem, true);
- assertThat(items).hasSize(1);
-
- WriteModification result =
- atomicCounterExtension.beforeWrite(DefaultDynamoDbExtensionContext.builder()
- .items(items)
- .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
- .operationName(OperationName.UPDATE_ITEM)
- .operationContext(PRIMARY_CONTEXT).build());
-
- Map transformedItem = result.transformedItem();
- assertThat(transformedItem).isNotNull().hasSize(2);
- assertThat(transformedItem).containsEntry("id", AttributeValue.fromS(RECORD_ID));
- isValidUuid(transformedItem.get("uuidAttribute").s());
- assertThat(result.updateExpression()).isNull();
- }
+ private final AutoGeneratedUuidExtension extension = AutoGeneratedUuidExtension
+ .builder()
+ .uuidSupplier(() -> Generators.timeBasedEpochGenerator().generate())
+ .build();
+
+ @EnumSource(value = OperationName.class, names = {"PUT_ITEM", "UPDATE_ITEM"}, mode = INCLUDE)
+ @ParameterizedTest
+ void beforeWrite_setNewUUID_whenHasNoUuidInItem(OperationName operation) {
+ ItemWithUuid item = new ItemWithUuid();
+ item.setId(RECORD_ID);
+ item.setUuidAttribute(UUID.randomUUID().toString());
+
+ Map items = ITEM_WITH_UUID_MAPPER.itemToMap(item, true);
+ assertThat(items).hasSize(2);
+
+ WriteModification result = extension.beforeWrite(DefaultDynamoDbExtensionContext
+ .builder()
+ .items(items)
+ .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
+ .operationName(operation)
+ .operationContext(PRIMARY_CONTEXT).build());
+
+ assertThat(result.transformedItem())
+ .hasSize(2)
+ .containsEntry("id", AttributeValue.fromS(RECORD_ID))
+ .extractingByKey("uuidAttribute")
+ .satisfies(value -> assertThat(value.s())
+ .matches(UUID_PATTERN)
+ .isNotEqualTo(item.getUuidAttribute())
+ .satisfies(this::assertUUIDv7));
+
+ assertThat(result.additionalConditionalExpression())
+ .isNull();
+ assertThat(result.updateExpression())
+ .isNull();
+ }
- @Test
- public void beforeWrite_updateItemOperation_UuidNotPresent_newUuidCreated() {
- ItemWithUuid item = new ItemWithUuid();
- item.setId(RECORD_ID);
-
- Map items = ITEM_WITH_UUID_MAPPER.itemToMap(item, true);
- assertThat(items).hasSize(1);
-
- WriteModification result =
- atomicCounterExtension.beforeWrite(DefaultDynamoDbExtensionContext.builder()
- .items(items)
- .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
- .operationName(OperationName.UPDATE_ITEM)
- .operationContext(PRIMARY_CONTEXT).build());
- assertThat(result.transformedItem()).isNotNull();
- assertThat(result.updateExpression()).isNull();
- assertThat(result.transformedItem()).hasSize(2);
- assertThat(isValidUuid(result.transformedItem().get("uuidAttribute").s())).isTrue();
+ @EnumSource(value = OperationName.class, names = {"PUT_ITEM", "UPDATE_ITEM"}, mode = INCLUDE)
+ @ParameterizedTest
+ void beforeWrite_setNewUUID_whenHasUuidInItem(OperationName operation) {
+ ItemWithUuid item = new ItemWithUuid();
+ item.setId(RECORD_ID);
+ item.setUuidAttribute(null);
+
+ Map items = ITEM_WITH_UUID_MAPPER.itemToMap(item, true);
+ assertThat(items).hasSize(1);
+
+ WriteModification result = extension.beforeWrite(DefaultDynamoDbExtensionContext
+ .builder()
+ .items(items)
+ .tableMetadata(ITEM_WITH_UUID_MAPPER.tableMetadata())
+ .operationName(operation)
+ .operationContext(PRIMARY_CONTEXT).build());
+
+ assertThat(result.transformedItem())
+ .hasSize(2)
+ .containsEntry("id", AttributeValue.fromS(RECORD_ID))
+ .extractingByKey("uuidAttribute")
+ .satisfies(uuid -> assertThat(uuid.s())
+ .matches(UUID_PATTERN)
+ .isNotEqualTo(item.getUuidAttribute())
+ .satisfies(this::assertUUIDv7));
+
+ assertThat(result.additionalConditionalExpression())
+ .isNull();
+ assertThat(result.updateExpression())
+ .isNull();
+ }
}
@Test
- void IllegalArgumentException_for_AutogeneratedUuid_withNonStringType() {
-
- assertThatExceptionOfType(IllegalArgumentException.class)
- .isThrownBy(() -> StaticTableSchema.builder(ItemWithUuid.class)
- .newItemSupplier(ItemWithUuid::new)
- .addAttribute(String.class, a -> a.name("id")
- .getter(ItemWithUuid::getId)
- .setter(ItemWithUuid::setId)
- .addTag(primaryPartitionKey()))
- .addAttribute(Integer.class, a -> a.name("intAttribute")
- .getter(ItemWithUuid::getIntAttribute)
- .setter(ItemWithUuid::setIntAttribute)
- .addTag(AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute())
- )
- .addAttribute(String.class, a -> a.name("simpleString")
- .getter(ItemWithUuid::getSimpleString)
- .setter(ItemWithUuid::setSimpleString))
- .build())
-
- .withMessage("Attribute 'intAttribute' of Class type class java.lang.Integer is not a suitable Java Class type"
- + " to be used as a Auto Generated Uuid attribute. Only String Class type is supported.");
- }
-
- public static boolean isValidUuid(String uuid) {
- return UUID_PATTERN.matcher(uuid).matches();
+ void throws_IllegalArgumentException_for_AutogeneratedUuid_withNonStringType() {
+ StaticTableSchema.Builder staticTableBuilder = StaticTableSchema
+ .builder(ItemWithUuid.class)
+ .newItemSupplier(ItemWithUuid::new)
+ .addAttribute(Integer.class, a -> a.name("intAttribute")
+ .getter(ItemWithUuid::getIntAttribute)
+ .setter(ItemWithUuid::setIntAttribute)
+ .addTag(autoGeneratedUuidAttribute())
+ );
+ assertThatThrownBy(staticTableBuilder::build)
+ .isExactlyInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Attribute 'intAttribute' of Class type class java.lang.Integer is not a suitable Java Class type"
+ + " to be used as a Auto Generated Uuid attribute. Only String Class type is supported.");
}
private static class ItemWithUuid {
@@ -175,9 +245,6 @@ public void setIntAttribute(Integer intAttribute) {
this.intAttribute = intAttribute;
}
- public ItemWithUuid() {
- }
-
public String getId() {
return id;
}
@@ -218,5 +285,7 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(id, uuidAttribute, simpleString);
}
+
}
-}
\ No newline at end of file
+
+}
diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java
index e59ea214399b..3ae0f2620805 100644
--- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java
+++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java
@@ -15,39 +15,34 @@
package software.amazon.awssdk.enhanced.dynamodb.functionaltests;
-import static java.util.stream.Collectors.toList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
import static software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute;
import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue;
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey;
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.updateBehavior;
+import com.fasterxml.uuid.Generators;
import java.util.Arrays;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.UUID;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
import java.util.regex.Pattern;
-import java.util.stream.IntStream;
-import org.assertj.core.api.Assertions;
import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable;
import software.amazon.awssdk.enhanced.dynamodb.Expression;
-import software.amazon.awssdk.enhanced.dynamodb.OperationContext;
-import software.amazon.awssdk.enhanced.dynamodb.TableMetadata;
import software.amazon.awssdk.enhanced.dynamodb.TableSchema;
import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension;
import software.amazon.awssdk.enhanced.dynamodb.extensions.annotations.DynamoDbAutoGeneratedUuid;
-import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DefaultOperationContext;
import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema;
import software.amazon.awssdk.enhanced.dynamodb.mapper.UpdateBehavior;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean;
@@ -55,38 +50,26 @@
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey;
import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbUpdateBehavior;
import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest;
-import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
-import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
-import software.amazon.awssdk.services.dynamodb.model.GetItemRequest;
-import software.amazon.awssdk.services.dynamodb.model.GetItemResponse;
-import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
@RunWith(Parameterized.class)
-public class AutoGeneratedUuidRecordTest extends LocalDynamoDbSyncTestBase{
-
- private static final String UUID_REGEX =
- "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
-
- private static final Pattern UUID_PATTERN = Pattern.compile(UUID_REGEX);
-
- public static void assertValidUuid(String uuid) {
- Assertions.assertThat(UUID_PATTERN.matcher(uuid).matches()).isTrue();
- }
+public class AutoGeneratedUuidRecordTest extends LocalDynamoDbSyncTestBase {
+ private static final Pattern UUID_PATTERN = Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
private static final String TABLE_NAME = "table-name";
- private static final OperationContext PRIMARY_CONTEXT =
- DefaultOperationContext.create(TABLE_NAME, TableMetadata.primaryIndexName());
-
-
- public AutoGeneratedUuidRecordTest(String testName, TableSchema recordTableSchema) {
+ private final DynamoDbTable mappedTable;
+ private final Consumer assertUuidVersion;
+
+ public AutoGeneratedUuidRecordTest(String ignoredTestName,
+ TableSchema recordTableSchema,
+ AutoGeneratedUuidExtension autoGeneratedUuidExtension,
+ Consumer assertUuidVersion) {
+ this.assertUuidVersion = assertUuidVersion;
this.mappedTable = DynamoDbEnhancedClient.builder()
.dynamoDbClient(getDynamoDbClient())
- .extensions(AutoGeneratedUuidExtension.create())
- .build().table(getConcreteTableName("table-name"),
- recordTableSchema);
- this.testCaseName = testName;
+ .extensions(autoGeneratedUuidExtension)
+ .build()
+ .table(getConcreteTableName(TABLE_NAME), recordTableSchema);
}
private static final TableSchema FLATTENED_TABLE_SCHEMA =
@@ -94,7 +77,7 @@ public AutoGeneratedUuidRecordTest(String testName, TableSchema recordTa
.newItemSupplier(FlattenedRecord::new)
.addAttribute(String.class, a -> a.name("generated")
.getter(FlattenedRecord::getGenerated)
- .setter(FlattenedRecord::generated)
+ .setter(FlattenedRecord::setGenerated)
.tags(autoGeneratedUuidAttribute()))
.build();
@@ -107,47 +90,48 @@ public AutoGeneratedUuidRecordTest(String testName, TableSchema recordTa
.tags(primaryPartitionKey()))
.addAttribute(String.class, a -> a.name("attribute")
.getter(Record::getAttribute)
- .setter(Record::attribute))
+ .setter(Record::setAttribute))
.addAttribute(String.class, a -> a.name("lastUpdatedUuid")
.getter(Record::getLastUpdatedUuid)
- .setter(Record::lastUpdatedUuid)
+ .setter(Record::setLastUpdatedUuid)
.tags(autoGeneratedUuidAttribute()))
.addAttribute(String.class, a -> a.name("createdUuid")
.getter(Record::getCreatedUuid)
- .setter(Record::createdUuid)
+ .setter(Record::setCreatedUuid)
.tags(autoGeneratedUuidAttribute(),
updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS)))
- .flatten(FLATTENED_TABLE_SCHEMA, Record::getFlattenedRecord, Record::flattenedRecord)
+ .flatten(FLATTENED_TABLE_SCHEMA, Record::getFlattenedRecord, Record::setFlattenedRecord)
.build();
- private final List