Skip to content

Commit b958cfd

Browse files
authored
chore: add documentation and example (#90)
1 parent 882550d commit b958cfd

File tree

15 files changed

+648
-6
lines changed

15 files changed

+648
-6
lines changed

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Changelog
2+
3+
## [Unreleased]
4+
5+
## [0.1.0-M0] - 03/19/2021
6+
7+
**WARNING: Beta releases may contain bugs and no guarantee is made about API stability. They are not recommended for production use!**
8+
9+
This is the initial beta release of AWS SDK Kotlin. It represents an early look at the overall API surface.
10+
11+
12+
See the [Getting Started Guide](docs/GettingStarted.md) for how to work with beta releases and examples.
13+
14+
15+
### Services in this release
16+
17+
* DynamoDB
18+
* Polly
19+
* Translate
20+
* Cognito Identity Provider
21+
* Secrets Manager
22+
* NOTE: Default idempotency token provider will not currently work, you'll need to override the config to create or update secrets until [#180](https://github.com/awslabs/smithy-kotlin/issues/180) is implemented
23+
* KMS
24+
* Lambda
25+
26+
NOTES:
27+
* We currently can (theoretically) support any JSON based AWS protocol. If there is a service you would like to see added in a future release (before developer preview) please reach out and let us know.
28+
* No customizations are currently implemented, some SDK's may not behave 100% correctly without such support.
29+
* Retries, waiters, paginators, and other features are not yet implemented
30+
31+
### Features
32+
* Coroutine API
33+
* DSL Builders
34+
* Default (environment or config) or static credential providers only. Additional providers will be added in later releases.
35+
* JVM only support (multiplatform support is on the roadmap)

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
# AWS SDK for Kotlin
22

3-
43
## License
54

65
This library is licensed under the Apache 2.0 License.
76

87

8+
## Getting Started
9+
10+
See the [Getting Started Guide](docs/GettingStarted.md)
11+
12+
913
## Development
1014

1115
### Generate SDK(s)

build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ dependencies {
2121

2222
val lintPaths = listOf(
2323
"codegen/smithy-aws-kotlin-codegen/**/*.kt",
24-
"client-runtime/**/*.kt"
24+
"client-runtime/**/*.kt",
25+
"examples/**/*.kt"
2526
)
2627

2728
tasks.register<JavaExec>("ktlint") {
@@ -48,4 +49,4 @@ tasks.register("showRepos") {
4849
println("All repos:")
4950
println(repositories.map { it.name })
5051
}
51-
}
52+
}

docs/GettingStarted.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Beta Release Quickstart
2+
3+
Beta releases of the AWS Kotlin SDK are published as a complete maven local repository with all associated dependencies.
4+
5+
6+
1. Download the [latest release](https://github.com/awslabs/aws-sdk-kotlin/releases) from Github
7+
8+
2. Unzip the repository somewhere on your local machine
9+
10+
```sh
11+
> unzip aws-sdk-kotlin-0.1.0-M0.zip
12+
```
13+
14+
There should be a folder named `aws-sdk-kotlin-repo`
15+
16+
3. Add the local repository to your Gradle or Maven configuration
17+
18+
#### Gradle Users
19+
20+
```kt
21+
# file: my-project/build.gradle.kts
22+
23+
24+
repositories {
25+
maven {
26+
name = "kotlinSdkLocal"
27+
url = uri("/path/to/aws-sdk-kotlin-repo/m2")
28+
}
29+
mavenCentral()
30+
}
31+
```
32+
33+
#### Maven Users
34+
```xml
35+
<project>
36+
...
37+
<repositories>
38+
<repository>
39+
<id>kotlinSdkLocal</id>
40+
<name>Beta AWS Kotlin SDK Repo</name>
41+
<url>/path/to/aws-sdk-kotlin-repo/m2</url>
42+
</repository>
43+
</repositories>
44+
...
45+
</project>
46+
47+
```
48+
49+
50+
4. Add services to your project
51+
52+
```kt
53+
54+
val awsKotlinSdkVersion = "0.1.0-M0"
55+
// OR put it in gradle.properties
56+
// val awsKotlinSdkVersion by project
57+
58+
dependencies {
59+
implementation(kotlin("stdlib"))
60+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
61+
62+
implementation("aws.sdk.kotlin:dynamodb:$awsKotlinSdkVersion")
63+
}
64+
```
65+
66+
67+
4. Checkout the `examples` directory
68+
69+
70+
## Giving Feedback
71+
72+
* Slack - Join #aws-sdk-kotlin-interest to share feedback and get updates on SDK development
73+
* Submit [issues](https://github.com/awslabs/aws-sdk-kotlin/issues)

examples/build.gradle.kts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
plugins {
2+
kotlin("jvm") version "1.4.31"
3+
}
4+
5+
allprojects {
6+
group = "aws.sdk.kotlin.example"
7+
version = "1.0-SNAPSHOT"
8+
9+
repositories {
10+
maven {
11+
name = "kotlinSdkLocal"
12+
url = uri(TODO("set your local repository path"))
13+
// e.g.
14+
//url = uri("file:///tmp/aws-sdk-kotlin-repo/m2")
15+
}
16+
mavenCentral()
17+
}
18+
}
19+
20+
21+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
plugins {
2+
kotlin("jvm")
3+
}
4+
5+
val awsSdkKotlinVersion: String by project
6+
7+
dependencies {
8+
implementation(kotlin("stdlib"))
9+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
10+
implementation("aws.sdk.kotlin:dynamodb:$awsSdkKotlinVersion")
11+
implementation("com.google.code.gson:gson:2.8.6")
12+
}
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0.
4+
*/
5+
package aws.sdk.kotlin.example
6+
7+
import aws.sdk.kotlin.runtime.AwsServiceException
8+
import aws.sdk.kotlin.services.dynamodb.DynamodbClient
9+
import aws.sdk.kotlin.services.dynamodb.model.*
10+
import com.google.gson.JsonElement
11+
import com.google.gson.JsonParser
12+
import kotlinx.coroutines.delay
13+
import kotlinx.coroutines.runBlocking
14+
import java.lang.IllegalStateException
15+
16+
/**
17+
* Partial implementation of: https://docs.amazonaws.cn/en_us/amazondynamodb/latest/developerguide/GettingStarted.Java.html
18+
*/
19+
fun main() = runBlocking {
20+
val client = DynamodbClient { region = "us-east-2" }
21+
22+
val tableName = "dynamo-movies-example"
23+
24+
try {
25+
createMoviesTable(client, tableName)
26+
27+
client.waitForTableReady(tableName)
28+
29+
loadMoviesTable(client, tableName)
30+
31+
val films2222 = client.moviesInYear(tableName, 2222)
32+
check(films2222.count == 0)
33+
34+
val films2013 = client.moviesInYear(tableName, 2013)
35+
check(films2013.count == 2)
36+
37+
val titles = films2013.items?.mapNotNull { (it["title"] as? AttributeValue.S)?.value }
38+
println("2013 film titles:")
39+
println(titles)
40+
} catch (ex: AwsServiceException) {
41+
println(ex)
42+
}
43+
44+
client.close()
45+
}
46+
47+
suspend fun createMoviesTable(client: DynamodbClient, name: String) {
48+
val tableExists = client.listTables(ListTablesRequest {}).tableNames?.contains(name) ?: false
49+
if (tableExists) return
50+
51+
val req = CreateTableRequest {
52+
tableName = name
53+
keySchema = listOf(
54+
KeySchemaElement {
55+
attributeName = "year"
56+
keyType = KeyType.Hash
57+
},
58+
KeySchemaElement {
59+
attributeName = "title"
60+
keyType = KeyType.Range
61+
}
62+
)
63+
64+
attributeDefinitions = listOf(
65+
AttributeDefinition {
66+
attributeName = "year"
67+
attributeType = ScalarAttributeType.N
68+
},
69+
AttributeDefinition {
70+
attributeName = "title"
71+
attributeType = ScalarAttributeType.S
72+
}
73+
)
74+
provisionedThroughput {
75+
readCapacityUnits = 10
76+
writeCapacityUnits = 10
77+
}
78+
}
79+
80+
val resp = client.createTable(req)
81+
println("created table: ${resp.tableDescription?.tableArn}")
82+
}
83+
84+
// no waiters support (yet)
85+
suspend fun DynamodbClient.waitForTableReady(name: String) {
86+
while (true) {
87+
try {
88+
val req = DescribeTableRequest { tableName = name }
89+
if (describeTable(req).table?.tableStatus != TableStatus.Creating) {
90+
println("table ready")
91+
return
92+
}
93+
} catch (ex: AwsServiceException) {
94+
if (!ex.isRetryable) throw ex
95+
}
96+
println("waiting for table to be ready...")
97+
delay(1000)
98+
}
99+
}
100+
101+
suspend fun loadMoviesTable(client: DynamodbClient, name: String) {
102+
// load items into table
103+
val data = getResourceAsText("data.json")
104+
val elements = JsonParser.parseString(data).asJsonArray
105+
elements.forEach {
106+
// map the json element -> AttributeValue
107+
val attrValue = jsonElementToAttributeValue(it) as? AttributeValue.M ?: throw IllegalStateException("expected a top level object value")
108+
val req = PutItemRequest {
109+
tableName = name
110+
item = attrValue.value
111+
}
112+
113+
client.putItem(req)
114+
}
115+
}
116+
117+
suspend fun DynamodbClient.moviesInYear(name: String, year: Int): QueryResponse {
118+
val req = QueryRequest {
119+
tableName = name
120+
keyConditionExpression = "#yr = :yyyy"
121+
expressionAttributeNames = mapOf(
122+
"#yr" to "year"
123+
)
124+
expressionAttributeValues = mapOf(
125+
":yyyy" to AttributeValue.N(year.toString())
126+
)
127+
}
128+
return query(req)
129+
}
130+
131+
// utility/support functions
132+
133+
fun getResourceAsText(path: String): String =
134+
object {}.javaClass.getResource(path).readText()
135+
136+
// map json to attribute values
137+
fun jsonElementToAttributeValue(element: JsonElement): AttributeValue = when {
138+
element.isJsonNull -> AttributeValue.NULL(true)
139+
element.isJsonPrimitive -> {
140+
val primitive = element.asJsonPrimitive
141+
when {
142+
primitive.isBoolean -> AttributeValue.BOOL(primitive.asBoolean)
143+
primitive.isString -> AttributeValue.S(primitive.asString)
144+
else -> {
145+
check(primitive.isNumber) { "expected number" }
146+
AttributeValue.N(primitive.asString)
147+
}
148+
}
149+
}
150+
element.isJsonArray -> AttributeValue.L(element.asJsonArray.map(::jsonElementToAttributeValue))
151+
element.isJsonObject -> {
152+
AttributeValue.M(
153+
element.asJsonObject.entrySet().associate {
154+
it.key to jsonElementToAttributeValue(it.value)
155+
}
156+
)
157+
}
158+
else -> throw IllegalStateException("unknown json element type: $element")
159+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
[
2+
{
3+
"year": 2013,
4+
"title": "Turn It Down, Or Else!",
5+
"info": {
6+
"directors": [
7+
"Alice Smith",
8+
"Bob Jones"
9+
],
10+
"release_date": "2013-01-18T00:00:00Z",
11+
"rating": 6.2,
12+
"genres": [
13+
"Comedy",
14+
"Drama"
15+
],
16+
"image_url": "http://ia.media-imdb.com/images/N/O9ERWAU7FS797AJ7LU8HN09AMUP908RLlo5JF90EWR7LJKQ7@@._V1_SX400_.jpg",
17+
"plot": "A rock band plays their music at high volumes, annoying the neighbors.",
18+
"rank": 11,
19+
"running_time_secs": 5215,
20+
"actors": [
21+
"David Matthewman",
22+
"Ann Thomas",
23+
"Jonathan G. Neff"
24+
]
25+
}
26+
},
27+
{
28+
"year": 2013,
29+
"title": "Rush",
30+
"info": {
31+
"directors": [
32+
"Ron Howard"
33+
],
34+
"release_date": "2013-09-02T00:00:00Z",
35+
"rating": 8.3,
36+
"genres": [
37+
"Action",
38+
"Biography",
39+
"Drama",
40+
"Sport"
41+
],
42+
"image_url": "http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg",
43+
"plot": "A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.",
44+
"rank": 2,
45+
"running_time_secs": 7380,
46+
"actors": [
47+
"Daniel Bruhl",
48+
"Chris Hemsworth",
49+
"Olivia Wilde"
50+
]
51+
}
52+
}
53+
]

examples/gradle.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
# AWS SDK
3+
awsSdkKotlinVersion=0.1.0-M0
4+
57.8 KB
Binary file not shown.

0 commit comments

Comments
 (0)