Auto Added by WPeMatico

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

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

Sannsyn Case Study: a High-performance Backend for Modern Machine Learning

Sannsyn provides artificial intelligence-based solutions for businesses that want to improve their user experience, increase their customer loyalty, and boost their conversion rates. Personalized customer recommendations are a core functionality for the solutions Sannsyn offers.

These solutions pose a unique technical challenge with a multitude of components on the server-side with billions of interactions across a complicated system, all while keeping the client-side simple.

Sannsyn has never looked back after choosing Kotlin, and here is why:

  • Great interoperability – Kotlin makes it possible to have all sorts of JVM components, including Scala and Clojure.
  • A perfect solution for high-performance backend applications.
  • Everyone on the team that has tried it has fallen in love with it!

We asked Hallvard, Sannsyn’s Community Manager for TellusR to tell us about the story of how Sannsyn applies Kotlin to complex system development.

Solution Overview

The Gravity platform is one of Sannsyn’s flagship products. On the surface it seems rather simple: submit customer events and retrieve customer recommendations. But under the hood, it’s a hive of components, structures, and messages that communicate back and forth between each other.


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


Requests come in over HTTPS to a frontend server and are then dispatched to an Akka-based system made up of small components, each with very specific and specialized tasks. Without going into too much detail, the process looks like this:

Since the Gravity platform is spread out over different machines, Akka is used for internal communication across the system. While the Akka ecosystem is based on Scala, the team prefers to stick to the JVM platform rather than limit the focus to just Scala and Akka. Different components are implemented in Scala, Java, Clojure, and Kotlin − sometimes there is code that is compiled from different languages that coexist in the same JVM. It is precisely this no-effort interoperability within this multitude of languages that is one of Kotlin’s key strengths.

Let’s take our Akka integration as a practical example. Sending messages between actors is performed in Akka/Scala with the very elegant ! command. This, for instance, will send theMessage to theActor:

theActor ! theMessage

Why not have this in our Kotlin code as well? We could use `!` to make it look as much like the original as possible, but Kotlin can’t do this without the backticks, and they really aren’t very elegant, so we chose to create a tell function instead. So, what we wanted was this:

    
theActor tell theMessage

And this can be easily achieved using the following:

    
private infix fun ActorRef.tell(msg: String) = this.tell(msg, self)

So, we didn’t end up with the elegant ! we wanted from the Scala code. But then, we implemented the same thing for the forward function. Akka hasn’t done this, but for consistency of expression, we would like the forward function to be used in the same manner as the tell function. So, this is how we defined it:

    
private infix fun ActorSelection?.forward(message: String) = this?.forward(message, context)

And what this gave us, was more of Akka’s elegance than Akka has by itself!

It is also worth noting that the extension function this time is on a nullable type. We have some ActorSelection objects lying around that need to be nullable since they are constructed from a configuration that might be missing. And, since we’re allowed to define the extension function on a nullable type, we can add this extra elegance without having to bloat the code with null checks on every call site. We’ve really appreciated this feature!

So, when we then started work on our newest product, the Solr refiner named TellusR, Kotlin was the natural choice for us. We quickly came to appreciate it. The thing with writing code that hooks into other people’s code is that the stack traces very often include lines that are unrelated to your own code. So, to simplify the reading of long stack traces we wrote two small extensions to pinpoint our own responsibility in different exceptions. The first extension picked up the last line of Sannsyn code involved:

    
val Throwable.stackTraceTopString
    get() = stackTrace.firstOrNull {
            it.className.contains("com.sannsyn")
        }?.toString()?.trimStart()

And then another extension which combined this with the actual error message before it was written into our logs:

val Throwable.messageAndCrumb
    get() = "${localizedMessage ?: toString()} (${stackTraceTopString ?: "-"})"

This small measure has saved us a lot of time when it comes to searching for the culprit of errors. This is our new favorite Logback one-liner:

logger.warn("HERE: {}", e.messageAndCrumb, e)

Since this is only six small lines of code, it quickly spread from TellusR over to all our other Kotlin-based projects.

Why Kotlin?

Sannsyn began using Kotlin because of Kotlin’s take on null objects. This was back before Kotlin had released a 1.0 version. Back then Sannsyn was maintaining a client’s eBook reading app, and struggled with the Android version’s many NPEs. The team conducted research to find a null-safe language for the JVM, hoping it might be usable on the Android platform.

Moving to Kotlin on Android proved simple and problem-free. Integrating it with the existing Java code was a piece of cake too. So the natural move was to try Kotlin with products on the server.

In addition to the nullability handling, there was also another great benefit to using Kotlin – its seamless integration with JVM languages. All other JVM based languages recognized and understood Kotlin’s bytecode immediately. And there was the fact it is supported in IntelliJ IDEA!

“Since the very beginning of our migration to Kotlin, IntelliJ IDEA has been around to support us. Making the move to Kotlin really felt like just upgrading from Java.”

