The new AWS SDK for Kotlin with Coroutines support

The new AWS SDK for Kotlin was announced at AWS re:Invent in December 2021. Using the SDK, you can build Kotlin applications that work with Amazon S3, Amazon EC2, DynamoDB, and more. The SDK is currently in preview and is expected to become stable soon.

The SDK was designed from the ground up to support the Kotlin language and its best practices, providing Kotlin developers with a familiar and idiomatic experience for interacting with AWS. The SDK leverages Kotlin coroutines for asynchronous implementation, and there are plans to make it compatible with Kotlin multiplatform projects.

To start using the new SDK in your Kotlin programs, you’ll need to add a corresponding dependency to your project. For instance, if we would like to communicate with DynamoDB, then the aws.sdk.kotlin:dynamodb module is required:

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
    
    // The following line adds a dependency on the dynamodb client.
    // For demonstration purposes, we use 0.+ to get the latest version
    implementation("aws.sdk.kotlin:dynamodb:0.+")
}

You can find the complete list of supported modules in the documentation for the AWS SDK.

After downloading the dependencies we can start using the API:

import kotlinx.coroutines.runBlocking
import aws.sdk.kotlin.services.dynamodb.DynamoDbClient
//sampleStart 
fun main() = runBlocking {
    val client = DynamoDbClient { region = "us-east-2" }
    val resp = client.listTables { limit = 10 }

    println("Current DynamoDB tables: ")
    resp.tableNames?.forEach { println(it) }

    client.close()
}
//sampleEnd 

The program simply retrieves the list of tables and prints the table names into the standard output. In the example above, listTables is a suspending function, so the code is wrapped into a runBlocking call.

How about a slightly more complex example that demonstrates downloading every S3 object in a bucket to a local temporary directory, featuring paginated access, concurrent flows, and byte-streaming responses?

import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.GetObjectRequest
import aws.sdk.kotlin.services.s3.model.ListObjectsV2Request
import aws.sdk.kotlin.services.s3.paginators.listObjectsV2Paginated
import aws.smithy.kotlin.runtime.content.writeToFile
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flowOf
import java.nio.file.Paths
import kotlin.io.path.createDirectories
//sampleStart 
suspend fun downloadAllS3Objects(bucketName: String) {
   val s3 = S3Client.fromEnvironment()
   val listReq = ListObjectsV2Request {
       bucket = bucketName
   }
   s3.listObjectsV2Paginated(listReq)
       .flatMapConcat { it.contents?.asFlow() ?: flowOf() }
       .filter { it.size > 0 }
       .collect { obj ->                     
           val getReq = GetObjectRequest {
               bucket = bucketName
               key = obj.key
           }
           s3.getObject(getReq) {
               val path = Paths.get(System.getProperty("java.io.tmpdir"), obj.key)
               path.parent.createDirectories()
               it.body?.writeToFile(path)
           }
       }
}
//sampleEnd

In the example above, you can see again the use of the suspending functions in the SDK: the getObject and writeToFile functions are all marked with the suspend keyword.

In the official documentation for the new AWS SDK for Kotlin, you can find detailed step-by-step instructions on how to get started. Also, you can find a number of interesting examples that demonstrate the API with a number of AWS services such as Amazon DynamoDB, S3, Rekognition, Amazon Simple Notification Service, and AWS Key Management Service.

The new AWS SDK for Kotlin is in active development and you can check out what features are planned in the roadmap. Try it now and let us know what you think!

Continue ReadingThe new AWS SDK for Kotlin with Coroutines support

适用于 Kotlin 并支持协同程序的新 AWS SDK

适用于 Kotlin 的新 AWS SDK 已于 2021 年 12 月在 AWS re:Invent 上宣布。 您可以使用此 SDK 构建与 Amazon S3、Amazon EC2、DynamoDB 等协同工作的 Kotlin 应用程序。 SDK 目前处于预览阶段,预计很快会推出稳定版。

