What the Flow?

Shelby Cohen
Intuit Engineering
Published in
6 min readDec 24, 2019
Photo by Jeremy Bishop on Unsplash

“WTF — What the Flow?” That’s what I left KotlinConf 2019 thinking.

After hearing Roman Elizarov’s talk at KotlinConf this year, I was excited to dive deeper into Kotlin Flow. Kotlin Flow is new and shiny but is it actually better? Why should we choose Kotlin Flow over something familiar like Project Reactor?

What is Reactive Programming?

Project Reactor and RxJava are two popular reactive libraries which allow you to program with asynchronous data streams. Reactive programming can occur on many different platforms but this article will focus primarily on server-side Spring applications.

Reactive programming can be daunting, and when I first heard the words Flux and Mono when introduced to Project Reactor, I had to sift through the documentation several times before I began to really grasp the concept. It takes practice, but once you understand one framework, it is much easier to pick up another one.

Why use Kotlin Flow instead of other reactive programming libraries?

Recently, Kotlin released Kotlin Flow, which is stable in kotlinx.coroutines version 1.3.0. In the Medium article, Simple design of Kotlin Flow, Elizarov explains how the combination of language features (coroutines) and a library (Kotlin Flow) enables a powerful abstraction with a simple design.

JetBrains is the company that created the programming language Kotlin. When JetBrains is creating something new they focus on three steps:

1. Learn about an existing technology2. Understand the pitfalls and successes of the existing technology3. Create something new that solves the problems and builds off of the successes

This approach has proven to be successful and is the reason that I gravitated towards Kotlin for server-side development, instead of Java. Kotlin simply solved a lot of the everyday issues I encountered, such as null safety and lack of conciseness. JetBrains appears to be implementing those same 3 steps with Kotlin Flow but for reactive programming. Flow’s design was inspired by reactive streams and its various implementations.

Backpressure — what is it and when does it happen?

Backpressure is a common problem with many asynchronous event-based systems, and is an issue that I, as well as many of my colleagues, run into on Spring Boot applications.

For example, an API I wrote gets a list of credentials from a database, calls a downstream service to update the credentials for security reasons, and returns that updated list to the caller. This API uses Project Reactor to be able to asynchronously update the large list of credentials. When this API is called repeatedly, it creates millions of downstream calls which can cause the data consumer to become overloaded. To address this issue, I have written a custom exception that is thrown in the event of this issue which lets the user know that we cannot complete the request. This is a usable work around for now, but it is not a long term solution. Ideally, a message should be sent back to the data producer (in this case, the downstream service) saying, “Slow down!” before errors start getting thrown. With Project Reactor, I haven’t found an easy way to implement this ideal solution.

Here’s where Kotlin comes in to save the day! Kotlin deals with backpressure with suspending functions. By using the suspend modifier, the function can pause the execution of the caller without blocking a thread. The collector of the flow gets all of the incoming request data sent in from the caller. When that collector of the flow is overwhelmed with a ton of requests, it can suspend or pause the emitter and just resume it later.

First of all, it’s incredibly helpful to have a feature like this built into the programming language itself. This feature elegantly solves one of the biggest problems for reactive programmers: backpressure.

Okay, let’s jump into the code. I love live music and going to concerts, so I figured I would create a Spring WebFlux Project that calls SeatGeek, a website where you can find tickets to concerts, sports games, and other events, using the SeatGeek API. Spring WebFlux is a part of Spring 5 and provides reactive programming support for web applications. I will show you some snippets below but you can view the whole project on GitHub.

There are two endpoints defined below using Spring WebFlux. When defining a controller for a Web project on a Reactive Stack, you can simply return the resulting reactive type from the controller method. This applies to both Project Reactor and Kotlin Flow. When using Project Reactor, the controller methods can return a Flux or Mono. When using Kotlin Flow and Coroutines, the controller methods use the suspend modifier and the return type is Flow.

Return type of getAllConcertVenueNames() is Flux<List<ProjectReactorResponse>>. A Flux<T> is a standard Publisher<T> that represents an asynchronous sequence of 0 to N emitted items.

The annotation @GetMapping is used for the paths /reactorConcertVenues and /kotlinFlowConcertVenues.

Return type of getAllConcertVenueNames() is Flow<List<KotlinFlowResponse>>. A Flow is a cold asynchronous data stream that sequentially emits values.
The getConcerts() function is used to make the call to the SeatGeek API. Since we are using Spring WebFlux, the reactive WebClient is easiest to work with. The bodyToFlux() function is helpful to return a Flux type to use throughout the Project Reactor code.
The getConcertsFlow() function is used to make the call to the SeatGeek API. Instead of using bodyToFlux(), we can use bodyToFlow() which very similarly is helpful because it returns the type Flow to be used throughout the Kotlin Flow code.

The service function getAllConcertVenueNames() returns a Flux<List<ProjectReactorResponse>> and since our getConcerts() function returns a Flux, we don’t need to convert the response to another type. We can use map { } to operate on each of the items in the eventList to eventually get to the venue name, which is what we want to in the final response list.

The service function getAllConcertVenueNames() returns a Flow<List<KotlinFlowResponse>> and since our getConcertsFlow() function returns a Flow, we don’t need to convert the response to another type. We can also use map { } here to operate on each of the items in the eventList to eventually get to the venue name, which is what we want to in the final response list.

If we were to call getConcerts() instead of getConcertsFlow() and we were working with a Flux type we can simply add asFlow() at the end of the chain to convert the type to a Flow.

As you can see above, understanding different implementations of reactive streams, can help you understand Kotlin Flow more easily. And the kotlinlang.org asynchronous flow documents how you can convert to multiple reactive modules:

While being different, conceptually, Flow is a reactive stream and it is possible to convert it to the reactive (spec and TCK compliant) Publisher and vice versa. Such converters are provided by kotlinx.coroutines out-of-the-box and can be found in corresponding reactive modules (kotlinx-coroutines-reactive for Reactive Streams, kotlinx-coroutines-reactor for Project Reactor and kotlinx-coroutines-rx2 for RxJava2). Integration modules include conversions from and to Flow, integration with Reactor’s Context and suspension-friendly ways to work with various reactive entities.

Kotlin Flow doesn’t stop here. It’ll only keep getting better, especially with the future improvements that Jetbrains has recently announced at KotlinConf:

  • Out-of-the-box support for UI models
  • Sharing and caching flows
  • Concurrency and parallelism operators (I am most excited for this!)
  • Chunking and windowing operators

Spring support is also only going to keep getting better. It was really helpful to see most of the Spring WebFlux Documentation examples in Java and Kotlin.

If you are interested in exploring more about Kotlin Flow and reactive programming, here are some readings from Roman Elizarov that I would recommend: Reactive Streams and Kotlin Flow, Extension Oriented Design, and Structured Concurrency.

🌊Kotlin is kool.

--

--

Shelby Cohen
Intuit Engineering

Software Engineer👩🏼‍💻👾 #Kotlin #FP #Boston @twitter