Besides the goal of minimizing NPEs, exploring this new language in the making turned out to be fun! Multiplatform build options came out at exactly the right time. During the MPP solution release, the Sannsyn team were struggling with the port of an internal message format that had to be usable in both JavaScript and code for mobile devices. 

Instead of maintaining an external protocol that all these projects had to respect, they now simply program the protocol in an MPP project so there is only one codebase, and use the produced bytecode and JavaScript code everywhere afterwards. This has saved our developers a lot of effort and reduced the risk of introducing protocol errors.

Favorite features

“Our main focus originally was the NPEs, so our favorite feature in Kotlin is the nullability handling”.

  • The syntax of the higher order functions. Kotlin is almost at a Haskell level here. There is no need to split it into streams and aggregate afterwards.
  • Kotlin’s type inference makes code pretty non-verbose. This, along with data classes, keeps the code very concise and elegant.
  • The language design around coroutines is brilliant! More lightweight than threads, sure; non-blocking, sure; but let’s not forget that also the design of the syntax in this case makes programming in asynchronous environments easier.

Summary

Initially attracted to Kotlin as an NPE killer, Sannsyn engineers enjoy compact and neat syntax, well-designed solutions like coroutines, multiplatform projects with the option of code sharing, and of course first-class IntelliJ IDEA support. They also really love interoperability with the JVM and the happiness which Kotlin brings to the team.

Continue ReadingSannsyn Case Study: a High-performance Backend for Modern Machine Learning

Server-side With Kotlin Webinar Series, Vol. 4

Announcing a new series of webinars about Kotlin for server-side! These will be held between December 14 and 21. Join the live sessions or catch-up on the recordings afterwards!

In this webinar series, our speakers will host step-by-step live coding sessions to show you what kinds of benefits you can get from Kotlin for server-side and its rich ecosystem.

Subscribe to our YouTube channel to stay up-to-date with all the planned webinars and upcoming videos!

Follow Kotlin on YouTube

Object Detection and Image Recognition with Kotlin

Tempered in the crucible of Apache Hadoop and Apache Spark, Alexey Zinoviev has spent the past few years working on Machine Learning frameworks for JVM programming languages (Java, Scala, and Kotlin). Since 2020, Alexey has been actively contributing to the new Deep Learning framework created at JetBrains.

In this webinar, we will explore a deep learning library written in Kotlin, learn how to detect objects of different types in images, build predictive models on numeric data, and use KTor and KotlinDL to create a Kotlin Web Application that will recognize animals in the images.

Dec 14, 2021
4pm–5pm UTC

Register

Functional Programming in Kotlin with Arrow.kt

Simon Vergauwen and Alejandro Serrano are both engineers at 47 Degrees. Simon is one of the maintainers of the Arrow library. And Alejandro is slowly moving to Kotlin after a decade of being a Haskeller. In fact, he has written a couple of books on the subject!

Arrow strives to be a great functional companion library for Kotlin. This is not just a matter of style: this functional style makes it easy for us to describe complex patterns, and our goal is to showcase a few of these patterns in the context of a Ktor project. We’ll discuss how to handle retries using circuit breakers and schedulers, and how to carry out powerful validation. Along the way, we’ll show bits and pieces of other Arrow projects, like optics and analysis.

Dec 15, 2021
4pm–5pm UTC

Register

Building web applications with Ktor and Exposed

Anton Arhipov is a Developer Advocate on the Kotlin team at JetBrains. His professional interests include programming languages and developer tooling. Anton has been a Java Champion since 2014 and is also a co-organizer of DevClub.eu, a local developers community based in Tallinn, Estonia.

Ktor is a lightweight framework for building asynchronous server and client applications. Exposed is a database access library that is often used with Ktor. In this session, you will learn how to bootstrap a project with Ktor, build interaction between server and client via WebSockets, and add database support with the Exposed library.

Dec 21, 2021
4pm–5pm UTC

Register

Save the date

Once you’ve registered, we’ll send you a confirmation email with calendar invitations. We’ll also send you a reminder one day before each of the webinars begin.

All webinars are free to attend and will be recorded and published on YouTube after streaming. Subscribe to the Kotlin by JetBrains YouTube channel to be notified about each uploaded recording.

Learn more about server-side Kotlin

We’ve created a page with lots of useful reference materials about using Kotlin on the backend. Follow the link below for tips, tricks, and best practices, all carefully curated by the Kotlin team.

Go to Kotlin server-side page

Continue ReadingServer-side With Kotlin Webinar Series, Vol. 4

Kotlin for Server-Side Frameworks News: Kotlin Premier Event Presentation Highlights

The Kotlin Online Event is over. But we thought we’d give a quick recap of the two server-side talks: What’s New in Ktor 2.0 and Spring Native with Kotlin. In these presentations, Hadi Hariri and Sébastien Deleuze took us on a pair of deep dives into the multiplatform abilities of the frameworks.

