I have a strange bug with coroutines (basic level)...
# coroutines
p
I have a strange bug with coroutines (basic level) This one
Copy code
@GetMapping("/health-check")
    fun healthCheck() = runBlocking {
        mapOf(
            "version" to javaClass.getPackage().implementationVersion,
        )
    }
returns
Copy code
{
  "version": null
}
however this one
Copy code
@GetMapping("/health-check")
    fun healthCheck() =
        mapOf(
            "version" to javaClass.getPackage().implementationVersion,
        )
returns something. Why it that?
s
javaClass
is an extension property on the current receiver. Inside
runBlocking
, the receiver is replaced by a
CoroutineScope
, so
javaClass
actually gets you the class of the coroutine scope, which I guess is not what you want!
A simple solution is a qualified `this`:
Copy code
class MyClass {
    fun myFun() = runBlocking {
        val wrongClass = this.javaClass // ❌
        val myClass = this@MyClass.javaClass // ✅
    }
}
p
Thanks. Huh, logical, but huh. So excatly what will it be? How is that possible then that I see all instance fields?
s
When I said the receiver is “replaced”, that’s actually a bit of a simplification. Actually the original receiver is still there. When you bring a new receiver into scope, its members will shadow the members of the existing receivers. So you can see all the original instance fields, as long as they don’t share the same name as a property belonging to the new receiver.
p
And can I achieve that without mentioning the actual classname? (so without MyClass)
s
Not really, but you could work around it by just extracting another function:
Copy code
@GetMapping("/health-check")
fun healthCheck() = runBlocking {
    mapOf(
        "version" to getImplementationVersion(),
    )
}

fun getImplementationVersion() = javaClass.`package`.implementationVersion