从头开始设计 SDK 是为了支持 Kotlin 语言及其最佳做法,为 Kotlin 开发者提供与 AWS 交互的熟悉和惯用体验。 SDK 利用 Kotlin 协同程序进行异步实现,并计划使其兼容 Kotlin 多平台项目。

要开始在 Kotlin 程序中使用新 SDK,您需要向项目添加相应的依赖项。 例如,如果要与 DynamoDB 通信,则需要 aws.sdk.kotlin:dynamodb 模块:

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
    
    // The following line adds a dependency on the dynamodb client.
    // For demonstration purposes, we use 0.+ to get the latest version
    implementation("aws.sdk.kotlin:dynamodb:0.+")
}

您可以在 AWS SDK 文档中找到受支持模块的完整列表。

下载依赖项后,即可开始使用 API:

import kotlinx.coroutines.runBlocking
import aws.sdk.kotlin.services.dynamodb.DynamoDbClient
//sampleStart 
fun main() = runBlocking {
    val client = DynamoDbClient { region = "us-east-2" }
    val resp = client.listTables { limit = 10 }

    println("Current DynamoDB tables: ")
    resp.tableNames?.forEach { println(it) }

    client.close()
}
//sampleEnd 

该程序只会检索表的列表,并将表名打印到标准输出中。 在上面的示例中,listTables 是一个挂起函数,因此代码被包装到 runBlocking 调用中。

我们来看一个稍微复杂一点的示例,演示如何将存储桶中的每个 S3 对象下载到本地临时目录(包含分页访问、并发流和字节流响应)。

import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.GetObjectRequest
import aws.sdk.kotlin.services.s3.model.ListObjectsV2Request
import aws.sdk.kotlin.services.s3.paginators.listObjectsV2Paginated
import aws.smithy.kotlin.runtime.content.writeToFile
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flowOf
import java.nio.file.Paths
import kotlin.io.path.createDirectories
//sampleStart 
suspend fun downloadAllS3Objects(bucketName: String) {
   val s3 = S3Client.fromEnvironment()
   val listReq = ListObjectsV2Request {
       bucket = bucketName
   }
   s3.listObjectsV2Paginated(listReq)
       .flatMapConcat { it.contents?.asFlow() ?: flowOf() }
       .filter { it.size > 0 }
       .collect { obj ->                     
           val getReq = GetObjectRequest {
               bucket = bucketName
               key = obj.key
           }
           s3.getObject(getReq) {
               val path = Paths.get(System.getProperty("java.io.tmpdir"), obj.key)
               path.parent.createDirectories()
               it.body?.writeToFile(path)
           }
       }
}
//sampleEnd

在上面的示例中,您可以再次看到 SDK 中挂起函数的使用:getObject 和 writeToFile 函数都使用 suspend 关键字进行标记。

您可以在适用于 Kotlin 的新 AWS SDK 的官方文档中找到有关如何入门的详细分步说明。 此外,您还可以找到许多有趣的示例,它们使用 Amazon DynamoDB、S3、Rekognition、Amazon Simple Notification Service 和 AWS Key Management Service 等一系列 AWS 服务来演示 API。

适用于 Kotlin 的新 AWS SDK 正在积极开发中,您可以在路线图中查看计划的功能。 立即试用,并告诉我们您的想法!

英文博文原作者:

Anton Arhipov

Continue Reading适用于 Kotlin 并支持协同程序的新 AWS SDK

Faire Сase Study: Kotlin Backend for a Disruptive SMB Marketplace

Like most startups, at the beginning of its journey Faire was looking for an efficient solution to base its tech stack on. Having started with Java, a year in, the company started looking for other options, and opted for Kotlin. They now use Kotlin for their Android app and for the website backend, which successfully handles up to 1K requests per second.

The current backend repo has 788,020 lines of code within 6,078 Kotlin files, with roughly 45 engineers actively committing code and more onboarding every week.

