aws-sdk-java-v2 icon indicating copy to clipboard operation
aws-sdk-java-v2 copied to clipboard

DynamoDB Enhanced Client Polymorphic Types Support

Open anasatirbasa opened this issue 6 months ago • 0 comments

Motivation and Context

By default, the DynamoDbEnhancedClient does not natively support storing multiple Java subclasses of a common supertype in the same table. In complex domain models (e.g. storing both Employee and Customer instances of Person), there was a need to write complex type‐discrimination logic. This change introduces a clean, annotation‐driven layer that automatically dispatches to the correct subtype schema at runtime, reducing boilerplate and eliminating fragile manual checks.

Modifications

  • New Annotations
    • @DynamoDbSubtypeDiscriminator to mark the discriminator field on the base type.
    • @DynamoDbSupertype (with inner Subtype annotation) to declare each concrete subtype and its discriminator value on the supertype class.
  • Static Attribute Tag
    • Added StaticAttributeTags.subtypeName() and SubtypeNameTag to record the discriminator attribute name in TableMetadata.
  • Polymorphic Schema Classes
    • StaticSubtype<T> encapsulates a subtype’s TableSchema and its discriminator value.
    • StaticPolymorphicTableSchema<T> implements TableSchema<T>: reads the discriminator from the item or object, looks up the right StaticSubtype, and delegates all mapping calls.
    • PolymorphicTableSchema<T> wraps the static polymorphic schema for recursive resolution and caching.
  • Factory Integration
    • Updated TableSchemaFactory.fromClass(...) to detect @DynamoDbSupertype and route to PolymorphicTableSchema.create(...).
  • Extension & Operation Hooks
    • Modified EnhancedClientUtils.readAndTransformSingleItem and all core operations (Put, Update, Transact) to resolve and use the concrete subtype schema before invoking extensions or building requests.
  • Converters Delegation
    • Added an override of converterForAttribute(...) in StaticPolymorphicTableSchema to delegate to the root schema so user‐defined @DynamoDbConvertedBy converters continue to work seamlessly.
  • Diagrams & Documentation
    • Added a Low Level Design document including sequence diagrams and flowcharts to illustrate routing logic and serialization/deserialization flows.

Testing

  • Unit Tests
    • Added tests for StaticPolymorphicTableSchema covering:
      • Mapping to and from each subtype (mapToItem / itemToMap).
      • Error cases: missing discriminator, invalid discriminator value, duplicate subtype names.
    • Verified that custom attribute converters (e.g. for Instant) are correctly applied via converterForAttribute.
  • Integration Tests
    • Put/get/update items in a real DynamoDB Local table with a mixed set of Person and Customer subclasses.
    • Tested with polymorphic beans and flattened maps to ensure dispatch at each level.
  • Manual Verification
    • Confirmed that client‐side extensions (e.g. auto‐timestamp update) receive the correct subtype schema context in beforeWrite / afterRead.

Screenshots (if appropriate)

(See design doc diagrams in Section 4 and 5 for visual routing and flowchart illustrations.)

Test Coverage Checklist

Scenario Done Comments if Not Done
1. Different TableSchema Creation Methods
a. TableSchema.fromBean(Customer.class) [x]
b. TableSchema.fromImmutableClass(Customer.class) for immutable classes [x]
c. TableSchema.documentSchemaBuilder().build() [ ]
d. StaticTableSchema.builder(Customer.class) [x]
2. Nesting of Different TableSchema Types
a. @DynamoDbBean with nested @DynamoDbBean as NonNull [x]
b. @DynamoDbBean with nested @DynamoDbImmutable as NonNull [x]
c. @DynamoDbImmutable with nested @DynamoDbBean as NonNull [x]
d. @DynamoDbBean with nested @DynamoDbBean as Null [x]
e. @DynamoDbBean with nested @DynamoDbImmutable as Null [x]
f. @DynamoDbImmutable with nested @DynamoDbBean as Null [x]
3. CRUD Operations
a. scan() [ ]
b. query() [x]
c. updateItem() [ ]
d. putItem() [x]
e. getItem() [x]
f. deleteItem() [ ]
g. batchGetItem() [ ]
h. batchWriteItem() [ ]
i. transactGetItems() [ ]
j. transactWriteItems() [ ]
4. Data Types and Null Handling
a. top-level null attributes [x]
b. collections with null elements [x]
c. maps with null values [x]
d. conversion between null Java values and AttributeValue [x]
e. full serialization/deserialization cycle with null values [x]
5. AsyncTable and SyncTable
a. DynamoDbAsyncTable Testing [ ]
b. DynamoDbTable Testing [ ]
6. New/Modification in Extensions
a. Tables with Scenario in ScenarioSl No.1 (All table schemas are Must) [ ]
b. Test with Default Values in Annotations [ ]
c. Combination of Annotation and Builder passes extension [ ]
7. New/Modification in Converters
a. Tables with Scenario in ScenarioSl No.1 (All table schemas are Must) [ ]
b. Test with Default Values in Annotations [ ]
c. Test All Scenarios from 1 to 5 [ ]

Types of changes

  • [x] New feature (non-breaking change which adds functionality)

Checklist

  • [x] I have read the CONTRIBUTING document
  • [x] Local run of mvn install succeeds
  • [x] My code follows the code style of this project
  • [ ] My change requires a change to the Javadoc documentation
  • [x] I have updated the Javadoc documentation accordingly
  • [x] I have added tests to cover my changes
  • [x] All new and existing tests passed
  • [ ] I have added a changelog entry. Adding a new entry must be accomplished by running the scripts/new-change script and following the instructions.
  • [ ] My change is to implement 1.11 parity feature and I have updated LaunchChangelog

License

  • [x] I confirm that this pull request can be released under the Apache 2.0 license

anasatirbasa avatar Jul 17 '25 07:07 anasatirbasa