1

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

delimiter
  • 183
  • 1
  • 2
  • 9

1 Answers1

0

Maybe it looks ugly, but it works...

it.call((it.parameters[0].type.classifier as KClass<*>).objectInstance)
sirjoga
  • 91
  • 4