Is it possible to turn blocking Java code into non-blocking with Kotlin? How?

I am complete new to Kotlin so please bear with me. My problem: I am developing an API that will query a database. The database provides JDBC connector that is blocking and my queries will be long-running (up to 60s). Is it possible to turn the blocking code into non-blocking with Kotlin? How? Example code would be appreciated. Thanks.

Well, yes and no. We can’t anyhow turn blocking operation into non-blocking. But we can handle it in a smart way, so most of our code is non-blocking.

While using Kotlin coroutines, we can do it simply by:

with (Dispatchers.IO) {
    // blocking operation
}

Internally, it schedules the operation using a special thread pool, but the calling thread is only suspended and can do something else.

If not using coroutines then I believe Kotlin doesn’t provide any tools for this.

Do you mean withContext(...)?

Yes, I meant withContext() :slight_smile:

It is not possible to turn blocking code into a non-blocking. Unless project Loom fulfills its promise and even in this case it probably won’t be fully automatic. In Kotlin you can call blocking code asynchronously. Though it will still block a thread it is called on.

Yeah basically what broot and thumannw said; use withContext().

Let’s say your blocking database call looks like this:
database.withHandle { it.createQuery("get-my-data.sql").list() }

Put that code inside a withContext lambda, like so:

withContext(Dispatchers.IO) {
    database.withHandle { it.createQuery("get-my-data.sql").list() }
}

This will run the code inside the withContext lambda on the Dispatchers.IO coroutine dispatcher; essentially what happens is your blocking code is run on a different thread, while your calling thread is suspended while waiting for the blocking code to complete. It doesn’t stop the blocking code from blocking a thread, but since it blocks a thread in a threadpool and suspends your calling thread, you still get the effect you want. :slightly_smiling_face:

If you want to make it more dynamic, and allow consumers of your API to provide their own threadpool/dispatcher for running blocking code, you could do something like the following:

suspend fun <T> makeBlockingCodeSuspend(
    dispatcher: CoroutineDispatcher? = null,
    block: suspend CoroutineScope.() -> T
) = withContext(dispatcher ?: Dispatchers.IO, block)

EDIT: Anyone know how to make Dispatchers.IO not show up as a hyperlink?

Like this: Dispatchers.IO