What’s New in Ktor 2.0

This talk covered some of the exciting new things that are coming in Ktor 2.0. Ktor 2.0 is currently in Beta, but it already includes features that should help simplify development and lay the groundwork for many new things to come. 

So, what’s new in Ktor 2.0? It may come as no surprise that Ktor 2.0 brings proper package names and discoverable modules. To make upgrading to the new version easier, the team has released the Ktor 1.6 to Ktor 2.0.0 migration guide. Additionally, we will automate the migration process to make sure updating is a smooth experience.

Structural Search and Replace provides a powerful way to search for specific code patterns and replace them with others.

The server side of Ktor

Ktor was designed as a multiplatform framework supported on a server (JVM) and client (JVM, Native, JS), and Ktor 2.0 extends its abilities by bringing Native support to the server.

Features are now plugins. Anything in Ktor that used to be called a feature is now called a plugin. You can create the functionality you want using various plugins, including third-party ones.

We’ve simplified the API, and it no longer contains any unnecessary details – just onCall, onCallReceive, and onCallRespond. Please share any feedback you have about this so that we can continue to enhance the API.

Ktor for client

The API is now simpler and more discoverable. Generics are gone, and the body now includes types, which makes it easier to use.

Retries were highly requested, so they now come bundled. With Ktor 2.0, you can say whether a retry is of a specific type or on a specific exception, and you can implement certain delays without having to use any exponential decay functions.

Additionally, Ktor for the client now comes with content negotiation – you can do content negotiation like you would with a server especially in microservices.

Documentation 

We didn’t forget the Documentation. It has been rewritten, and all the previous gaps have been filled. Every single sample is up to date and available for download! 

Generators and IDE support

There’s a new generator at start.ktor.io that consists of just two simple steps: choosing a name and additional settings, and choosing plugins (that used to be called features), including third-party ones. 

And that’s just the beginning.

Spring Native with Kotlin

Sébastien Deleuze shared a comprehensive overview of the new Ahead-of-Time transformations that allow Spring Boot Native applications to have smaller footprints and improved Native compatibility, and he announced some other new features as well.

What is Spring Native? 

Spring Native offers Beta support for compiling Spring Boot applications to Native executables with GraalVM, providing a new way to deploy Spring Boot applications that allows them to run exceptionally efficiently.

Kotlin/JVM/Native 

The discussion of the Kotlin/JVM target and compiling the bytecode with GraalVM naturally leads us to Kotlin/JVM/Native. It provides the perfect fit because it allows you to go Native while staying in the JVM ecosystem, and the Spring and Kotlin compiler plugin infrastructures are excellent with Native.

Future Kotlin adoption

The next wave of Kotlin market share increases might not come from better language aspects, but instead from the investments into the K2 compiler and the upcoming new compiler frontend, third-party compiler plugins, Compose for Web, and Kotlin/Wasm.

Ahead-of-Time (AOT) transformations 

The Spring AOT Maven and Gradle plugins perform powerful build-time transformations on Spring Boot applications to improve efficiency on Native, and potentially on the JVM as well. Spring’s AOT strategy includes bringing Spring Fu efficiency to Spring Boot applications. On this topic, it’s worth noting that AOT mode is mandatory for Native but optional for the JVM.

Hard performance data

Build time is almost instant on the JVM. Native still takes some time, but it will be reduced with the upcoming Native 0.11.

Native already makes container image sizes much smaller than they are in the JVM, and with the upcoming UPX compression, they will be about half as large as they are now.

AOT brings a 10% memory footprint improvement for the JVM. The footprint for Native is already significantly lower, but with 0.11, the memory footprint will be reduced by even more – by up to 20% compared to 0.10.

Startup on Native is almost instant (taking 80 milliseconds tops), and this will be cut in half with Native 0.11

Roadmap

Spring Native 0.11.0 with

  • AOT application context
  • GraalVM 21.3 with reflection optimizations
  • Java 11 and Java 17 support
  • Spring Boot 2.6.0
  • UPX compression for container images

The future of Spring Native is first-class Native support in Spring Boot 3.x. This will allow for better compatibility and footprinting via more significant changes in Spring. 

Spring is now building a framework for the next decade.

Continue ReadingKotlin for Server-Side Frameworks News: Kotlin Premier Event Presentation Highlights

Kotlin for Server-Side Frameworks News: Kotlin Premier Event Presentation Highlights

The Kotlin Online Event is over. But we thought we’d give a quick recap of the two server-side talks: What’s New in Ktor 2.0 and Spring Native with Kotlin. In these presentations, Hadi Hariri and Sébastien Deleuze took us on a pair of deep dives into the multiplatform abilities of the frameworks.

What’s New in Ktor 2.0

