I have the following Scala class hierarchy:
abstract class BaseModule(val appConf : AppConfig) {
// ...
}
class SimpleModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
class FairlyComplexModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
// dozens of other BaseModule subclasses...
At runtime, my app will accept a String input argument for the fully-qualified class name of a BaseModule
subclass to instantiate, but the code won't know which concrete subclass it will be. So I have:
val moduleFQCN = loadFromInputArgs() // ex: "com.example.myapp.SimpleModule"
val moduleClass = Class.forName(moduleFQCN)
println(s"Found ${moduleFQCN} on the runtime classpath.")
val module = Class.forName(moduleFQCN).getConstructor(classOf[AppConfig]).newInstance(appConf).asInstanceOf[BaseModule]
So this way, the input specifies which BaseModule
subclass to look for on the classpath, and then subsequently, to instantiate. The first three lines above execute just fine, and I see the println
fire. However the last line above throws an exception:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
<rest of stacktrace omitted for brevity>
So clearly I'm doing something wrong when trying to create an instance of the SimpleModule
subclass, just can't figure out what it is. Any ideas?
You're probably failing because you call newInstance()
without any arguments, but no default constructor is found therefore the instantiation fails.
try this:
Class.forName(moduleFQCN).getConstructor(classOf[AppConfig])
.newInstance(appConf).asInstanceOf[BaseModule]
Where appConf
is an instance of AppConfig
and is the parameter to instantiate BaseModule
with.