Kotlin 1.4.20 Released

Kotlin 1.4.20 is here with new experimental features for you to try. Being open to community feedback is one of the Kotlin team’s basic principles, and we need your thoughts about the prototypes of the new features. Give them a try and share your feedback on Slack (get an invite here) or YouTrack.

Kotlin 1.4.20

Here are some of the key highlights:

  • Support for new JVM features, like string concatenation via invokedynamic.
  • Improved performance and exception handling for KMM projects.
  • Extensions for JDK Path:
    Path("dir") / "file.txt"

    .

We are also shipping numerous fixes and improvements for existing features, including those added in 1.4.0. So if you encountered problems with any of those features, now’s a good time to give them another try.

Read on to learn more about the features of Kotlin 1.4.20. You can also find a brief overview of the release on the What’s new in Kotlin 1.4.20 page in Kotlin docs. The complete list of changes is available in the change log.

As always, we’d like to thank our external contributors who helped us with this release.

Now let’s dive into the details!

Kotlin/JVM

On the JVM, we’ve added the new JVM 15 target and mostly focused on improving existing functionality and performance, as well as fixing bugs.

invokedynamic string concatenation

Since Java 9, the string concatenation on the JVM has been done via the dynamic method invocation (the

invokedynamic

instruction in the bytecode). This works faster and consumes less memory than the previous implementation, and it leaves space for future optimizations without requiring bytecode changes.

We have started to implement this mechanism in Kotlin for better performance, and it can now compile string concatenations into dynamic invocations on JVM 9+ targets.

Currently, this feature is experimental and covers the following cases:

  • String.plus

    in the operator (

    a + b

    ), explicit (

    a.plus(b)

    ), and reference (

    (a::plus)(b)

    ) forms.

  • toString

    on inline and data classes.

  • String templates, except for those with a single non-constant argument (see KT-42457).

To enable

invokedynamic

string concatenation, add the

-Xstring-concat

compiler option with one of the following values:

Kotlin/JS

Kotlin/JS continues to evolve at a rapid pace, and this release brings a variety of improvements, including new templates for its project wizard, improved DSL for better control over project configuration, and more. The new IR compiler has also received a brand-new way to compile projects ignoring errors in their code.

Gradle DSL changes

The Kotlin/JS Gradle DSL has received a number of updates that simplify project setup and customization, including webpack configuration adjustments, modifications to the auto-generated

package.json

file, and improved control over transitive dependencies.

Single point for webpack configuration

Kotlin 1.4.20 introduces a new configuration block for the

browser

target called

commonWebpackConfig

. Inside it, you can adjust common settings from a single point, instead of duplicating configurations for

webpackTask

,

runTask

, and

testTask

.

To enable CSS support by default for all three tasks, you just need to include the following snippet in the

build.gradle(.kts)

of your project:

kotlin {
	browser {
		commonWebpackConfig {
			cssSupport.enabled = true
		}
		binaries.executable()
	}
}

package.json customization from Gradle

The

package.json

file generally defines how a JavaScript project should behave, identifying scripts that are available to run, dependencies, and more. It is automatically generated for Kotlin/JS projects during build time. Because the contents of

package.json

vary from case to case, we’ve received numerous requests for an easy way to customize this file.

Starting with Kotlin 1.4.20, you can add entries to the

package.json

project file from the Gradle build script. To add custom fields to your

package.json

, use the

customField

function in the compilations

packageJson

block:

kotlin {
    js(BOTH) {
        compilations["main"].packageJson {
            customField("hello", mapOf("one" to 1, "two" to 2))
        }
    }
}

When you build the project, this will add the following block to the configuration file

build/js/packages/projectName/package.json

:

"hello": {
  "one": 1,
  "two": 2
}

Whether you want to add a scripts field to the configuration, making it easy to run your project from the command line, or want to include information for other post-processing tools, we hope that you will find this new way of specifying custom fields useful.

Selective yarn dependency resolutions (experimental)

When including dependencies from npm, there are times when you want to have fine-grained control over their dependencies (transitive dependencies). There are numerous reasons this could be the case. You might want to apply an important upgrade to one of the dependencies of a library you are using. Or you may want to roll back an update of a transitive dependency which currently breaks your application. Yarn’s selective dependency resolutions allow you to override the dependencies specified by the original author, so you can keep on developing.