This talk covered some of the exciting new things that are coming in Ktor 2.0. Ktor 2.0 is currently in Beta, but it already includes features that should help simplify development and lay the groundwork for many new things to come. 

So, what’s new in Ktor 2.0? It may come as no surprise that Ktor 2.0 brings proper package names and discoverable modules. To make upgrading to the new version easier, the team has released the Ktor 1.6 to Ktor 2.0.0 migration guide. Additionally, we will automate the migration process to make sure updating is a smooth experience.

Structural Search and Replace provides a powerful way to search for specific code patterns and replace them with others.

The server side of Ktor

Ktor was designed as a multiplatform framework supported on a server (JVM) and client (JVM, Native, JS), and Ktor 2.0 extends its abilities by bringing Native support to the server.

Features are now plugins. Anything in Ktor that used to be called a feature is now called a plugin. You can create the functionality you want using various plugins, including third-party ones.

We’ve simplified the API, and it no longer contains any unnecessary details – just onCall, onCallReceive, and onCallRespond. Please share any feedback you have about this so that we can continue to enhance the API.

Ktor for client

The API is now simpler and more discoverable. Generics are gone, and the body now includes types, which makes it easier to use.

Retries were highly requested, so they now come bundled. With Ktor 2.0, you can say whether a retry is of a specific type or on a specific exception, and you can implement certain delays without having to use any exponential decay functions.

Additionally, Ktor for the client now comes with content negotiation – you can do content negotiation like you would with a server especially in microservices.

Documentation 

We didn’t forget the Documentation. It has been rewritten, and all the previous gaps have been filled. Every single sample is up to date and available for download! 

Generators and IDE support

There’s a new generator at start.ktor.io that consists of just two simple steps: choosing a name and additional settings, and choosing plugins (that used to be called features), including third-party ones. 

And that’s just the beginning.

Spring Native with Kotlin

Sébastien Deleuze shared a comprehensive overview of the new Ahead-of-Time transformations that allow Spring Boot Native applications to have smaller footprints and improved Native compatibility, and he announced some other new features as well.

What is Spring Native? 

Spring Native offers Beta support for compiling Spring Boot applications to Native executables with GraalVM, providing a new way to deploy Spring Boot applications that allows them to run exceptionally efficiently.

Kotlin/JVM/Native 

The discussion of the Kotlin/JVM target and compiling the bytecode with GraalVM naturally leads us to Kotlin/JVM/Native. It provides the perfect fit because it allows you to go Native while staying in the JVM ecosystem, and the Spring and Kotlin compiler plugin infrastructures are excellent with Native.

Future Kotlin adoption

The next wave of Kotlin market share increases might not come from better language aspects, but instead from the investments into the K2 compiler and the upcoming new compiler frontend, third-party compiler plugins, Compose for Web, and Kotlin/Wasm.

Ahead-of-Time (AOT) transformations 

The Spring AOT Maven and Gradle plugins perform powerful build-time transformations on Spring Boot applications to improve efficiency on Native, and potentially on the JVM as well. Spring’s AOT strategy includes bringing Spring Fu efficiency to Spring Boot applications. On this topic, it’s worth noting that AOT mode is mandatory for Native but optional for the JVM.

Hard performance data

Build time is almost instant on the JVM. Native still takes some time, but it will be reduced with the upcoming Native 0.11.

Native already makes container image sizes much smaller than they are in the JVM, and with the upcoming UPX compression, they will be about half as large as they are now.

AOT brings a 10% memory footprint improvement for the JVM. The footprint for Native is already significantly lower, but with 0.11, the memory footprint will be reduced by even more – by up to 20% compared to 0.10.

Startup on Native is almost instant (taking 80 milliseconds tops), and this will be cut in half with Native 0.11

Roadmap

Spring Native 0.11.0 with

  • AOT application context
  • GraalVM 21.3 with reflection optimizations
  • Java 11 and Java 17 support
  • Spring Boot 2.6.0
  • UPX compression for container images

The future of Spring Native is first-class Native support in Spring Boot 3.x. This will allow for better compatibility and footprinting via more significant changes in Spring. 

Spring is now building a framework for the next decade.

Continue ReadingKotlin for Server-Side Frameworks News: Kotlin Premier Event Presentation Highlights

Useful Kotlin Idioms You Should Know

Kotlin was designed to be very similar to Java to make migration as smooth as possible. However, Kotlin was also designed to improve the developers’ experience by providing a more expressive syntax and a more sophisticated type system. To take full advantage of the language and write more concise code, learning Kotlin idioms is a must. Without them, it is easy to fall back into old Java patterns.

So, where do you begin? In this blog post, we would like to highlight some good places to start on the path to learning idiomatic Kotlin.

Data classes

Let’s start with data classes, which are probably one of the most popular features of Kotlin. 
If you need a class to hold some values, data classes are exactly what you need. The main purpose of data classes is to hold data, and some utility functions are automatically generated for them.

