Monday, February 22, 2010

Some Groovy Class-Loading Notes

Was trying to load a resource (*.properties) from the class-path and as you know, class loading can be a PITA at different enviroments (IDEs, build tools, tests, containers).

Here's the snippet I used, ran with Maven and Eclipse IDE, target/test-classes is in the class-path.
String name = "aflexi.itest.properties"

// System CL
println ClassLoader.getSystemClassLoader()
// Uses system or bootstrap CL
println ClassLoader.getSystemResource(name)

// Caller CL
println ClassLoader.getCallerClassLoader()
println ClassLoader.getCallerClassLoader().getResource(name)

// Class's class loader. Perfectly fine in both places
println getClass().getClassLoader()
println getClass().getClassLoader().getResource("aflexi.itest.properties")

// Doesn't work anywhere, the CL is the one of previous, but the name will be resolved as "net/aflexi/cdn/test/itest/aflexi.itest.properties"
println getClass().getClassLoader0()
println getClass().getResource("aflexi.itest.properties")

// Doesn't work either. Using Groovy's calling class.
println ReflectionUtils.getCallingClass()
println ReflectionUtils.getCallingClass().getResource("aflexi.itest.properties")

And here's the result:

Expression / Class LoaderTest 1: InstanceTest 2: InstanceTest 1: Found Resource?Test 2: Found Resource?
ClassLoader.getSystemClassLoader().getResource()sun.misc.Launcher$AppClassLoader@19134f4sun.misc.Launcher$AppClassLoader@19134f410
ClassLoader.getCallerClassLoader().getResource()sun.misc.Launcher$AppClassLoader@19134f4org.codehaus.groovy.tools.RootLoader@8965fb11
getClass().getClassLoader().getResource()groovy.lang.GroovyClassLoader$InnerLoader@14177f3groovy.lang.GroovyClassLoader$InnerLoader@dc043511
getClass().getResource()groovy.lang.GroovyClassLoader$InnerLoader@14177f3groovy.lang.GroovyClassLoader$InnerLoader@dc043500
ReflectionUtils.getCallingClass().getResource()class cuke4duke.internal.groovy.GroovyLanguageclass groovy.ui.GroovyMain00

Take note that, getClass().getResource() uses the same CL instance (otherwise system CL) with getClass().getClassLoader().getResource(). The reason why it failed is that, it resolves the name of the properties file with package name, i.e. aflexi.itest.properties to net/aflexi/cdn/test/itest/aflexi.itest.properties.

Saturday, February 20, 2010

POGO + Singleton + Mixin

Something worth sharing (or probably you may suggest me with a better solution) about injection/Mixin on Groovy's object that is being a singleton.

Let's start off with an example. I have a Users class with a private singleton, e.g.
@Mixin(Whatever)
class Users{

  private static Users instance = new Users()

  def doGetUserByEmail(){}

  static def getUserByEmail(){
    instance.doGetUserByEmail()
  }
}

Unfortunately, this is not working as Users.instance is constructed within the class before Groovy does more thing with its interpreter (at this point, I still have limited knowledge about Groovy, but that's the basic idea).

So I let Groovy to handle the construction of the singleton for me, with @Singleton - resulted with the same effect.

However, @Singleton(lazy = true) solves the problem, as the late/lazy instantiation happens on a "ready" POGO class.