With Kotlin 1.4.20, we are providing a preliminary (experimental) way to configure this feature from a project’s Gradle build script. While we are still working on a smooth API integration with the rest of the Kotlin/JS options, you can already use the feature through the

YarnRootExtension

inside the

YarnPlugin

. To affect the resolved version of a package for your project, use the

resolution

function. In its arguments, specify the package name selector (as specified by Yarn) and the desired version.

An example configuration for selective dependency resolution in your

build.gradle.kts

file would look like this:

rootProject.plugins.withType<YarnPlugin> {
    rootProject.the<YarnRootExtension>().apply {
        resolution("react", "16.0.0")
        resolution("processor/decamelize", "3.0.0")
    }
}

Here, all of your npm dependencies that require

react

will receive version

16.0.0

, and

processor

will receive its

decamelize

dependency as version

3.0.0

. Additionally, you can also pass

include

and

exclude

invocations to the

resolution

block, which allows you to specify constraints about acceptable versions.

Disabling granular workspaces (experimental)

To speed up build times, the Kotlin/JS Gradle plugin only installs the dependencies that are required for a particular Gradle task. For example, the

webpack-dev-server

package is only installed when you execute one of the

*Run

tasks, and not when you execute the

assemble

task. While this means unnecessary downloads are avoided, it can create problems when running multiple Gradle processes in parallel. When the dependency requirements clash, the two installations of npm packages can cause errors.

To resolve this issue, Kotlin 1.4.20 includes a new (experimental) option to disable these so-called granular workspaces. Like the experimental support for selective dependency resolutions, this feature is currently also accessible through the

YarnRootExtension

, but it will likely be integrated more closely with the rest of the Kotlin/JS Gradle DSL. To use it, add the following snippet to your

build.gradle.kts

file:

rootProject.plugins.withType<YarnPlugin> {
    rootProject.the<YarnRootExtension>().disableGranularWorkspaces()
}

With this configuration, the Kotlin/JS Gradle plugin will install all npm dependencies that may be used by your project, including those used by tasks that are not currently being executed. This means that the first Gradle build might take a bit longer, but the downloaded dependencies will be up to date for all tasks you run. This way, you can avoid conflicts when running multiple Gradle processes in parallel.

New Wizard templates

To give you more convenient ways to customize your project during creation, the project wizard for Kotlin comes with new adjustable templates for Kotlin/JS applications. There are templates for both the browser and Node.js runtime environments. They serve as a good starting point for your project and make it possible to fine tune the initial configuration. This includes settings like enabling the new IR compiler or setting up additional library support.

With Kotlin 1.4.20, there are three templates available:

  • Browser Application allows you to set up a barebones Kotlin/JS Gradle project that runs in the browser.
  • React Application contains everything you need to start building a React app using the appropriate kotlin-wrappers. It provides options to enable integrations for style-sheets, navigational components, and state containers.
  • Node.js Application preconfigures your project to run in a Node.js runtime. It comes with the option to directly include the experimental kotlinx-nodejs package, which we introduced in a previous post.

Ignoring compilation errors (experimental)

With Kotlin 1.4.20, we are also excited to showcase a brand-new feature available in the Kotlin/JS IR compilerignoring compilation errors. This feature allows you to try out your application even while it is in a state where it usually wouldn’t compile. For example, when you’re doing a complex refactoring or working on a part of the system that is completely unrelated to a compilation error. With this new compiler mode, the compiler ignores any erroneous code and replaces it with runtime exceptions instead of refusing to compile.

Kotlin 1.4.20 comes with two tolerance policies for ignoring compilation errors in your code:

  • In
    SEMANTIC

    mode, the compiler will accept code that is syntactically correct but doesn’t make sense semantically. An example for this would be a statement containing a type mismatch (like

    val x: String = 3

    ).

  • In
    SYNTAX

    mode, the compiler will accept any and all code, even if it contains syntax errors. Regardless of what you write, the compiler will still try to generate a runnable executable.

As an experimental feature, ignoring compilation errors requires an opt-in through a compiler option. It’s only available for the Kotlin/JS IR compiler. To enable it, add the following snippet to your

build.gradle.kts

file:

kotlin {
   js(IR) {
       compilations.all {
           compileKotlinTask.kotlinOptions.freeCompilerArgs += listOf("-Xerror-tolerance-policy=SYNTAX")
       }
   }
}

