Wednesday, March 21, 2012

Grails dynamic methods

One of the great features of Grails is the dynamic methods that allow you to create complex lookup methods dynamically.

Here's a couple of points though


Account.findByLabelInList(labels)


The InList appender allows you to search by items in a list

Likewise for Criteria.


CreateCriteria
e.g.
static findMyAccount(def name, def country, def accountType, def labels) {
(DcmAccount)DcmAccount.createCriteria().get {
eq("name", name
eq("country", country)
eq("accountType", accountType)
'in'("labels", labels)
}
}

This is a method on the domain class that I created to lookup accounts based on 4 criteria. Notice the in criteria. It has to be enclosed in quotes since it is a Grails reserved word. It allows you to search for items contained in a list.

Monday, March 12, 2012

FoxClocks

Fox Clocks is a handy little addon for firefox. It can display multiple clocks around the world so you can see the local time in any chosen city.

I thought there was a problem with the daylights saving time bevahiour of FoxClocks.

I'm using version 2.9.35. It was reporting my local time correctly, but 2 days ago the US had their daylights savings time adjustment, while in Europe we are not having ours for 2 more weeks.

My time was been reported corectly, but my US based FoxClocks were not. They were still showing the old pre-Daylight Savings time.

The problem is because that FoxClocks uses an internal database of when daylights saving events occur. I simply had to update that database using Tools/ Options/ Time Zone Data/ Check Now.
When this is done it displayed the correct US times.

Monday, March 05, 2012

Grails Class.forName (loading classes dynamically)

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