data class Figure(
   val width: Int,
   val height: Int,
   val length: Int,
   val color: Color,
)

In addition to equals(), hashCode(), and toString() functions, data classes include a very convenient copy() function and a way to destructure the object into number of variables:

val figure = Figure(1, 2, 3, Color.YELLOW)
val (w, h, l, _) = figure.copy(color = Color.RED)

See how we only redefine the color in the copy function for the figure? This is a nice introduction to the next two Kotlin features – named and default arguments.

Named and default arguments

With default arguments, we can remove the need for overloading constructors or functions. 
For example, let’s say we’d like to create instances of the Figure class from the above example with the default color set to GREEN. Instead of adding a secondary constructor, we can just set a default value for the default color:

data class Figure(
   val width: Int,
   val height: Int,
   val length: Int,
   val color: Color = Color.GREEN,
)

val figure = Figure(1, 2, 3)

When we read this code, it is difficult to immediately figure out what the Figure’s constructor arguments are. What do 1, 2, and 3 mean? The IDE can help us out by rendering the parameter names as hints:

To improve the readability of such code, you can also use named arguments:

val figure = Figure(width = 1, height = 2, length = 3)

In fact, we have seen the use of named arguments with the copy() function for data classes:

val greenFigure = Figure(1, 2, 3) // default color is GREEN
val redFigure = greenFigure.copy(color = Color.RED)

The copy() function arguments have all the default values. When invoking the function you can choose which parameters you want to provide:

... = greenFigure.copy(width = 10)
... = greenFigure.copy(color = Color.RED)
... = greenFigure.copy(width = 15, color = Color.YELLOW)

Expressions

An important thing to keep in mind when starting out with Kotlin after having programmed in Java is that if, when, and try are expressions in Kotlin. All of these expressions return a value. 

For instance, instead of

val weather: String = getWeatherConditions()
var drivingStyle = ""

if(weather == "Sunny") {
   drivingStyle = "Speedy"
} else {
   drivingStyle = "Safely"
}

you can write

val weather: String = getWeatherConditions()
var drivingStyle = if(weather == "Sunny") {
   "Speedy"
} else {
   "Safely"
}

When the conditions for the “if” statement are too complex, it is worth using the “when” expression. For instance, this code looks a bit noisy with “if” expressions: 

val weather: String = getWeatherConditions()
var drivingStyle =
   if (weather == "Sunny") {
       "Speedy"
   } else if (weather == "Foggy" || weather == "Rainy") {
       "Safely"
   } else if (weather == "Blizzard") {
       "Don't drive!"
   } else {
       "Undefined"
   }

But it’s much cleaner with a “when” expression:

var drivingStyle = when (getWeatherConditions()) {
   "Sunny" -> "Speedy"
   "Foggy", "Rainy" -> "Safely"
   "Blizzard" -> "Don't drive!"
   else -> "Undefined"
}

In combination with sealed classes (or enum classes), the “when” expression becomes a powerful tool to make your programs safer.

sealed class Weather
object Rainy : Weather()
object Sunny : Weather()
object Foggy : Weather()
object Blizzard : Weather()

var drivingStyle = when (getWeatherConditions()) {
   Sunny -> "Speedy"
   Foggy, Rainy  -> "Safely"
}

This code does not compile! We have to either add an “else” branch in the “when” statement or cover all the remaining options for the condition.

The issue is that using the else branch would diminish the benefits of using sealed classes in “when” expressions. If the else branch is present, adding the new subclass won’t result in a compilation error and you can miss the places where the specific case is required for the new subclass. In Detekt, for instance, you can configure whether or not the else branch can be treated as a valid case for enums and sealed classes.

apply()

In Kotlin, apply() is one of the five scope functions provided by the standard library. It is an extension function and it sets its scope to the object on which apply() is invoked. This allows executing any statements within the scope of the receiver object. In the end, the function returns the same object, with some modified changes.

The function is quite useful for object initialization. For instance, here’s a nice example from Phillip Hauer’s blog:

val dataSource = BasicDataSource().apply {
   driverClassName = "com.mysql.jdbc.Driver"
   url = "jdbc:mysql://domain:3309/db"
   username = "username"
   password = "password"
   maxTotal = 40
   maxIdle = 40
   minIdle = 4
}

Instead of creating an object variable and referring to it for initializing every single property, we can assign the values within the block to the apply() function. 

The apply() function also comes in useful when working with Java libraries that use recursive generics. For instance, Testcontainers use recursive generics to implement self-typing to provide a fluent API. Here’s an example in Java:

[java]
PostgreSQLContainer> container = new PostgreSQLContainer(“postgres:13”)
.withInitScript(“schema.sql”)
.withDatabaseName(“database”)
.withUsername(“user”)
.withPassword(“password”);
[/java]

To implement the same in Kotlin, we can use the apply() function as follows:

