Thursday 19 February 2009

Hitlers nightly build fails

With a whole bunch of Energizers en route to Canadia post-haste I'm feeling distinctly in de-mob happy mode. 

Thought I would post a funny, yet development related, video which @unclebobmartin just shared

Hitler's Nightly Build Fails


Its worth watching the the end.. Its get better n better :) Cheers, @franklywatson

Wednesday 11 February 2009

Case-insensitive ordering using HSQLDB

We've recently begun the process of testing our app on Postgres, and came across a problem where our 'order' statements were returning results in a different order to HSQLDB.

Postgres was ignoring the case of items, whereas HSQLDB was not - so if I were to order the strings "Al" and "AM", HSQLDB would show "AM" before "Al", but Postgres would show "Al" before "AM".

Given that the behaviour of Postgres (case-insensitive ordering) was the desired behaviour, we wanted to get HSQLDB to do the same. After a lot of searching any many dead ends, we found that you simply use ".ignoreCase()" after an order criteria:

List books = Book.withCriteria() {
ilike('authorName', "%${searchKey}%")
order('authorName', 'asc').ignoreCase()
maxResults(max)
}

Immutable Objects in Groovy

Anyone familiar with Joshua Bloch's book Effective Java will know about the importance of immutable objects. However, writing classes like that in Groovy always seemed to me to be problematic. You can declare the properties final but if the property type is itself mutable encapsulation is broken. Defining properties as private wasn't enough as Groovy lets you access them from anywhere regardless (I'm still not entirely clear why the language even supports it). A combination of final properties with overridden get methods where property types are mutable works but then you're writing almost as much code as you'd need to in Java and who knows what someone can get away with by using the .@ operator!

Google provided the solution this morning. It turns out there is an @Immutable annotation in Groovy that solves the problem in a very neat way even giving you an implementation of equals, hashCode and toString for free. Those methods tend to be pretty much templated in immutable classes anyway so getting effective implementations without writing any code makes a lot of sense and feels very 'Groovy'.

Tuesday 10 February 2009

Binding to collection fields on command objects

One of the cool new features of Grails 1.1 is the ability to bind form elements to collection properties of domain objects. Unfortunately it doesn't quite work out of the box for command objects.

Suppose I have a command class like this:

    class MyCommand {
Map things = [:]
}

and my form posts params like this:

    things[key1] = value1
things[key2] = value2
things[key3] = value3

I'd hope that the binder could cope with this and populate my command object's things property with the appropriate keys and values. It doesn't work as it seems that Grails attempts to figure out what the type of the object contained in the collection is. For domain objects this is possible since the hasMany closure can be used. Command objects don't have this available and so you end up with a nasty stack trace boiling down to a NullPointerException.

However there is a way to 'fool' the data binder. All it's trying to do is figure out the value type for the Map so it can use an appropriate PropertyEditor to decode the HTTP request parameter value. In this example the value is just a String. Initializing the Map like this provides a workaround:

    import org.apache.commons.collections.MapUtils
import org.apache.commons.collections.FactoryUtils

class MyCommand {
Map things = MapUtils.lazyMap([:], FactoryUtils.constantFactory(''))
}

That's using a LazyMap from Commons Collections which (in case you can't guess) is a Map implementation that populates a default value when get is called for an unmapped key. The Map in the command object will use the empty string as its default value which is enough for the Grails data binder to figure out the value type and bind our parameters.

I haven't tried the same trick with richer data types yet (e.g. a collection of domain objects in a command) but I don't think there's any reason why a similar workaround returning a different value from the Factory shouldn't work.

Sunday 1 February 2009

Testing Url Mappings

If you have to support legacy urls, want some quick feedback when putting your url mappings together or want to verify the parameters are being parsed correctly, here's a little grails integration-test snippet that you may find useful:

def grailsUrlMappingsHolderBean

void testMappingForPersonController() {
def mappingInfo = grailsUrlMappingsHolderBean.match('/person/pain')
assertEquals 'person', mappingInfo.controllerName
assertEquals 'show', mappingInfo.actionName
assertEquals 'pain', mappingInfo.parameters.id
}

The grails testing plugin provides custom assertions for doing this and more (assertUrlMapping etc.).

kthxbye