Using the AWS SDK for Kotlin - AWS SDK for Kotlin

This is prerelease documentation for a service in preview release. It is subject to change.

Using the AWS SDK for Kotlin

After Setting up the SDK and Configuring the SDK, you are ready to make requests to AWS services such as Amazon S3, DynamoDB, IAM, Amazon EC2, and more.

This chapter provides instructions and programming examples you can use with the AWS SDK for Kotlin for specific features and AWS services.

Making requests

After you configure a service client, you instantiate it and use its methods to make requests to that AWS service.

For example, this code snippet shows how to create a RunInstancesRequest object to create a new Amazon EC2 instance:

val ec2Client = Ec2Client.fromEnvironment() val runInstancesRequest = RunInstancesRequest { imageId = amiId instanceType = InstanceType.T1Micro maxCount = 1 minCount = 1 } ec2Client.runInstances(runInstancesRequest)

Each non-streaming operation on service clients has DSL overload, which is a type-safe way you can use to define the inputs for operations. For example, the following code snippet is equivalent to the previous one.

val ec2Client = Ec2Client.fromEnvironment() val runInstancesRequest = ec2Client.runInstances { imageId = amiId instanceType = InstanceType.T1Micro maxCount = 1 minCount = 1 }

If you have one or more operations to perform sequentially with the same AWS service, you can use the use extension with a lambda to perform the operations. When you use this method, the service client automatically closes down correctly. See the following code snippet for an example of how to perform the same operation as above without first separately declaring a service client.

Ec2Client { region = "us-west-2" }.use { ec2Client -> ec2Client.runInstances { imageId = amiId instanceType = InstanceType.T1Micro maxCount = 1 minCount = 1 } }

Making concurrent requests

The AWS SDK for Kotlin is natively asynchronous. Each operation is generated as a suspend function, which you call from a coroutine. For additional information about coroutines, refer to the official Kotlin documentation.

To make concurrent requests, use the async coroutine builder to process the response or the launch coroutine builder if you only need to verify that the operation succeeded. asyncreturns a Deferred, a lightweight non-blocking future that represents a promise to provide a result later. launch returns a Job without any associated value. Refer to the following code snippet for an example of how to retrieve the size of two different keys in Amazon S3.

import kotlinx.coroutines.async import kotlinx.coroutines.runBlocking import kotlin.system.measureTimeMillis import aws.sdk.kotlin.services.s3.S3Client fun main(): Unit = runBlocking { val s3 = S3Client { region = "us-west-2" } val myBucket = "bucket-name" val key1 = "first-object-key" val key2 = "second-object-key" val resp1 = async { s3.headObject { bucket = myBucket key = key1 } } val resp2 = async { s3.headObject { bucket = myBucket key = key2 } } val elapsed = measureTimeMillis { val totalContentSize = resp1.await().contentLength + resp2.await().contentLength println("Content length of $key1 + $key2 = $totalContentSize.") } println("Requests completed in $elapsed ms.") }

Making blocking requests

Since the SDK is natively asynchronous, you use the runBlocking coroutine builder to perform operations from blocking code. This will launch a new coroutine and block the current thread until the coroutine completes.

Streaming requests

To make requests containing binary data, you represent these as a ByteStream type. The SDK provides multiple convenience methods to supply a ByteStream, including the following:

  • ByteStream.fromFile(file: File)

  • File.asByteStream(): ByteStream

  • Path.asByteStream(): ByteStream

  • ByteStream.fromBytes(bytes: ByteArray)

  • ByteStream.fromString(str: String)

The following code snippet demonstrates basic usage of these methods.

val request = PutObjectRequest { ... body = ByteStream.fromFile(file) // body = ByteStream.fromBytes(byteArray) // body = ByteStream.fromString("string") // ... }

For more information and a complete list of methods available in the SDK, refer to the aws.smithy.kotlin.runtime.content package in the AWS SDK for Kotlin API Reference.

Handling responses

When you make a request, you can use a response handler to process the response back from the AWS service.

For example, this code snippet shows an example of how to handle the response from Amazon EC2 by printing out the instanceId for the new instance from the request above.

val response = ec2Client.runInstances(runInstancesRequest) println(response.instances?.get(0)?.instanceId)

Refer to the following code snippet for an example of how the complete request might look with use.

Ec2Client { region = "us-west-2" }.use { ec2Client -> val response = ec2Client.runInstances { imageId = amiId instanceType = InstanceType.T1Micro maxCount = 1 minCount = 1 } println(response.instances?.get(0)?.instanceId) }

Streaming responses

Binary data are represented as a ByteStream type, an abstract read-only stream of bytes.

Responses that contain binary stream data, such as from a getObject request to Amazon S3, are handled with a lambda function instead of returning the response directly. This scopes access to the response to the function, simplifying lifetime management for both the caller and the SDK runtime. You must define what will be returned from within the lambda, since all associated resources are released as soon as the function returns.

val s3Client = S3Client.fromEnvironment() val req = GetObjectRequest { ... } val path = Paths.get("/tmp/download.txt") // GetObject has the following signature: // suspend fun <T> getObject(input: GetObjectRequest, block: suspend (GetObjectResponse) -> T): T val contentSize = s3Client.getObject(req) { resp -> // resp is valid until the end of the block // do not attempt to store or process the stream after the block returns // resp.body is of type ByteStream val rc = resp.body?.writeToFile(path) rc } println("SUCCESS: Wrote $contentSize bytes to $path")

The SDK provides various ways of consuming the ByteStream type. These include:

  • ByteStream.writeToFile(file: File): Long

  • ByteStream.writeToFile(path: Path): Long

  • ByteStream.toByteArray(): ByteArray

  • ByteStream.decodeToString(): String

For more information and a complete list, refer to the aws.smithy.kotlin.runtime.content package in the AWS SDK for Kotlin API Reference.

Closing the client

When you no longer need the service client, close it.

ec2Client.close()
Note

Service clients extend the Closable interface. As a best practice - especially with short-lived code such as AWS Lambda functions - explicitly call the close() method.