val container = postgres("postgres:13") {
   withDatabaseName("db")
   withUsername("user")
   withPassword("password")
   withInitScript("sql/schema.sql")
}

You can learn about using Testcontainers with Kotlin in this Spring Time in Kotlin episode about integration testing.

Null-safety

When talking about Kotlin’s features and idiomatic code, you can’t get around null-safety. An object reference might be null, and the compiler will let us know if we are trying to dereference the null value. That’s really convenient!

val figure: Figure? = createFigure() // can return null
val otherFigure = figure.copy(color = Color.YELLOW)

The figure.copy() is a potential source of NullPointerException, as the createFigure() function might have returned null. We could validate if the reference is null and then safely invoke the copy() function. 

val figure: Figure? = createFigure()
if(figure != null) {
   val otherFigure = figure.copy(color = Color.YELLOW)
}

// or

val figure: Figure? = createFigure() // can return null

if(figure == null) {
   throw IllegalStateException("figure is null")
}

val otherFigure = figure.copy(color = Color.YELLOW)
[kotlin]



<p>You can imagine that in more complex use cases, this code will become quite verbose and cluttered with null-checks. To remedy this, there are useful operators to deal with nullability in Kotlin.</p>



<p>First, you can use the <a href="https://kotlinlang.org/docs/null-safety.html#safe-calls">safe-call operator</a>:</p>



[kotlin runnable=false]
val figure: Figure? = createFigure()
val otherFigure = figure?.copy(color = Color.YELLOW)

Or, if you would like to signal the incorrect situation, it is possible to use the Elvis operator (?:) as follows:

val figure: Figure = createFigure() ?: throw IllegalStateException("figure is null")
val otherFigure = figure.copy(color = Color.YELLOW)

If the result of the createFigure() function is null, then the Elvis operator will lead to throwing the IllegalArgumentException. This means that there’s no situation when the figure object could be null, so you can get rid of the nullable type and the compiler won’t complain about calling any function on this object. The compiler is now absolutely sure that there won’t be a NullPointerException.

When working with object graphs where any object could be null, you inevitably have to null-check the values.

For example, Bob is an employee who may be assigned to a department (or not). That department may in turn have another employee as a department head. To obtain the name of Bob’s department head (if there is one), you write the following:

val bob = findPerson()

if( bob == null || 
    bob.department == null || 
    bob.department.name == null){
   throw IllegalStateException("invalid data")
}

val name = bob.department.head.name

This is so verbose! You can make this code much nicer by using the safe-call and Elvis operators:

val bob = findPerson()
val name = bob?.department?.head?.name ?: throw IllegalStateException("invalid data")

By using the nullable types in Kotlin, you help the compiler to validate your programs, and so make the code safer. The additional operators, like safe-call and Elvis, let you work with the nullable types in a concise manner. You can find more information about null-safety in Kotlin on the documentation page.

Extension functions

In Java, static functions in Util-classes is a common idiom. ClientUtil, StringUtil, and so on – you have definitely encountered these in your Java projects. 

Consider the following example:

class Person(val name: String, val age: Int)

val person = Person("Anton", 16)
println(person) // org.kotlin.Person@6bf256fa

Because there’s no toString() function in the Person class, this code prints just an object reference value. You could either implement your own toString() function, or define Person as a data class to let the compiler generate this function for you. But what if you can’t modify the source of the Person class (e.g. the class is provided by an external library you have added to your project)?

If you use Java habits, you would probably create a PersonUtil class with a static function that takes the Person class as an argument and returns a String. In Kotlin, there’s no need to create *Util classes, as there are top-level functions available, so it would look something like this:

fun prettyPrint(person: Person): String {
   return "Person{name=" + person.name + ", age=" + person.age + "}"
}

You can use string templates instead of string concatenation:

fun prettyPrint(person: Person): String {
   return "Person{name=${person.name}, age=${person.age}}"
}

Since there’s just one statement in the function, you can apply the expression-body syntax as follows:

fun prettyPrint(person: Person): String =
   "Person{name=${person.name}, age=${person.age}}"

It’s getting better, but still looks quite like Java. You can improve this code by implementing prettyPrint() as an extension function to the Person class. You don’t need to modify the Person class source code for that, as the extension can be declared in a different location than the original class.

fun Person.prettyPrint(): String = "Person{name=$name, age=$age}"

Now you can invoke the new function on the Person class instance:

val person = Person("Anton", 16)
println(person.prettyPrint()) // Person{name=Anton, age=16}

By using the extension functions it is possible to extend existing APIs. For instance, when using Java libraries you can extend the existing classes with new functions for convenience. In fact, a number of functions in the Kotlin standard library are implemented via extensions. For instance, scope functions are a prominent example of extension functions in the standard library.

Summary