We hope that compilation with errors will help you tighten feedback loops and increase your iteration speed when working on Kotlin/JS projects. We look forward to receiving your feedback, and any issues you find while trying this feature, in our YouTrack.

As we continue to refine the implementation of this feature, we will also offer a deeper integration for it with the Kotlin/JS Gradle DSL and its tasks at a later point.

Kotlin/Native

Performance remains one of Kotlin/Native’s main priorities in 1.4.20. A key feature in this area is a prototype of the new escape analysis mechanism that we plan to polish and improve in coming releases. And of course, there are also smaller performance improvements, such as faster range checks (

in

).

Another aspect of the improvements to Kotlin/Native development in 1.4.20 is polishing and bug fixing. We’ve addressed a number of old issues, as well as those found in new 1.4 features, for example the code sharing mechanism. One set of improvements fixes behavior inconsistencies between Kotlin/Native and Kotlin/JVM in corner cases, such as property initialization or the way

equals

and

hashCode

work on functional references.

Finally, we have extended Objective-C interop capabilities with an option to wrap Objective-C exceptions into Kotlin exceptions, making it possible to handle them in the Kotlin code.

Escape analysis

Escape analysis is a technique that the compiler uses to decide whether an object can be allocated on the stack or should “escape” to the heap. Allocation on the stack is much faster and doesn’t require garbage collection in the future.

Although Kotlin/Native already had a local escape analysis, we are now introducing a prototype implementation of a new, more efficient global escape analysis. This is performed in a separate compilation phase for the release builds (with the

-opt

compiler option).

This prototype has already yielded some promising results, such as a 10% average performance increase on our benchmarks. We’re researching ways to optimize the algorithm so that it finds more objects for stack allocation and speeds up the program even more.

While we continue to work on the prototype, you can greatly help us by trying it out and sharing the results you get on your real-life projects.

If you want to disable the escape analysis phase, use the

-Xdisable-phases=EscapeAnalysis

compiler option.

Opt-in wrapping of Objective-C exceptions

The purpose of exceptions in Objective-C is quite different from that in Kotlin. Their use is normally limited to finding errors during development. But technically, Objective-C libraries can throw exceptions in runtime. Previously, there was no option to handle such exceptions in Kotlin/Native, and encountering an

NSException

thrown from a library caused the termination of the whole Kotlin/Native program.

In 1.4.20, we’ve added an option to handle such exceptions in runtime to avoid program crashes. You can opt in to wrap

NSException

’s into Kotlin’s

ForeignException

’s for further handling in the Kotlin code. Such a

ForeignException

holds the reference to the original

NSException

, which lets you get information about the root cause.

To enable the wrapping of Objective-C exceptions, specify the

-Xforeign-exception-mode objc-wrap

option in the

cinterop

call or add the

foreignExceptionMode = objc-wrap

property to the

.def

file. If you use the CocoaPods integration, specify the option in the

pod {}

build script block of a dependency like this:

pod("foo") {
   extraOpts = listOf("-Xforeign-exception-mode”, “objc-wrap")
}

The default behavior remains unchanged: the program terminates when an exception is thrown from the Objective-C code.

CocoaPods plugin improvements

Improved task execution

In this release, we’ve significantly improved the flow of task execution. For example, if you add a new CocoaPods dependency, existing dependencies are not rebuilt. Adding an extra target also doesn’t trigger the rebuilding of dependencies for existing targets.

Extended DSL

In 1.4.20, we’ve extended the DSL for adding CocoaPods dependencies to your Kotlin project.

In addition to local Pods and Pods from the CocoaPods repository, you can add dependencies on the following types of libraries:

  • A library from a custom spec repository.
  • A remote library from a Git repository.
  • A library from an archive (also available by arbitrary HTTP address).
  • A static library.
  • A library with custom cinterop options.

The previous DSL syntax is still supported.

Let’s examine a couple of DSL changes in the following examples:

  • A dependency on a remote library from a Git repository.
    You can specify a tag, commit, or branch by using corresponding keywords, for example:

        pod("JSONModel") {
        source = git("https://github.com/jsonmodel/jsonmodel.git") {
            branch = "key-mapper-class"
        }
    }
       

    You can also combine these keywords to get the necessary version of a Pod.

  • A dependency on a library from a custom spec repository.
    Use the special

    specRepos

    parameter for it:

        specRepos {
        url("https://github.com/Kotlin/kotlin-cocoapods-spec.git")
    }
    pod("example")
    