We chatted with Jeff Gulbronson, a software engineer who has been with Faire since it was a year old, about Faire and why it chose Kotlin. The key benefits of Kotlin he identified were:

  • Kotlin improves developers’ productivity thanks to its modern language features, and helps avoid common Java mistakes.
  • Interop with Java makes it easy to use existing Java libraries.
  • Easy to get started as a Java developer, making hiring easier.
  • Using Kotlin makes the engineering team happier.

Let’s look at Faire’s journey together with Jeff.


Kotlin is an excellent choice for server-side application development. Go to the Kotlin for server-side page to learn more.


About Faire

Originating in the US, Faire is a wholesale marketplace that aims to help small and medium businesses (SMBs) to compete against the likes of Amazon and Walmart and chase their dreams.

The platform is backed by investors, such as Y Combinator, Sequoia Capital, and DST Global. At the end of 2020, Faire raised 170M at a 2.5B valuation and is now looking to expand into Europe.

Architecture Overview

Faire’s backend monolith is written entirely in Kotlin, as are the new services they create as they seek to replace the old monolith system. They make use of both traditional Java libraries, such as Hibernate for ORM, and Guice for dependency injection, as well as libraries written in Kotlin such as Wire for protocol buffers and OkHTTP for network requests. The architecture is standard – a MySQL database, Redis for caching, and then Amazon’s Simple Queue Service (SQS) to run jobs asynchronously.

When an HTTP request comes in, it hits an external load balancer (an Amazon Elastic Load Balancer).

The request is routed to the Kubernetes cluster, where it arrives at an Nginx instance to see which service to route to.

The code is split into two main groups: web server and worker pods. Web server pods service incoming HTTP requests, and enqueue jobs. The jobs are handled by the worker pods, which also handle recurring tasks such as “Run this piece of code every day at 1 am”.

MySQL is the primary data store, and Redis is used for caching. Faire uses an event-streaming service (Kinesis Firehose) to stream data into their data warehouse.

Why Kotlin?

While Java was a fine language choice, Faire started looking for a programming language that would be more expressive and fix some of its shortcomings. Jeff worked with Kotlin at his previous company and had been exposed to how powerful it is. He suggested trying Kotlin and seeing if it would be a better fit for Faire to replace Java.

Kotlin had full interop with the JVM, behaved similarly to Java, but cut down on the rough edges with features such as nullable types, object keyword, mutable vs immutable collections, and more.

“We decided to switch because we liked the velocity of new Kotlin features, and felt the features available at the time made it worth switching to. The fact that the Java interop is first-tier made it extremely easy to introduce Kotlin to the codebase, as there was little to no risk if we decided to switch back to Java in the future.”

For Faire, Kotlin in many ways came across as a “better Java”, for Faire and they jumped into the migration process.

Java to Kotlin Migration: Challenges and Benefits

The initial commit to add Kotlin was only a few files: one to convert a simple existing Java file to Kotlin, and then a couple of updates to the team’s Maven files to update the build system.

They started the migration process by using the Java-to-Kotlin converter built into IntelliJ IDEA. Automated conversion isn’t perfect and requires some manual work to make the code fluent. There were cases where a Java Integer would be converted to a Kotlin Int, only for the team to find out that field is in fact nullable (sometimes in tests, other times in staging).

Migration to Kotlin helped to reveal previously made assumptions about the nullability of different variables. In Java, extra validation would have to be added to call-sites to catch and prevent errors; with Kotlin, this work could be delegated by leveraging the type system and relying on the compiler. This resulted in less boilerplate code for null checks and improved quality by eliminating human mistakes.

In early 2018 there weren’t many other companies using Kotlin for the backend, so it was tough to find external resources for specific issues. Faire developers overcame these issues through trial and error. For example, Kotlin leans towards final by default, which in some cases conflicts with how Hibernate works. They eventually learned how to properly integrate with Java libraries and built up best practices, and as more of the code was converted to Kotlin, they saw fewer and fewer NPEs.

