This is a quickie for now.. I will have to come back and expand this entry when I understand more of why it happens.
simple problem. Wanted to load classes dynamically based on a domain instance name.
Simple (in theory)
String name="Domain"
String className = "com.package.test."+name+"Service"
Object o =Class.forName(className).newInstance()
But it fails with a ClassNotFoundException. (and of course the class does exist).
After a lot of tested I came to the following answer
Object o = Thread.currentThread().contextClassLoader.loadClass(className).newInstance()
or
Object o = SomeOtherService.getClassLoader().loadClass(className).newInstance()
Why I don't know. One tends to work in unit tests and not in application code, and the opposite for the other, so often I include both
Here's some links that may help explain.
http://groovy.dzone.com/news/class-loading-fun-groovy
Based on this I wrote a simple test to check the different class loaders
def testB(){
parseCL(this.getClass().getClassLoader()) //This ClassLoader does NOT work
parseCL(AnotherService.getClassLoader()) // This class Loader does work
}
def parseCL(ClassLoader cl){
println "********************"
println cl
println "********************"
println "Parent ="+cl.getParent()
cl = cl.getParent()
def indent = "--"
while(cl){
println indent+cl
cl = cl.getParent()
println indent+"Parent ="+cl
indent = indent +"--"
}
}
Note the top level classloader is different
********************
java.net.URLClassLoader@247510e7 // DOES NOT LOAD CLASS DYNAMICALLY
********************
Parent =java.net.URLClassLoader@77479ef9
--java.net.URLClassLoader@77479ef9
--Parent =org.codehaus.groovy.grails.cli.support.GrailsRootLoader@15ded0fd
----org.codehaus.groovy.grails.cli.support.GrailsRootLoader@15ded0fd
----Parent =sun.misc.Launcher$AppClassLoader@35a16869
------sun.misc.Launcher$AppClassLoader@35a16869
------Parent =sun.misc.Launcher$ExtClassLoader@77cde100
--------sun.misc.Launcher$ExtClassLoader@77cde100
--------Parent =null
********************
java.net.URLClassLoader@77479ef9 // LOADS CLASS DYNAMICALLY
********************
Parent =org.codehaus.groovy.grails.cli.support.GrailsRootLoader@15ded0fd
--org.codehaus.groovy.grails.cli.support.GrailsRootLoader@15ded0fd
--Parent =sun.misc.Launcher$AppClassLoader@35a16869
----sun.misc.Launcher$AppClassLoader@35a16869
----Parent =sun.misc.Launcher$ExtClassLoader@77cde100
------sun.misc.Launcher$ExtClassLoader@77cde100
--------Parent =null