You can find more examples in the Kotlin with CocoaPods sample.

Updated integration with Xcode

To work correctly with Xcode, Kotlin requires some Podfile changes:

  • If your Kotlin Pod has any Git, HTTP, or specRepo pod dependencies, you should also specify them in the Podfile. For example, if you add a dependency on

    AFNetworking

    from the CocoaPods repository, declare it in the Podfile, as well:

    pod 'AFNetworking'
  • When you add a library from the custom spec, you also should specify the location of specs at the beginning of your Podfile:

    source 'https://github.com/Kotlin/kotlin-cocoapods-spec.git'
    
    target 'kotlin-cocoapods-xcproj' do
      // ... other Pods ...
      pod 'example'
    end

Integration errors now have detailed descriptions in IntelliJ IDEA, so if you have any problems with your Podfile you will immediately get information about how to fix them.

Take a look at the

withXcproject

branch of the Kotlin with CocoaPods sample. It contains an example of Xcode integration with the existing Xcode project named

kotlin-cocoapods-xcproj

.

Support for Xcode 12 libraries

We have added support for new libraries delivered with Xcode 12. Feel free to use them in your Kotlin code!

Updated structure of multiplatform library publications

Before Kotlin 1.4.20, multiplatform library publications included platform-specific publications and a metadata publication. However, there was no need to depend solely on the metadata publication, so this artifact was never used explicitly.

Starting from Kotlin 1.4.20, there is no longer a separate metadata publication. Metadata artifacts are now included in the root publication, which stands for the whole library and is automatically resolved to the appropriate platform-specific artifacts when added as a dependency to the common source set.

Note that you must not add an empty artifact without a classifier to the root module of your library to meet the requirements of repositories such as Maven Central, as this will result in a conflict with metadata artifacts that are now included in this module.

Compatibility with libraries published in 1.4.20

If you have enabled hierarchical project structure support and want to use a multiplatform library that was published with such support in Kotlin 1.4.20 or higher, you will need to upgrade Kotlin in your project to version 1.4.20 or higher, as well.

If you are a library author and you publish your multiplatform library in Kotlin 1.4.20+ with hierarchical project structure support, keep in mind that users with earlier Kotlin versions who also have hierarchical project structure support enabled will not be able to use your library. They will need to upgrade Kotlin to 1.4.20 or higher.

However, if you or your library’s users do not enable hierarchical project structure support, those with earlier Kotlin versions will still be able to use your library.

Learn more about publishing a multiplatform library.

Standard library changes

Extensions for java.nio.file.Path

Starting from 1.4.20, the standard library provides experimental extensions for

java.nio.file.Path

.

Working with the modern JVM file API in an idiomatic Kotlin way is now similar to working with

java.io.File

extensions from the

kotlin.io

package. There is no longer any need to call static methods of

Files

anymore, because most of them are now available as extensions on the

Path

type.

The extensions are located in the

kotlin.io.path

package. Since

Path

itself is available in JDK 7 and higher, the extensions are placed in the

kotlin-stdlib-jdk7

module. In order to use them, you need to opt in to the experimental annotation

ExperimentalPathApi

.

// construct path with the div (/) operator
val baseDir = Path("/base")
val subDir = baseDir / "subdirectory" 

