• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1**Design:** New Feature, **Status:** Design
2
3## Problem
4
5In DynamoDB, an [item](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html) is a
6collection of attributes, each of which has a name and a value. Aws-sdk-java 1.x  provided Document API to access these
7items. The user could access these items without actually knowing the complete schema of the entire item. This feature
8did not exist in Aws-sdk-java 2.x. This document proposes mechanism by which user will be able to access the DDB items
9as documents using enhanced dynamodb client.
10
11### Requested features
12Aws-sdk-java 2.x should provide Document API similar to that of aws-sdk-java 1.x with following APIs
13
141. APIs to access DynamoDB for complicated data models without having to use DynamoDB Mapper.
15   For example, APIs for converting from JSON to DynamoDb items & vice versa.
162. APIs to manipulate semi structured data for each of the attribute values.
17   For example, APIs to access the AttributeValue as string sets, number sets,  string list, number list etc.
183. Allow direct read and write of dynamoDB elements as Documents.
19
20Example Github issue: https://github.com/aws/aws-sdk-java-v2/issues/36
21
22## Current functionality
23Aws-sdk-java 2.x currently supports Mid-level DynamoDB mapper/abstraction for Java by providing Mapper Clients.
24While using these mappers the user needs to define the complete Table schema at the time of mapped table creation.
25
26## Naming conventions
27Please note that the names of classes and api mentioned in this design document  are not final and might get changed
28based on future reviews
29
30## Proposed Solution
31
32Add a new DocumentSchema in existing enhanced client. This schema just needs the primary key and sort key to be defined
33at the time of mapped table creation. This will retrieve the dynamo db table items as Documents.
34User can then access the attribute values from these documents by getters.
35Similarly , user can create a new Document and insert it to the mapped table by using the builder apis of Document.
36
37### Enhanced Client Table Schema creation API
38The DocumentSchema is created by supplying partitionKey, sortKey and optional attributeConverterProviders in the builder.
39If AttributeConverterProvider are not supplied in TableSchema the Document Table schema will use the default converter
40providers.
41~~~java
42 // Existing way of creating enhanced client
43 DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder().build();
44
45// New API in TableSchema to create a DocumentTableSchema
46DocumentTableSchema documentTableSchema =
47    TableSchema.documentSchemaBuilder()
48               .addIndexPartitionKey(primaryIndexName(), "sample_hash_name", AttributeValueType.S)
49               .addIndexSortKey("gsi_index", "sample_sort_name", AttributeValueType.N)
50               .addAttributeConverterProviders(cutomAttributeConverters)
51               .build();
52
53 // Existing API to access DynamoDB table.
54 DynamoDbTable<EnhancedDocument> documentTable = enhancedClient.table("table-name", documentTableSchema);
55~~~
56*addAttributeConverterProviders = Appends custom attribute converter providers to the defaults provided by sdk*<br>
57
58### Accessing Document  from DDB table
59#### Reading a document to DDB Table
60The DocumentSchema mapped table returns items as EnhancedDocument,
61The EnhancedDocument can then be used to retrieve attribute values.
62
63~~~java
64// Creating a document which defined primary key of the item needs to be retrieved
65EnhancedDocument hashKeyDocument = EnhancedDocument.builder()
66                                                    .addString("sample_hash_name", "sample_value")
67                                                    .build();
68// Retrieving from existing Get operation.
69EnhancedDocument retrievedDocument = documentTable.getItem(hashKeyDocument);
70
71// Retrieving from existing Get operation
72EnhancedDocument documentTableItem = documentTable.getItem(
73                                        EnhancedDocument.builder()
74                                                        .addString("sample_hash_name", "sample_value")
75                                                        .build());
76
77// Accessing an attribute from document using generic getter.
78Number sampleSortvalue = documentTableItem.get("sample_sort_name", EnhancedType.of(Number.class));
79
80// Accessing an attribute from document using specific getters.
81sampleSortvalue = documentTableItem.getNumber("sample_sort_name");
82
83// Accessing an attribute of custom class using custom converters.
84CustomClass customClass = documentTableItem.get("custom_nested_map", new CustomAttributeConverter()));
85
86// Accessing Nested set
87Set<List<String>> stringSet = documentTableItem.get("string_set", new EnhancedType<Set<List<<String>>>(){}));
88~~~
89
90
91#### Writing a document to DDB Table
92The EnhancedDocument provides builder method to create documents that can be put to DocumentSchema mapped table.
93
94~~~java
95
96// Creating a document from Json input.
97EnhancedDocument  documentFromJson = EnhancedDocument.fromJson(("{\"sample_hash_name\": \"sample_value_2\"}"));
98// put to dynamo db table
99documentTable.putItem(documentFromJson);
100
101// Creating a document from EnhanceDocumentBuilders
102EnhancedDocument documentFromBuilder = EnhancedDocument.builder()
103                                                       .addString("sample_hash_name", "sample_value_2")
104                                                       .addNumber("sample_sort_name", 111)
105                                                       .addNumberList("sample_names", 1 ,2 ,3, 4)
106                                                       .build();
107
108// put to dynamo db table
109documentTable.documentFromBuilder(documentFromBuilder);
110
111// retrieving a document from dynamo db and updating some attributes
112EnhancedDocument documentTableItem = documentTable.getItem(hashKeyDocument);
113// using toBuilder to make a copy of the retrieved item and then modifying the key attribute
114EnhancedDocument changedValue = documentTableItem.toBuilder().addString("key-to-change", "changedValue").build();
115// put to dynamo db table
116documentTable.putItem(changedValue);
117~~~
118
119
120#### Attribute converter providers for EnhancedDocument
121
122A builder method would be provided to add Attribute converters for an EnhancedDocument.
123The default value of attribute converter field would be null for EnhancedDocument.
124
125Q: What converter providers will be used for EnhancedDocument retrieved from Dynamo db?<br>
126A: For the EnhancedDocuments retrieved from the SDK get/scan/query operations the DefaultAttributeConverterProviders would
127be assigned by default. If the user has provided attribute converter providers at the time of table creation then these
128converters will be used.
129
130Q: What converter providers  would be used for EnhancedDocument created by the user ?<br>
131A: The converter providers supplied by the user in the EnhancedDocument builders. If no converter providers are provided
132then user will get error while trying to get the attribute values. Thus, user should always supply defaultConverterProviders
133while creating the EnhancedDocuments for which user wants to access the attriute values latter.
134
135
136#### Getters and Setters for EnhancedDocuments
137
138Q: What kind of getter API would be available for EnhancedDocument?<br>
139A: Following getter API would be available in EnhancedDocument
140 1. Class specific getters like getString(), getNumber, getMap() same as V1.
141 2. Generic getter API for any EnhancedType.
142 3. Getters with ConverterProviders in ares
143
144Q: What kind of setter API would be available for EnhancedDocument?<br>
145A: Following builder API would be available in EnhancedDocument
1461. Class specific builder like addString(), addNumber, addMap() same as V1.
1472. Generic builder API for any EnhancedType like add(value, EnhancedType).
1483. Builders for custom classes with Custom converter providers/
149
150## Appendix B: Alternative solutions
151
152### Design alternative: Using existing Document APIs from Sdk-core
153This design approach enhances the software.amazon.awssdk.core.document.Document with additional APIs enhancing it for
154better experience writing and reading open content.
155
156#### Reading flat structures from DynamoDB
157~~~java
158Document document = table.getItem(Key.builder().partitionValue("0").build());
159// Current Document API
160String id = document.asMap().get("id").asString();
161Instant time = Instant.parse(document.asMap().get("time").asString());
162
163// Document Converters API
164String id = document.get("id", String.class);
165Instant time = document.get("time", Instant.class);
166
167// Document JSON API
168String json = document.toJsonString();
169
170~~~
171
172**Decision**
173
174This alternative was discarded since it doesnot make use of existing converter providers.
175The Document will be required to be converted from key-AttributeValue map to Documents , for which new jsonNode converters
176needs to be implemented.