Hi all, this topic is more advanced but I can’t fi...
# getting-started
c
Hi all, this topic is more advanced but I can’t find a better channel to place it. I need to execute some code on startup without knowing of its existence, think of an expendable registry where classes can register themselves (somehow like observer). The challenge is that - as I can’t instantiate these classes (actively) - the code is currently within a
companion object
. So I decided to provide an interface (or an annotation) and find the functions to call on startup as follows using (using classgraph as for scanning - I’m not bound to that framework):
Copy code
interface OnStartup {
  fun onStartup()
}

// a class that wil instantiated a lot of times during runtime
data class SomeClass(val name: String) {
  companion object : OnStartup {
    override fun onStartup() {
      // notify someone at startup about our existence
    }
  }
}

fun main() {
  ClassGraph().enableAllInfo().acceptPackages("com.test").scan()
    .getClassesImplementing(OnStartup::class.java)
    .filter { it.isStatic }
    .flatMap { findStartupMethods(it) }
    .forEach {
      it.call()
    }
}

private fun findStartupMethods(classInfo: ClassInfo): List<KFunction<*>> {
  return classInfo.methodInfo.filter { function ->
    function.name == "onStartup"
  }.mapNotNull { method ->
    method.loadClassAndGetMethod().kotlinFunction
  }
}
This will not work as
call()
expects a parameter:
Callable expects 1 arguments, but 0 were provided.
which should be the instance of the class (from my understanding), so I guess it should be the
companionObjectReference
. The code works well if I define the
onStartup
function on top level (but that has negative impacts for my idea). Is there any way to retrieve the
companionObjectReference
? Or to achieve this behaviour? Maybe there is another annotation scanner that fits better for Kotlin? Any help is appreciated.
y
Since you have classInfo, can you get a
Class
out of it? Because then, you can do
klass.kotlin.objectInstance!!
c
Ah, didn’t saw the
.kotlin
🙂 thanks for your help! Solution now looks like:
Copy code
val companion = classInfo.loadClass().kotlin
if (companion.isCompanion) {
  companion.memberFunctions.filter { it.name == "onStartup" }.forEach { it.call(companion.objectInstance) }
}
K 1