// list files in a directory
val kotlinFiles: List<Path> = Path("/home/user").listDirectoryEntries("*.kt")
```

We especially want to thank our contributor AJ Alt for submitting the initial PR with these extensions.

Improved performance of the

String.replace

function

We are always thrilled when the Kotlin community suggests improvements, and the following is one such case. In this release, we’ve changed the implementation of the

String.replace()

function.

The case-sensitive variant uses a manual replacement loop based on

indexOf

, while the case-insensitive one uses regular expression matching.

This improvement speeds up the execution of the function in certain cases.

Deprecation of Kotlin Android Extensions

Ever since we created Kotlin Android Extensions, they have played a huge role in the growth of Kotlin’s popularity in the Android ecosystem. With these extensions, we provided developers with convenient and efficient tools for reducing boilerplate code:

  • Synthetic views (
    kotlinx.android.synthetics

    ) for UI interaction.

  • Parcelable

    implementation generator (

    @Parcelize

    ) for passing objects around as

    Parcel

    ‘s.

Initially, we thought about adding more components to

kotlin-android-extensions

. But this didn’t happen, and we’ve even received user requests to split the plugin into independent parts.

On the other hand, the Android ecosystem is always evolving, and developers are getting new tools that make their work easier. Some gaps that Kotlin Android Extensions were filling have now been covered by native mechanisms from Google. For example, regarding the concise syntax for UI interaction, there is now Android Jetpack, which has view binding that replaces

findViewById

, just like Kotlin synthetics.

Given these two factors, we’ve decided to retire synthetics in favor of view binding and move the Parcelable implementation generator to a separate plugin.

In 1.4.20, we’ve extracted the Parcelable implementations generator from

kotlin-android-extensions

and started the deprecation cycle for the rest of it, which currently is only synthetics. For now, they will continue to work with a deprecation warning. In the future, you’ll need to switch your project to another solution. We will soon add the link to the guidelines for migrating Android projects from synthetics to view bindings here, so stay tuned.

The Parcelable implementation generator is now available in the new

kotlin-parcelize

plugin. Apply this plugin instead of

kotlin-android-extensions

. The

@Parcelize

annotation is moved to the

kotlinx.parcelize

package. Note that

kotlin-parcelize

and

kotlin-android-extensions

can’t be applied together in one module.

How to update

Before updating your projects to the latest version of Kotlin, you can try the new language and standard library features online at play.kotl.in. It will be updated to 1.4.20 soon.

In IntelliJ IDEA and Android Studio, you can update the Kotlin Plugin to version 1.4.20 – learn how to do this here.

If you want to work on existing projects that were created with previous versions of Kotlin, use the

1.4.20

Kotlin version in your project configuration. For more information, see the docs for Gradle and for Maven.

You can download the command-line compiler from the Github release page.

You can use the following library versions with this release:

The versions of libraries from

kotlin-wrappers

(

kotlin-react

etc.) can be found in the corresponding repository.

The release details and the list of compatible libraries are also available here.

If you run into any problems with the new release, you can find help on Slack (get an invite here) and report issues in our YouTrack.

External contributors

We’d like to thank all of our external contributors whose pull requests were included in this release:

Jinseong Jeon
Toshiaki Kameyama
Steven Schäfer
Mads Ager
Mark Punzalan
Ivan Gavrilovic
pyos
Jim Sproch
Kristoffer Andersen
Aleksandrina Streltsova
cketti
Konstantin Virolainen
AJ Alt
Henrik Tunedal
Juan Chen
KotlinIsland,
Valeriy Vyrva
Alex Chmyr
Alexey Kudravtsev
Andrey Matveev
Aurimas Liutikas
Dat Trieu
Dereck Bridie
Efeturi Money
Elijah Verdoorn
Enteerman
fee1-dead
Francesco Vasco
Gia Thuan Lam
Guillaume Darmont
Jake Wharton
Julian Kotrba
Kevin Bierhoff
Matthew Gharrity
Matts966
Raluca Sauciuc
Ryan Nett
Sebastian Kaspari
Vladimir Krivosheev
n-p-s
Pavlos-Petros Tournaris
Robert Bares
Yoshinori Isogai
Kris
Derek Bodin
Dominik Wuttke
Sam Wang
Uzi Landsmann
Yuya Urano
Norbert Nogacki
Alexandre Juca

Continue Reading Kotlin 1.4.20 Released

Doubt Regarding Context Objects In Scope Functions

Hey there,I was going through the documentation for Scope Functions and there is something that I don’t understand regarding the it context object. So in the documentation, there’s a line that says:

However, when calling the object functions or properties you don’t have the object available implicitly like this. Hence, having the context object as it is better when the object is mostly used as an argument in function calls.

Can anyone explain this part to me? I’m having some trouble understanding it.

Thanks for all the help 🙂

submitted by /u/racrisnapra666
[link] [comments]

Continue Reading Doubt Regarding Context Objects In Scope Functions

Jetpack Compose Linux performance

Hello everyone.

I wanted to try Jetpack Compose for Desktop on the only laptop I have right now which runs Ubuntu 14.

When I run an empty app, my fps goes down to ~5fps or so. I saw an issue on github where someone managed to resolve this problem by unplugging his second monitor but I still have the problem without mine.

Do you have the same problem if you use Compose on Linux ?

submitted by /u/Lazard_
[link] [comments]

Continue Reading Jetpack Compose Linux performance

The coolest thing I’ve written in Kotlin so far…

Wrote a reactive transaction manager for Spring so I can make transactions across multiple repositories inside a service and not just be tied to making a transaction only on one repository like what

ReactiveTransactionManager

restricts you to. Very useful if a lot of your business logic goes in the service layer:

The gist:

https://preview.redd.it/nhma09798j061.png?width=863&format=png&auto=webp&s=2379f93230ecf7612270d5abba65e15266736cf5

The implementation:

https://preview.redd.it/bz3hzrm48j061.png?width=1169&format=png&auto=webp&s=482af17a342542f85a39bec4737e5b651e32a7fb

The usage: (not the best use case, but at least it fits in one screenshot; it can be used across multiple repositories too)

https://preview.redd.it/yw4duqui7j061.png?width=1171&format=png&auto=webp&s=07f9960cc3248b9acaf99d6d16f4e7e7dea5e942

The usecases may be small, but damn that shitcode was fun to write

submitted by /u/wtf_kyle
[link] [comments]

Continue Reading The coolest thing I’ve written in Kotlin so far…

Server-Side Development with Kotlin: Frameworks and Libraries

It is quite common to use existing frameworks and libraries for backend application development. If we look at most of the popular frameworks in the Java ecosystem, many of them actually support Kotlin out of the box. There are a lot of Java libraries too. You can use these frameworks and libraries in your Kotlin programs thanks to Kotlin’s flawless Java interoperability.


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


This blog post is partially based on presentation content from the Kotlin 1.4 Online Event. You can watch the full video on our YouTube channel.

Spring Framework

The most popular and feature-rich framework in the ecosystem is Spring. Approximately half of all projects in the JVM ecosystem now use Spring as the framework of choice. The previous blog post about Kotlin for server-side development includes stories from Atlassian and Expedia who use Spring Boot for their projects.

Kotlin is one of the four major themes for Spring Framework 5.x. A number of extensions were added to the Spring core API specifically to provide better support for Kotlin.

In fact, Spring’s official documentation features code samples in both Java and Kotlin. This is very convenient if you’re new to Kotlin, because you can see the code sample in Java and then immediately see its Kotlin equivalent and so understand the idioms faster.

The start.spring.io project generator also supports Kotlin along with Java and Groovy.

The number of Spring tutorials is growing. We recommend that you start with the Building web applications with Spring Boot and Kotlin tutorial.

As support for Kotlin in Spring Framework is being improved, we had the privilege to host Sebastien Deleuze with his presentation about The State of Kotlin Support in Spring at the Kotlin 1.4 Online Event this year. See the video below.

An interesting new addition to Spring is the project Spring Fu. It is designed to configure Spring Boot with code in a declarative way. The Kotlin variety of the configuration DSL looks quite nice:

val app = webApplication {
	logging {
		level = LogLevel.DEBUG
	}
	beans {
		bean<SampleService>()
	}
	webMvc {
		port = if (profiles.contains("test")) 8181 else 8080
		router {
			val service = ref<SampleService>()
			GET("/") {
				ok().body(service.generateMessage())
			}
			GET("/api") {
				ok().body(Sample(service.generateMessage()))
			}
		}
		converters {
			string()
			jackson {
				indentOutput = true
			}
		}
	}
}

This new approach to configuration in Spring promises faster startup times and lower memory consumption, and it is a good fit with GraalVM native image thanks to its reflection-less approach.

Ktor

Ktor is a framework created and maintained by JetBrains. It was built with Kotlin from the ground up. Ktor encourages a minimalistic approach to application design, as you only need to configure the functionality that your project requires. Using Kotlin coroutines, Ktor is truly asynchronous and highly scalable. Ktor also includes an HTTP client that is implemented as a multiplatform library and is widely used in mobile application development with Kotlin.

Our previous blog post covers JetBrains Space and Adobe Experience Platform projects that use Ktor because of its support for asynchronous programming.

At Kotlin 1.4 Online Event, Hadi Hariri gave a presentation about the current state of the Ktor project and its future plans. See the video below.

Here are a few tutorials we recommend for learning about Ktor:

More web frameworks

Of course, Spring and Ktor are not the only frameworks in the JVM ecosystem and there are plenty of other frameworks that you can use with Kotlin. Take a look at Micronaut, Quarkus, Javalin, SparkJava, Vaadin, CUBA, and Vert.x. This is just a small list of the frameworks available. All these frameworks have either code samples in Java and Kotlin side by side or have dedicated tutorials on how to use the framework with Kotlin.

There are also a number of frameworks that are implemented in Kotlin. For instance, http4k, and Hexagon.

Database access

Backend applications often rely on database access. One of the most popular libraries today for working with databases is the Exposed library. It is an ORM framework for Kotlin that offers two levels of database access: a typesafe SQL-wrapping DSL, and lightweight data access objects.

Here’s a very simple example using Exposed:

object Cities : Table() {
   val id = integer("id").autoIncrement().primaryKey() // Column<Int>
   val name = varchar("name", 50) // Column<String>
}

Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")

transaction {
   create(Cities)

   val saintPetersburgId = Cities.insert {
       it[name] = "St. Petersburg"
   } get Cities.id

   val munichId = Cities.insert {
       it[name] = "Munich"
   } get Cities.id

   Cities.insert {
       it[name] = "Prague"
   }

println("All cities:")

for (city in Cities.selectAll()) {
   println("${city[Cities.id]}: ${city[Cities.name]}")
}

As you might have guessed, Exposed is not the only library that you can use with Kotlin for database access. You can use jdbi, jooq, JPA with Spring Data, and even just pure JDBC API to access databases from Kotlin code.

Testing

Testing a vital part of application development. JUnit and TestNG are perfectly fine for implementing unit tests in Kotlin. But there are more additional libraries that are great for testing in Kotlin:

  • Spek – a Kotlin-based Specification Testing framework for the JVM.
  • Kotest – a testing library with support for Kotlin multiplatform projects.
  • MokK – a mocking library for Kotlin tests.
  • Kotlin Power Assert – an amazing compiler plugin for Kotlin that enables the diagramming of assert function calls, making diagnosis of test failures a breeze.

Other libraries

Aside from handling HTTP requests and accessing databases, applications are often required to communicate with other services using specific protocols, perform decoding/encoding of data in various formats, and many other things. Here are a few libraries that will be useful for application development with Kotlin.

JSON is the universally accepted standard format for sending data between web servers and browsers. There are awesome JSON libraries available in the Java ecosystem and they are great for use in Kotlin programs too. Jackson and gson are the most popular Java libraries for working with JSON. However, there are also libraries that are implemented with Kotlin from scratch. Klaxon is a good example. Also kotlinx.serialization was recently released and it provides JSON support.

gRPC is a high-performance, open-source, universal RPC framework. Kotlin is now supported by gRPC.

RSocket is also gaining popularity as a protocol for use in building microservices. Kotlin integration was recently added to RSocket.

To work with GraphQL there’s graphql-kotlin library maintained by Expedia Group engineers.

These are just a few examples. In fact, there is a long list of Kotlin libraries maintained by the community where you’re sure to find a library for the task at hand. However, we’d like to point out that, thanks to Java interoperability, it is also possible to use virtually any Java library with Kotlin.

Additional Tools

Code quality is an important topic for Kotlin too! Thanks to the type system, especially null-safety, Kotlin is quite a safe programming language. However, there is still a need for code style checks. That’s the part that is currently implemented via additional tools.

Ktlint is a static code analysis tool maintained by Pinterest. It is a 2-in-1 tool that provides linting and formatting (supported via EditorConfig) for Kotlin code.

Detekt is a static code analysis tool that operates with the abstract syntax tree provided by the Kotlin compiler. It is easy to set up with Gradle and there’s also an IntelliJ IDEA plugin that simplifies configuration.

Generating API documentation from source code is also an important part of software project development. In Kotlin, we can use Dokka for this task. It is a documentation engine for Kotlin. Just like Kotlin itself, Dokka fully supports mixed-language Java/Kotlin projects. It understands standard Javadoc comments in Java files and KDoc comments in Kotlin files, and can generate documentation in multiple formats including standard Javadoc, HTML, and Markdown.

Summary

Kotlin was initially designed as an alternative JVM programming language, meaning that Kotlin can be used anywhere where Java is used. Thanks to Java interoperability, it is easy to use any of the existing frameworks and libraries that are familiar to Java developers. This all greatly simplifies the adoption of Kotlin for application development on the JVM.

The current state of Kotlin support in the ecosystem is at the stage where even big projects and companies are confidently adopting it. You can read about a few notable examples of such projects in the previous blog post, Productive Server-Side Development With Kotlin: Stories From The Industry

Continue Reading Server-Side Development with Kotlin: Frameworks and Libraries

End of content

No more pages to load