Saturday, 21 March 2009
Release of gmock 0.7.0
Strict ordering is accomplished through the ordered closure. Here is an example with an hypothetic cached cat database:
def database = mock()
def cache = mock()
ordered {
database.open()
cache.get("select * from cat").returns(null)
database.query("select * from cat").returns(["cat1", "cat2"])
cache.put("select * from cat", ["cat1", "cat2"])
database.close()
}
The partial mocking is performed simply by using the mock method on your concrete object. Here is how it works with a grails controller:
def controller = new SomeController()
mock(controller).params.returns = [id: 3]
GMock 0.7.0 is the last release compatible with Groovy 1.5.x. Support for Groovy 1.6.0 is coming soon.
Tuesday, 10 March 2009
Grails 1.1 released
Tuesday, 3 March 2009
Gsp reloading for other environments
This came to light because we do not use production data in our development environment but sometimes it's useful to have production data to test with or to work out a bug. We have a separate environment config for the times we want to run with prod data so this little flag has become a life-saver.
Monday, 2 March 2009
New in Groovy 1.6
whats new in groovy 1.6
Groovy 1.6 will be released with grails 1.1
Sunday, 1 March 2009
Running Selenium Tests In Grails 1.1
Anyone experimenting with Grails 1.1 might be interested to know that I've got the Selenium plugin working. If you put the following entries in your project's grails-app/conf/BuildConfig.groovy:
grails.plugin.repos.discovery.energizedwork="https://svn.energizedwork.com/skunkworks/grails/plugins"
grails.plugin.repos.distribution.energizedwork="https://svn.energizedwork.com/skunkworks/grails/plugins"
Then type grails install-plugin ew-selenium you should be good to go.
The command to run tests is grails run-selenium. The script now runs in the test environment by default so you no longer need to use grails test run-selenium.
You may need to configure the browser Selenium uses. To do so edit test/selenium/selenese/conf/SeleniumConfig.groovy and set the selenium.browser property. For some reason Firefox 3 needs to be specified as *chrome. For example on a Mac I have to use the setting
selenium.browser = "*chrome /Applications/Firefox.app/Contents/MacOS/firefox-bin"
I have no idea why this is necessary. I have upgraded the Selenium Server version included in the plugin but I found this was also necessary with the old 0.9.2 version.
I changed the plugin name to ew-selenium as there is a plugin called selenium on the main Grails plugin repository and it looks like Grails will ignore conflicting names on other repositories.
Thursday, 19 February 2009
Hitlers nightly build fails
Wednesday, 11 February 2009
Case-insensitive ordering using 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
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