Monday, June 15, 2009

Shutdown hook in Groovy... Inner Classes in Groovy

Groovy doesn't support Inner classes directly. I was in a hurry to implement a shutdown hook in Java so I came accross the groovy workaround
http://groovy.codehaus.org/Groovy+Alternatives+to+Inner+Classes

I had to tweak the script slightly to get it to work for the shutdown hook (see below).

To implement the shutdown hook in Java a Thread instance is passed to the addShutdownHook() method of the Runtime instance.

In Java we could create an Inner class that extends Thread, or that implements Runnable.

In Groovy we must create a Map. The Map contains a list of key/ values. These correspond to method names (key), and method implementations (closure). For this case the closure will represent the Thread that we pass to the Runtime.addShutdownHook() method. Therefore we are implmenting the run() method, so the key in the map must be run().

The ProxyGenerator is then used to dynamically add the interface to the close. Finally since Runtime.addShutdownHook() expects a Thread instance (not simply a class that implements Runnable) ,we must add the Thread.class to the call to ProxyGenerator.instantiateAggregate().



def shutdownClosureMap = [run: {
outputFile.close();
println "Shutting down";
}
]
def interfaces = [Runnable]
def shutdownListener = ProxyGenerator.instantiateAggregate(shutdownClosureMap, interfaces, Thread.class)

Runtime.getRuntime().addShutdownHook((Thread)shutdownListener);

Friday, June 12, 2009

Groovy GString/ STring

A few Gotchas that I've been getting stung with in Groovy.

GStrings and Strings

Be careful with Groovy Strings and Sql.

Make sure you know the rules of when Strings become GStrings, and therefore can support dynamic variable replacements.

GString docs can be found
http://docs.codehaus.org/display/GROOVY/Strings+and+GString

These rules are listed here: (Note this doc is aproposal for changnig GString)
http://docs.codehaus.org/display/GroovyJSR/Groovy+String+Handling

For example in the code below, if you simply use "def" to declare your variable, you will not see explicitly which types get converted to GStrings and which get converted to plain Strings.

By been explicit in your definitions however you can see that sql6 will not cast by default to a GString. This is becausei t is a multiline java.lang.String (see rules in link above). You will get this exception.

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object "..." with class 'java.lang.String' to class 'groovy.lang.GString'

To fix it.


Date startDate = new Date() -1;
Date endDate = new Date();
def Format = "yyyy-MM-dd"
def OFormat = "YYYY-MM-DD"
String startString = startDate.format(Format);
String endString = endDate.format(Format);
println "Running between $startString and $endString";
def sql = []
def sql1 ="""
select * from prov_auditing_master m where EVENTTIMECOMPLETED > to_date($startString,$OFormat) and EVENTTIMECOMPLETED < sql2 =""> to_date($startString,$OFormat) and EVENTTIMECOMPLETED < sql3 =""> to_date($startString,$OFormat)"+
" and EVENTTIMECOMPLETED < sql4 =""> to_date($startString,$OFormat) and EVENTTIMECOMPLETED < sql5 =" "> to_date($startString,$OFormat) and EVENTTIMECOMPLETED < sql6 = ""> to_date($startString,$OFormat)"+
" and EVENTTIMECOMPLETED < db =" int" i="1">
println i+": $sq"
i++
}

To fix

GString sql7 = "$sql6" ;
sql <<>