“Finally Kotlin let us use a modern language that new hires are happy to use. Really it’s like ‘Java Next’, which I think is the sweet spot for server use cases.”

Today the community generates lots of helpful materials. But when it’s your first exposure to a technology, it can be tricky to navigate them. To get daily access to Kotlin news and discussions join our community Slack.

Favorite features

“Java Interop — it feels weird to call this a feature, but we would not have been able to migrate to Kotlin without it. I was extremely impressed by how thoughtful the language creators were around interop, which with the exception of a few nuances, made it extremely easy to migrate our codebase.”

  • Data classes — data classes were a godsend in terms of debuggability (via toString), but also in terms of correctness (via equals and hashCode). On the server, the team is constantly creating small classes to move data around.
  • Type system (including read-only collections) — Java libraries provided some of the features that Kotlin gives first-class support for. One such case is ImmutableList and ImmutableSet which are provided by Guava. Another is using the @Nullable and @NotNull annotations to document variables. Kotlin puts all of these into the type system with List vs MutableList, and List vs List?. Having first-class support for these in the type system means the language can offer support for them via the standard library, and it doesn’t feel like they’re hacked on to the language. Simply put, this makes the development experience much nicer and lets the language do more of the work.
  • Lambda expressions and type inference — these deserve a special mention, they are again another godsend for us coming from Java (this was pre-Java 11, so no var keyword). Passing a function around in Java was a nightmare from a type system perspective, which meant we very rarely did it. And having to declare all types (even though IntelliJ IDEA helped) was a drag. With those two features combined, it feels like we can write the code we want (e.g. pass a lambda to a function to be invoked), as there is Java to resist it with its lack of functional support.

Summary

Converting from Java to Kotlin was fun and easy for Faire thanks to the excellent interop between Java and Kotlin. It also brought an additional advantage to the startup in terms of recruiting. Being able to work in a more modern language was compelling to a lot of the developers. And for many it was a new opportunity to write Kotlin in a production environment. Eventually, Faire found almost all of its developers much happier and more productive.

Continue ReadingFaire Сase Study: Kotlin Backend for a Disruptive SMB Marketplace

Expedia Group: Bootiful APIs With GraphQL and Kotlin

About Expedia

Expedia Group is the world’s travel platform. We help knock down the barriers to travel, making it easier, more enjoyable, more attainable and more accessible. We are here to bring the world within reach for customers and partners around the globe. We leverage our platform and technology capabilities across an extensive portfolio of businesses and brands to orchestrate the movement of people and the delivery of travel experiences on both a local and global basis.


Kotlin is an excellent choice for server-side application development. Go to the Kotlin for server-side page to learn more.


The technology stack at Expedia Group

The JVM is the primary technology stack used by the backend services at Expedia Group. The individual teams can choose their technology stack outside of the JVM, but since most libraries are Java-based, most of the backend stack is JVM-based as well. With the microservice architecture, there are currently hundreds of Spring Boot apps powering various parts of the customer experience.

Some teams within Expedia began experimenting with Kotlin on the server side in late 2017. Thanks to the expressiveness of the language, Kotlin quickly gained popularity among developers, and many greenfield projects started adopting it. Soon after, Kotlin became part of the core technology stack. It has also now become the language of choice for developing the new GraphQL services. Kotlin adoption is growing steadily at Expedia, and it is used to power a number of services including GraphQL, REST, and gRPC-based APIs.

Why Kotlin?

Expedia adopted Kotlin because of its null-safety compiler guarantees, the conciseness of the language, and its full Java interoperability. Interoperability with Java made a gradual Kotlin integration possible without having to fully rewrite applications. Migrating existing Java applications to Kotlin generally followed the path of introducing Kotlin data classes first and then gradually migrating the rest of the source code. Java interoperability also allowed Expedia to easily integrate Kotlin applications with Java libraries and fully utilize the existing JVM ecosystem.