This is not an exhaustive list of Kotlin idioms, but rather the basics to help you to get started with learning the idiomatic Kotlin style. Meanwhile, our team is working on collecting more idioms in the official documentation. Recently we published a page with the collection of Kotlin idioms for working with Strings. We invite you to share the Kotlin idioms you find useful either in the comments below or on Twitter by mentioning the @kotlin account.

What to read next:

Idioms in Kotlin documentation

Java to Kotlin migration guide (Strings)

Idiomatic Kotlin from formatting to DSL’s — slides by Anton Arhipov

“Idiomatic Kotlin. Best Practices” in Philipp Hauer’s Blog

Server-Side Development with Kotlin: Frameworks and Libraries

Productive Server-Side Development With Kotlin: Stories From The Industry

Continue ReadingUseful Kotlin Idioms You Should Know

Server-side With Kotlin Webinar Series, Vol. 3

Announcing a new series of webinars about Kotlin for server-side! These will take place between May 27 and June 15. Join the live sessions or watch the recordings later!

In this five-webinar series, our speakers will host step-by-step live coding sessions to show you what kinds of benefits you can get from Kotlin for server-side and its rich ecosystem. Each webinar will include a Q&A session to discuss everything you are interested in with the host and speakers from CUBA.platform (now Jmix), http4k, RSocket, Hazelcast, and Quarkus.

Subscribe to our YouTube channel to stay up to date with all the planned webinars and upcoming videos!

Follow Kotlin on YouTube

May 27, Aleksey Stukalov. Getting the Most From JPA With Kotlin

Aleksey Stukalov is a Solutions Director at Haulmont and a technology geek passionate about developer tooling. Since 2015 Aleksey has led the development of the CUBA.platform (now Jmix) framework used in numerous enterprise projects today.

In this webinar, you will learn how to use JPA in your Kotlin applications. You will also learn many tips and tricks for defining JPA entities and how you can use Kotlin to simplify your work.

May 27, 2021, at 17:00 CEST
Register here: https://info.jetbrains.com/kotlin-webinar-may-2021.html

June 1, Nicolas Fränkel. Spring: From MVC to Reactive

Nicolas Fränkel is a Developer Advocate with 15+ years of experience in consulting. He combines working for Hazelcast with training and book-writing.

You will learn how to migrate a traditional Spring Boot application to its Reactive equivalent, and how to use that to cut your monthly bills. In this demo-based talk, Nicolas will show how to migrate a traditional Spring Boot application that uses WebMVC, Spring Data JPA, and Spring Cache to its Reactive equivalent in a step-by-step process.

June 1, 2021, at 17:00 CEST
Register here: https://info.jetbrains.com/kotlin-webinar-june-2021.html

June 8, Oleh Dokuka. What’s New in Spring Boot With Kotlin

Oleh Dokuka is a Software Engineer who has experience with reactive technologies both as a user and a developer. A Java Champion and co-author of the book “Hands‑On Reactive Programming in Spring 5”, Oleh works on RSocket and improves Project Reactor.

In this session, you will learn how to get started with Kotlin Multiplatform and Spring Boot, and build a client-server application using Spring Boot and Kotlin on the server side and Kotlin/JS to power the client UI in the browser.

June 8, 2021, at 18:00 CEST
Register here: https://info.jetbrains.com/kotlin-webinar-june08-2021.html

June 10, Justin Lee. Quarkus for Kotlin Developers

Justin Lee is a Java Champion and a Kotlin fanatic. He has been programming in Java since 1996 and has worked on virtually every level of the application stack, from database drivers to application servers and front-end interfaces. Justin is currently a Principal Software Engineer working on QuarkusIO at Red Hat.

Justin will show you how Kotlin can be used with Quarkus for building applications in the cloud! Quarkus has radically changed how Java developers approach building applications. But even though Quarkus is an amazing framework for Java microservices, that doesn’t mean that Kotlin has to look in from the outside.

June 10, 2021, at 17:00 CEST
Register here: https://info.jetbrains.com/kotlin-webinar-june10-2021.html

June 15, David Denton and Ivan Sanchez. http4k: Server as a Function

Both of your speakers are GoogleDevExperts and co-creators of http4k: David Denton, Engineering Lead, and Ivan Sanchez, independent software consultant.

This session is a practical introduction to http4k, a functional toolkit for writing Kotlin HTTP applications for Server, Serverless, or Native runtimes. Using the Server as a Function approach, you’ll learn how to take advantage of the uniform client and server interfaces to easily create production-ready HTTP applications with zero magic. You’ll also see how this approach unlocks powerful testing techniques that result in super-fast tests that are both well-factored and simple to write.

June 15, 2021, at 18:00 CEST
Register here: https://info.jetbrains.com/kotlin-webinar-june-15-2021.html

Save the date

Once you’ve registered, we’ll send you a confirmation email with calendar invitations, and we’ll also send you a reminder one day before each of the webinars begins.

All webinars are free to attend and will be recorded and published on YouTube after streaming. Subscribe to the Kotlin by JetBrains YouTube channel to be notified about each uploaded recording.

