I am trying to notify a central class on startup about the existence of some classes that will be used during runtime. My idea is to use reflection: scan for annotation (or interface implementation) and call a method from the companion's object of those classes.
As suggested in [1] I am using classgraph
but I'm totally open to alternatives.
package com.test
import io.github.classgraph.ClassGraph
import io.github.classgraph.ClassInfo
import io.github.classgraph.ScanResult
import kotlin.reflect.KFunction
import kotlin.reflect.jvm.kotlinFunction
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class OnStartup
// a class that will be instantiated a lot of times during runtime
data class SomeClass(val name: String) {
companion object {
@OnStartup
fun onStartup() {
// notify someone at startup about our existence
}
}
}
fun main() {
val scanResult: ScanResult = ClassGraph().enableAllInfo().acceptPackages("com.test").scan()
scanResult
.getClassesWithMethodAnnotation(OnStartup::class.java.name)
.filter { it.isStatic }
.flatMap { findStartupMethods(it) }
.forEach { it.call() }
}
private fun findStartupMethods(classInfo: ClassInfo): List<KFunction<*>> {
return classInfo.methodInfo.filter { function ->
function.hasAnnotation(OnStartup::class.java)
}.mapNotNull { method ->
method.loadClassAndGetMethod().kotlinFunction
}
}
The problem is, that the code exits with
Exception in thread "main" java.lang.IllegalArgumentException: Callable expects 1 arguments, but 0 were provided.
From reading the Kotlin Docs and [2] my guess is that I should hand over the companionObjectInstance
as a parameter. But I have absolutely no idea how to get it...
Any help is really appreciated.
[1] Getting a list of annotated functions in Kotlin using reflection
[2] Kotlin invoke companion function with reflection