Kotlin Coroutines were a critical factor in the wide adoption of the language. They allow developers to write fully asynchronous code in an imperative way, which leads to more readable and maintainable code. The Spring Framework is used heavily at Expedia, and starting with version 5.2 it introduced interoperability between WebFlux and coroutines. For the engineers at Expedia, this was a game-changer that made it possible to leverage the Spring and Reactive stack in a more imperative way.

GraphQL with Kotlin

GraphQL was created to address the needs of mobile clients – it provides a single API for all the clients to integrate with that allows them to selectively ask for the data they need and that can be modified without breaking any of the existing clients. When Expedia started modernizing its frontend stack, they decided to move toward GraphQL and build a single API gateway to power all frontend applications. In order to streamline the development experience and ensure that the code is a single source of truth for the APIs, Expedia applies Kotlin’s powerful reflection library to generate the GraphQL schema directly from the source code.

“We believe that the ability to generate your GraphQL schemas directly from the source is useful functionality that can benefit the open-source community, so we open-sourced the resulting libraries as graphql-kotlin to help developers run GraphQL in Kotlin.” — Dariusz Kuc, Principal Software Engineer

Over time, the graphql-kotlin libraries grew to provide additional functionality, including a Spring Boot autoconfiguration library that eliminates all the boilerplate code needed to configure and run a GraphQL server. As a result, developers can simply write functions that return data classes, and the graphql-kotlin libraries will automatically convert them to a valid GraphQL schema and start a reactive Spring Boot web application.

At KotlinConf 2019, Dariusz Kuc and Guillaume Scheibel talked about how to utilize the power of Spring Boot together with graphql-kotlin. Watch the video:

The shift to Kotlin Coroutines

Expedia started the development of the new GraphQL services using Spring MVC, which relies on a blocking servlet threading model. While it worked, blocking threads was not the most efficient use of hardware resources. Since GraphQL services return data from some downstream services and data stores, whenever there is a dependency on a slow resource, underlying threads end up blocked as they wait for the data to arrive. Reactive frameworks allow you to process the data in a non-blocking way and are a good tool for approaching this problem.

Expedia’s first attempt with reactive frameworks was with RxJava, which helped to parallelize the downstream calls. While it worked for simple things, there were several issues that arose. Developers attempted to use traditional imperative programming models within the reactive paradigm. They were using incorrect operators or causing some unintended side effects. As a result, due to the different programming models, additional training was required, which slowed down the onboarding process of new developers.

That’s why, when Spring announced full interop between their reactive WebFlux framework and Kotlin coroutines, Expedia quickly switched. Thanks to the imperative programming model of Kotlin Coroutines, it was much easier for developers to learn and use it effectively. Coroutines quickly became the preferred way to write highly performant asynchronous code.

“Thanks to Kotlin’s conciseness and support for imperative programming style for writing fully asynchronous code, the resulting code is much more readable and maintainable. “ — Dariusz Kuc, Principal Software Engineer

Summary

In short, the following features make Kotlin an attractive programming language at Expedia:

  • Conciseness. The expressiveness of the language results in concise code, making it possible to write less code with fewer mistakes.
  • Null-safety. This extra safety feature is built into Kotlin’s compiler, resulting in fewer issues with dereferencing null values.
  • Java-interoperability. The fact that you can leverage the Java ecosystem, with all its frameworks and libraries, is a serious productivity booster! You also don’t have to rewrite the Java application fully in Kotlin – you can introduce Kotlin code gradually into your Java project and migrate slowly.
  • Kotlin Coroutines. These offer an easy way to master the asynchronous code with an imperative programming model. The fact that Coroutines support was added to the Spring Framework made it even easier to take advantage of this feature.
Continue ReadingExpedia Group: Bootiful APIs With GraphQL and Kotlin

End of content

No more pages to load