Learn more about server-side Kotlin

We’ve created a page with lots of useful reference materials about using Kotlin on the backend. Follow the link below for tips, tricks, and best practices, all carefully curated by the Kotlin team.

Go to Kotlin server-side page

Continue ReadingServer-side With Kotlin Webinar Series, Vol. 3

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

DoorDash: Building Scalable Backend Services with Kotlin

DoorDash uses Kotlin for all their backend services and infrastructure. Hundreds of engineers work with Kotlin across a massive system spanning multiple repos.

Two years ago, they made the bold move to split their existing legacy Python monolith into multiple backend services, which they developed in Kotlin. This upgrade resulted in tremendous improvements:

  • Better software performance.
  • Сleaner code.
  • Easier code reviews.

Another great thing about Kotlin is that people coming from Java, Golang, and Python find it really easy to get started.


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


About DoorDash

San Francisco-based on demand logistics platform DoorDash deals with customers who order food, merchants who prepare food for customers, and “Dashers” who deliver the food to the customer’s door.

By the end of November 2020, DoorDash had achieved $1.9 billion in revenue and it’s one of the most anticipated IPOs in 2020.

“We are serving millions of users every day, delivering their orders with a very intricate, well-knitted solution. Our Kotlin services are handling requests from several complex logistic systems in order to weave together a seamless on-demand food delivery experience for the customers.”

Why Kotlin?

DoorDash had a Python monolith system backend that worked satisfactorily but wasn’t going to keep up with the projected scaling. So DoorDash started to look into the options available for making a more scalable solution.

A special internal committee evaluated the choices available, such as Python 3 (with async IO), Java, Golang, and Kotlin in combination with gRPC to see which would best fit the company’s needs. The performance achieved with Python wasn’t sufficient. Golang performed great but at that time it wasn’t suited to complex business logic. The JVM appeared to be the most attractive landscape in terms of libraries, tooling, and frameworks, but almost all the developers were concerned about Java’s ceremonial constructs and bloated code.

Kotlin looked promising with its clean syntax and support for coroutines. It was easy to read, understand, and maintain. Kotlin also allowed developers with existing JVM experience to draw on their existing knowledge while building on top of solid frameworks that were well-documented and battle-tested.

Building up in the JVM ecosystem

The DoorDash software backend now consists of two types of services: “backend for frontend” (BFF) services that act as stateless proxies, and internal services that run on Kotlin and gRPC and are accessible only through BFF. The BFF uses Kotlin either with SpringBoot or Micronaut. In such a system, gRPC servers are capable of writing end-to-end suspendable code without descending into callback hell. This significantly improves performance.

Kotlin also allowed the team to use the rich Java library ecosystem and build solid services with complete instrumentation and maximum visibility.

The common backend stack means that developers can write shared libraries for services and the BFF. In DoorDash, Kroto+ is used to generate the coroutine-friendly client and server code. Building on top of Netty, they were able to add libraries like Lettuce (for Redis), R2DBC (for Postgres), and Micrometer (for instrumentation). These libraries provide the foundation for out-of-the-box coroutine reactor extensions. There was some work done to glue them together, including adding interceptors, extension methods, and dependency injection, but the ecosystem quickly reached a stable state.

“Writing interoperable code between libraries can get tricky. Thanks to Kotlin’s extensions system, we ended up writing additional extensions to weave these constructs together and still write some delightful code.”

Favourite feature

“Nullability and safety is our favorite feature due to the guarantees it can put on the code. Yes, interoperability with Java might still have some nuances, but as long as you have written your code inside Kotlin it’s a lifesaver (almost all of our business logic is in Kotlin).”

Other favourite features at DoorDash:

  • Extension Functions is a lifesaver and an answer to utility classes. If used right they make code look simpler and more pleasant to read.
  • Data classes are something that POJOs or DTOs (Data Transfer Objects) were always missing. Already having the capability to do copy and equals simplifies daily chores that would have been some IDE-generated junk or a Lombok hack.
  • Function blocks that look like bodies. This is probably the most heavily used feature in the DoorDash codebase. From caching to instrumentation, it is easy to write nice, well-indented blocks that look like function bodies instead of callback lambdas.
  • Coroutines are last but not least. At DoorDash there is a deep love of coroutines. Coroutines let you write regular straightforward code and manage the code generation for continuations under the hood. This keeps stack traces simpler for coroutine code, reducing cognitive load.

Summary

With Kotlin, DoorDash was able to achieve its scaling goals and improve overall system performance. Perfect Java compatibility and coroutines were the main reasons behind this transformational success. Kotlin was a good middle ground for people coming from Java, Golang, and Python. It was easy for them to quickly catch up and start writing good, maintainable code in Kotlin.

Continue ReadingDoorDash: Building Scalable Backend Services with Kotlin

End of content

No more pages to load