Fork me on GitHub

29 Dec 2009

Selenium RC tests with a remote app

I've just released a new snapshot of the Selenium RC plugin. The main new feature is the ability to run your Selenium tests against a running instance of your application instead of having the application start and stop as part of the test phase. A number of people have requested this. It's really useful for CI environments where you may want to start the app up on a different server from where the tests are being run.

All you need to do is set selenium.remote = true in your SeleniumConfig.groovy and set selenium.url to the root URL of the server where the app is running. Once this is done you can run tests as normal (note: when remote mode is used Selenium tests run in the other phase rather than the functional phase).

The really useful thing is that SeleniumConfig.groovy can contain environment blocks just as other Grails config files can. This means you can enable remote mode in your CI environment but continue to test as normal locally. For example:
selenium {
    remote = false
    // etc.
}

environments {
    hudson {
        selenium.remote = true
        selenium.url = "http://my.test.server/"
    }
}

The plugin release is a snapshot so you need to specify the version explictly: grails install-plugin selenium-rc 0.2-SNAPSHOT and you need to be using Grails 1.2.

12 Dec 2009

New Springcache Plugin Version

After saying it might take me a while I got stuck in and rewrote the Springcache plugin from scratch. The new version is up now. The plugin now requires Grails 1.2.0-M3 or greater as it's reliant on Spring 3.0.

The plugin allows you to declare caching and flushing behaviour on service methods (well, any Spring bean methods, but services are typical) using @Cacheable and @CacheFlush annotations. This is really useful for service methods that perform long-running or expensive tasks such as retrieving data from web services, network resources, etc. The plugin is less appropriate for service methods that retrieve data using GORM/Hibernate as you could just use the 2nd level cache, although there's nothing stopping you doing so if it makes sense in your domain.

The documentation and source code are in the usual places. Here's a quick summary of the changes and new features:

  • No longer depends on the (discontinued and non-Spring 3 compatible) spring-modules-cache library.
  • No more mapcache, the plugin now uses ehcache by default.
  • Only ehcache is supported directly but it's really easy to implement an adapter for other caching libraries if you need to.
  • Slightly simplified configuration. Some minor tweaks will be needed if you're upgrading from an earlier version of the plugin.
  • Bean names are now prefixed with "springcache" so they're much less likely to clash with other things in your Spring context.

There has been some interest in some new features such as a taglib for caching chunks of views which I may start looking at shortly.

26 Nov 2009

Springcache Plugin Status

A couple of people have asked me about the Springcache plugin and Grails 1.2. Currently the plugin is not compatible with 1.2-M3 and onwards. The reason for this is that the spring-modules-cache library that the plugin depends on is not compatible with Spring 3.0 which is used by the newest versions of Grails. Not only that but the spring-modules project has been discontinued altogether. There is a fork of it on Github but that doesn't look terribly active either. This means that at some point I'm going to have to sit down and write some code to bring the annotation driven caching inside the plugin itself and drop the spring-modules dependency. However, just to compound things the Spring documentation on the relevant area hasn't been updated yet and still references the classes that have been removed from the API which is what's causing the incompatibility in the first place!

So, it's on my to-do list but don't hold your breath!

21 Nov 2009

Why do Strings behave like a Collection?

Mostly I love Groovy but every now and then some behaviour gets on my nerves. For example, why do the iterator methods on String behave as though it was a collections of characters rather than an Object? If I define a method with a dynamic-typed parameter like:
void printNames(names) {
    names.each {
        println it
    }
}
Passing a collection of Strings results in each String being printed. Passing a single String results in each character of the String being printed separately. I would have thought that the Object behaviour was a more appropriate default here (iterators on Object are called once passing the object itself). After all the .chars property is available if you really want to represent a String as a collection of characters.

The solution is to override the method:
void printNames(String name) {
    printNames([name])
}
Unlike in Java dispatch to such overridden methods in Groovy is based on the runtime rather than declared type of the parameter.

You might think this is a trivial point, but the scenario that keeps biting me is HTTP parameters passed into a Grails controller. If you have multiple inputs with the same name, or a multi-select then sometimes params.x is a String and sometimes it's a List of Strings. Any code dealing with that parameter has to handle the two cases separately.

Slides from GGUG

I gave a talk last night at the London Groovy & Grails User Group about the Selenium RC plugin and how to use it. I pitched the talk assuming that people were somewhat familiar with Selenium and had probably used the Selenium IDE. I'm not sure if that was the right way to go but the talk went pretty well and people seemed interested in what I had to say. I ended up talking a lot about the page object pattern and how awesome it is for building manageable suites of Selenium tests.

I really wanted to show a few quick examples but I had neglected to consider that a mini display port VGA adapter might be a useful thing to bring and unfortunately with Skills Matter being in the middle of an office move there wasn't one to hand. Luckily I was able to borrow a laptop so at least I could get my slides up on the projector.

5 Nov 2009

Grails Selenium RC Plugin Released

I've finally got the first release of the Selenium RC plugin out of the door. Just run grails install-plugin selenium-rc to install.

For anyone unfamiliar with Selenium RC basically the plugin allows you to write and run Selenium tests in Groovy to functionally test Grails apps using a real browser. The tests run in the functional phase using grails test-app or grails test-app -functional.

In terms of compatibility there is a very minor issue with Safari and some slightly more annoying ones with IE - all of which the plugin's default configuration will work around for you. Unfortunately Firefox 3.5 on OSX Snow Leopard doesn't want to play at all due to an open Selenium bug. Firefox on other platforms, Google Chrome and Opera all appear to be 100% compatible.

I've tried to make writing the tests themselves as similar to regular Grails unit and integration testing as possible. Not only that, if you have the Spock plugin installed you can write your Selenium tests as Spock Specifications.

Documentation is here, source code is on GitHub and issues and feature requests can be raised on Codehaus' JIRA. I've got plenty of things to work on for future releases such as Selenium Grid integration and automatic screen-grabbing when assertions fail.

2 Nov 2009

Talk on Selenium RC Testing In Grails

I'll be delivering a short talk about testing Grails apps with the Selenium RC plugin I'm working on at the London Groovy and Grails User Group on 20th November. Details are here.

The plugin is basically release ready, I'll try to make the final push some time this week so that it's out in the wild in advance of the talk (and hopefully any particularly idiotic bugs are reported and fixed before I make a total fool of myself).

Git and Hudson

I just encountered a rather annoying problem when running Hudson as a service on Ubuntu. I was getting the following exception whenever the build checked code out of GitHub:
hudson.plugins.git.GitException: Could not apply tag hudson-Selenium_RC_Plugin-23
 at hudson.plugins.git.GitAPI.tag(GitAPI.java:265)
It turns out Git needs a username to be set and the hudson user that the Debian package creates when Hudson is installed doesn't have one. Easily fixed by using sudo nano /etc/passwd to add Hudson,,, into the hudson user's entry (if you look at your own entry you should see where it needs to go).

14 Sept 2009

Testing Grails Apps With Selenium-RC

I mentioned in my last post that I'd started to think we were going about Selenium testing all wrong. For years I've been writing Selenium tests using the Selenium IDE, so the tests are in HTML files. When doing pre-commit testing and on CI the tests are run with the HtmlTestRunner. This technique is fine and well - developing tests with the IDE is fast and they can be easily worked on an re-tested in the IDE until they are correct. However, some things have always bothered me and Adam Goucher's thoughts on the Selenium Value Chain crystallised some of those suspicions.

So what are the big advantages of using Selenium RC over just the IDE and HtmlTestRunner?

Test design

Selenium tests written in HTML tend to either become an amorphous blob, not testing one simple thing or proliferate to the point of having hundreds of small test files. With Selenium RC you can write Selenium test classes with multiple test case methods just as you would unit tests. Each test case can be neat, self-contained and share set up with other test cases in the same class. Also by abstracting out common command sequences into utility methods you can start to develop a higher level DSL for testing your application. In HTML tests this can be done by writing extension functions in Javascript but it's not as straightforward.

Data fixtures

Data set up is the biggest headache when writing Selenium tests in HTML. You can't drop out of selenese and set up a couple of domain objects so you end up either trying to run all your tests against a monolithic data fixture (a Sisyphean task if any of your tests make modifications to the data) or write some sort of URL endpoints that can set up and tear down data. We've done the latter and it's resulted in the single most bloated, horrible, misused bit of code in our app. Fixtures get re-used by other tests because they set up approximately appropriate data - until some change requires a change in the fixture and suddenly a bunch of unrelated tests fail. Selenium RC tests don't have this problem; you're in Groovy-land so you can access domain classes directly and use the invaluable build-test-data plugin to set data up.

Data verification

I mentioned previously the anti-pattern of false moniker testing and HTML based Selenium tests are terrible for this. If you have a test that creates some data, how do you verify it has done it correctly? The only way is to scrape the data on another screen - e.g. a CRUD list or show view. Ugh! With Selenium RC you can read the data from the database with standard Grails domain classes and verify your expectations directly.

I started experimenting over the weekend with getting Selenium RC tests written in Groovy to run using grails test-app -functional. It turns out to be really fairly straightforward and I've put some alpha code up on GitHub.

11 Sept 2009

Thoughts on Testing

These are some of the practices I try to live by when writing test coverage. Some of the detail may be Grails-centric since that's been my development platform of choice for the last couple of years, but the gist of the points is generally applicable.


I've been thinking about posting something like this for quite a while and was pushed over the edge by reading some interesting things...



Make just one (logical) assertion per test.

The prime attribute of a good test case is legibility. When my change breaks your test I don't what to be scratching my head trying to figure out what it is your the test is trying to prove. The best way to achieve legibility is to have each test case test just one thing. Sure, it may take more than one actual assert statement to test it properly. For example to test a query returns correct values you may want to assert that the return value is non-null, that it is a collection with the correct size and that each element of the collection complies with the query parameters. Those are separate assertion statements but in the service of a single logical assertion.

One of the worst habits you can get into when adding new functionality is to just bung a few more asserts into an existing test case. Imagine we're testing a list action on a Grails controller class. There's an existing test case to confirm the list of instances in the model are correct. You implement a new requirement to load some sidebar content for the page by adding some new stuff to the model (leaving aside the fact that there are better ways to achieve this). This change should be tested with a separate (set of) test case(s) to those testing the list model is correct. That may mean some duplication with several test cases invoking the same controller action with the same parameters but the trade-off is that each test case is self-contained, legible and will not break due to further changes that aren't related to the functionality the test is supposed to be verifying.



Name test cases according to what they are testing

This sounds obvious, but how often do you come across test cases named something like testSaveArticle that doesn't make it obvious what it is testing about saving an article? A good test case name is verbose but only as verbose as it needs to be; names like testListReturnsEmptyListWhenNoResultsFound, testListOnlyReturnsLiveAssets, testUserIsRedirectedToLoginFormIfNotLoggedIn tell me what I have broken when my changes cause those tests to fail. On the other hand if a test case name is too long or contains a lot of 'and's & 'or's it's probably a sign that the test is doing too much and not making a single logical assertion.



Avoid obliquely named 'helper' methods

Few things bug me more when trying to decipher other peoples' tests than helper methods whose names either don't describe properly what it is they do or that have a raft of side effects. These things make tests harder to read, not easier! Names like initMocks (to do what?), createArticles (how many? anything special about them? what behaviour are they trying to drive out?) or checkModel (what about it? how reusable is this?) require the person maintaining your test cases to find the implementation and figure out what it's doing.

Worse, such methods have a tendency to accumulate complex parameters over time, (often with defaults designed to minimise impact on existing code at the expense of making any sense) as they get re-used in new test cases that require them to do slightly different things.



Avoid the test-per-method anti-pattern

The 'test-per-method' anti-pattern is characterised by test cases named testMethodNameX that attempt to test all the paths through a given API method in a single test case (or worse, test only the happy path). A lot of people start out writing unit tests this way, probably because a lot of unit testing tutorials are written this way.

The problem is this pattern bundles a bunch of assertions into a single test and if the earlier ones fail the later ones won't even run meaning you can waste time uncovering layers of broken functionality as you work your way through the failures and re-run the test.

Legibility suffers as well as it may not be obvious at a glance what edge cases, boundary conditions and side-effects are covered and what the expectations for them are. If any kind of state has to be reset between different calls to a method then you will end up writing code that you simply wouldn't if you separated things out into multiple test cases.



Test edge cases and variant behaviour

Tests that only cover the happy path give you false confidence. Coverage should include things like...

  • What happens when null is passed to this method?
  • What is returned when a query finds no results?
  • What happens when you can't connect to that web service or the connection times out?
  • What happens when a user submits a form with incorrect data?
  • What happens when someone figures out your URL scheme includes domain instance ids and starts crafting their own URLs to retrieve records that don't exist?
  • What happens when someone figures out your URL includes a maxResults parameter and crafts a URL to request 10100 results?

TDD is your friend here; if you don't write the code until you've got a test for it, it's a lot harder to miss coverage of edge cases. Similarly the first thing you do when a bug is uncovered is to write a test that fails then fix it.



Test the thing you care about not a signifier

Max introduced me to the anti-pattern of false moniker testing and it's really changed the way I write assertions. It's an easy trap to fall into. Imagine you're testing that a query only returns 'live' records. Do you set up some live and some non-live records with particular names and then test that the names you expect show up in the results, or do you set up the data then assert that all the results actually are 'live' records? The former is terribly error prone (you assume you've set the data up correctly) and much less legible (which records are we expecting? Why that one in particular?)

Groovy's every iterator method is a godsend here enabling you to write code like:

def results = MyDomain.findAllLiveRecords()
assertFalse results.isEmpty()
assertTrue results.every { it.state == 'live' }


Avoid the monolithic setUp method

Much as it's bad to overload individual test cases with too many assertions it quickly becomes a problem when your setUp method is trying to set up data for too many test cases. Different test cases will probably require slightly different data to drive them which results in setUp trying to be all things to all cases or doing things that only a subset of the test cases actually need. As new functionality is developed the setUp becomes a black hole, accumulating more and more mass and becoming less legible and harder to refactor. The cohesion of the individual tests is harmed as well as it's hard to tell at a glance what data exists when an individual test case is run.

Ideally setUp should only be used for bootstrapping things that are truly common between all test cases and the test cases themselves should be responsible for setting up data to drive the test case's assertions.

Really bad examples of this problem will have setUp create a bunch of data and then some of the test cases actually delete it again before doing anything!
The worst example I've ever seen was from a project I worked on where the entire integration suite used a single DBUnit fixture! It was next to impossible to figure out what data would be returned in particular scenarios, impossible to change anything in the fixture without breaking a raft of other tests and the setUp and tearDown phases were so slow that the integration suite took 3 1/2 hours to run!



Keep data fixtures simple

On a related note it's worth striving to keep test data fixtures as simple as possible. For example, if a test has to wire up a bunch of properties and sub-graphs on domain object instances to satisfy constraints it can be really hard to see the wood for the trees when trying to figure out what data the test actually cares about.

When testing Grails apps the build-test-data plugin is a fantastic tool here. It allows sensible defaults to be configured so that tests only need to specify the properties they need to drive their assertions. With well thought out defaults in TestDataConfig.groovy the resulting test code can be very simple.

In unit tests the situation is easier. Since domain objects don't need to pass constraints to simulate persistent instances via mockDomain you don't need to jump through hoops setting properties and wiring up sub-graphs, test cases can set up simple skeleton objects that just contain sufficient state to drive the functionality and assertions the test case is making.



Test at the appropriate level

Slow-running integration tests that are not testing anything that couldn't be adequately tested with unit tests are just wasting time. In the Grails pre 1.1 this was a real issue as the enhancements that Grails makes to artefacts (domain classes, controllers, etc.) were not available in unit tests and therefore integration tests were the only practical way to Grails artefacts. Now with the unit testing support found in the grails.test package this is much less of an issue.

Integration tests definitely have their place but, I believe, should be used sparingly for things that a unit test cannot test and not just written as a matter of course. In Grails apps, for example, criteria queries and webflows cannot be tested with unit tests. I would also argue that there is value in integration testing things like complex queries or transactional behaviour where the amount of mocking required to get a unit test to work would result in you simply testing your own assumptions or expectations.

Do...

  • Write integration tests that add coverage that unit tests cannot.
  • Learn about the Grails unit testing support and understand the differences between unit and integration tests.

Don't...

  • Write an integration test when you should be writing a unit test or functional test.
  • Write integration tests that re-cover what is already adequately covered by unit tests.

I find that integration tests classes named for a single class (e.g. if I have a SecurityController and an integration test called SecurityControllerTests) are a bad code smell worth looking out for. They often tend to be an integration test masquerading as a unit test.

Refactoring Grails integration tests into unit tests doesn't (usually) take long, speeds up your build and I find often results in up to 50% less test code with the same amount of coverage.



Write functional test coverage

Okay, so your unit test verifies that your controller's list action will accept a sort parameter and return query results appropriately but it can't test that the associated view renders a column-heading link that sends that param or that clicking on it again reverses the order. When you start developing rich functionality on a web front-end a back-end unit test isn't going to do you a lot of good either.

Grails' functional testing plugin is a pretty good tool although for rich interaction testing I'd rather use Selenium.

Discussion of practices for these kind of tests really justifies a whole other post.

7 Sept 2009

Session Bound Temporary Files

I've just released Session Temp Files, a very simple plugin for managing a temporary file storage space bound to the HTTP session. I'm working on something where a user uploads a file at the start of a webflow conversation, the flow then validates the file and may require the user to enter extra information before finally the file is saved and an associated record is added to the database. The uploaded files needed to be stored somewhere between the initial upload phase and the successful outcome of the flow where they will be copied in to a permanent storage space. The file is really too big to keep in memory in the flow scope. It's easy enough to create a temp file and delete it at the end of the flow (even if the user cancels out of the flow) however users can also do things like close the browser, suddenly decide to do something different and type in a new URL, etc. The webflow then gets abandoned in an intermediate state. The flow itself will be destroyed when the HTTP session ends but the temp files I created will hang around until the OS decides to sweep the temp directory.

The plugin simply allows you to create a directory within the normal temp directory - System.properties."java.io.tmpdir" - that will get deleted when the HTTP session expires. It binds two new methods on to HTTPSession: getTempDir() returns the session's temp directory, creating it if it doesn't exist and createTempFile(prefix,suffix) works like File.createTempFile except that the file is created inside the directory returned by getTempDir.

The code is up on GitHub and the plugin is available from the standard Grails plugin repository via grails install-plugin session-temp-files.

12 Aug 2009

JSON Rendering Your Classes

It turns out adding custom JSON renderers for your own types to Grails is really easy. Since I habitually use Joda Time instead of the horrible java.util.Date and even more horrible java.util.Calendar I need to be able to render classes such as Joda's DateTime as JSON so that domain objects with fields of those types will convert properly.

Implementing a renderer for a type is as easy as this: DateTimeMarshaller.java. After that all that's required is to register the new renderer in BootStrap.groovy or some other appropriate spot with:

grails.converters.JSON.registerObjectMarshaller new DateTimeMarshaller()

I'll be adding this to the next release of the Joda Time Plugin so that it's completely transparent.

Update: Actually it's even easier than I thought. This being Groovy you can just use closures like so:

JSON.registerObjectMarshaller(DateTime) {
return it?.toString("yyyy-MM-dd'T'HH:mm:ss'Z'")
}

Update: This is now built in to version 0.5 of the Joda Time Plugin.

10 Jul 2009

Auditing data with the Acegi plugin and Grails upgrade pain

I'm in the middle of trying to upgrade our app (again). We're running on Grails 1.1 now and I'm attempting to get us to 1.1.1 and from there to 1.2-M1. As Marc Palmer points out the more people using it the more likely it is that 1.2 final will be rock solid.

The problem that's biting us right now is GRAILS-4453 (or, more accurately, HHH-2763). We're using Grails' Hibernate events support to track the user that created and last updated assets in our system. This isn't just us being anal, the site editors frequently search the data using those criteria so it's an essential feature.

In Grails 1.1 this is simplicity itself. The following code goes in the domain class and that's all there is to it:

 User createdBy
User updatedBy

def authenticateService

def beforeInsert = {
createdBy = authenticateService.userDomain()
}

def beforeUpdate = {
updatedBy = authenticateService.userDomain()
}

Yes, it is quite 'exciting' that you're able to inject a service into a domain class instance. GORM only maps explicitly typed properties to the database so anything declared using def is effectively transient.

Unfortunately Grails 1.1.1 includes a newer version of Hibernate that introduces a particularly horrible problem. When saving any update to our domain object now we're faced with the error: collection [User.authorities] was not processed by flush(). The problem appears to be that the User instance attached to createdBy cannot be flushed when the beforeUpdate closure executes because it has a lazy-loaded collection of authorities. Even declaring the authorities collection as lazy: false doesn't help as the relationship is a bi-directional many-to-many - each Authority also has a collection of all the Users who have been granted that role. Given that for the purposes of displaying data to the audience of our site this audit data doesn't matter a damn I really don't want to be eager fetching it. Also, given the nature of the User-Authority relationship, casual eager fetching could result in rather a lot of data being loaded in to memory (the User, his roles, all the other users with that role, all their roles...)

Our options seem to be:

  1. Explicitly eager fetch the User data in places where the owning object will get updated. Since the domain class in question is the root of a heirarchy of 13 sub-classes (things this project has taught me #63: never do this) and varieties get updated by a service or two, at least one controller and one Quartz and several hundred Selenium test fixtures, it's going to be a massive PITA and just as bad to remove if/when HHH-2763 ever gets fixed.
  2. Break referential integrity and store username or id rather than an actual domain object relationship. This feels horribly wrong and is likely to cause problems down the line.
  3. Store the created/updated information as a domain object of its own. This would make the query to find data by who created or updated it more complex (although not impossibly so) and might actually be prone to the same original bug

I don't know if anyone might have come across this problem and has some kind of workaround (preferably one that isn't an evil hack). I'd really appreciate any pointers.

Update: This is fixed in Grails 1.2-M2

23 Jun 2009

Scripting Plugin and Dependency Installation

Another quick script that I find quite useful, particularly on continuous integration servers is my Prepare.groovy script. It solves a couple of problems

  • Some plugins are not as well behaved as others on installation, for example the Functional Testing plugin automatically installs when test-app or run-app is installed but will then immediately crash with a ClassNotFoundException because the libraries it depends on are not on the classpath yet. Re-running the command will then work but if the commands are part of a CI build it's probably already bombed out and reported a broken build.
  • The Ivy plugin is great but test-app and run-app won't invoke its get-dependencies target to pull down libraries the way they will automatically install plugins.
  • Sometimes the grails command you want the build to execute is supplied by a plugin so there's no convenient way to run it directly from a brand new workspace because the plugin isn't installed yet.

The script simply ensures all plugins are installed and then invokes the Ivy plugin's get-dependencies target (only if the Ivy plugin is installed - it won't blow up on you if you don't use Ivy). At that point you should have a fully workable workspace and be able to run any grails command you like without your app complaining that some library or other isn't present.

18 Jun 2009

Joda Time Auto-Timestamping Issue on Grails 1.1.1

I've not upgraded most of my code to Grails 1.1.1 yet so I hadn't noticed this problem until it was brought to my attention by Manuel Vio on the grails-user mailing list.

I raised a bug a few days ago around the fact that GORM identifies Joda Time types (and presumably any non-default property type) as a one-to-one association. Up to now the only problem this caused me was that it means the Joda Time plugin has to do some slightly hacky tricks in the scaffolding templates to prevent crashes when Grails tries to render the properties as though they were associated domain instances only to find they have no id property. However, on Grails 1.1.1 the bug is causing a nasty failure on auto-timestamping.

Under Grails 1.1 you can use a Joda DateTime for an auto-timestamped fields:

DateTime dateCreated
DateTime lastUpdated

static mapping = {
dateCreated type: PersistentDateTime
lastUpdated type: PersistentDateTime
}

These behave exactly like the regular Date fields with those names, i.e. they're set automatically on save and update. In Grails 1.1.1 the same class will fail on save with a GroovyRuntimeException Could not find matching constructor for: java.lang.Object(java.lang.Long).

There is a (somewhat strange) workaround - declare the timestamped fields as non-lazy!

DateTime dateCreated
DateTime lastUpdated

static mapping = {
dateCreated type: PersistentDateTime, lazy: false
lastUpdated type: PersistentDateTime, lazy: false
}

Digging into the Grails code a little I found that association properties have their getter wrapped in a lazy-loading proxy. Since GORM thinks Joda Time properties are associations, this happens to them. The auto-timestamping code initialises the properties using property.getType().newInstance(System.currentTimeMillis()). Unfortunately, because property is actually the lazy-load proxy rather than the real property property.getType() returns Object.

15 Jun 2009

Checking for plugin updates

If you're anything like me you probably like to keep all your Grails plugins updated to the latest versions. It's quite easy to miss a release announcement and not realise there's a new version available. Although grails list-plugins will list out the available versions and what version you currently have installed it doesn't really highlight the plugins you could upgrade. I threw this script together this morning to do exactly that. It will simply check the plugin versions you have installed against all configured repositories and notify you of any that could be updated.

13 Jun 2009

Querying by Association Redux

A couple of months back I posted about the problems with criteria queries where you want results with a collection property that contains some value.

Last night I was reading through my new copy of Glen Smith and Peter Ledbrook's Grails In Action and my eye was caught by a particular example where they use aliases in a criteria query. Sure enough a quick test this morning confirms that this is the solution to the problem.

To recap. If I have these domain classes:

class Pirate {
String name
static belongsTo = Ship
static hasMany = [ships: Ship]
}

class Ship {
String name
static hasMany = [crew: Pirate]
}

and I want to query for all the Ships containing a particular Pirate I would probably try to do this:

def ships = Ship.withCriteria {
crew {
eq("name", "Blackbeard")
}
}

Unfortunately, while I end up with the correct Ship instances, each of their crew collections only contains the item(s) that matched the criteria regardless of any others that may actually exist.

Using an alias we can do this type of query without resorting to HQL:

def ships = Ship.withCriteria {
createAlias("crew", "c")
eq("c.name", "Blackbeard")
}

A complete test case that proves the point using the domain classes above is:

class PirateTests extends GroovyTestCase {

void setUp() {
Ship.withSession {session ->
def blackbeard = new Pirate(name: "Blackbeard")
def jack = new Pirate(name: "Calico Jack")
def bart = new Pirate(name: "Black Bart")
[blackbeard, jack, bart]*.save()

def ship1 = new Ship(name: "Queen Anne's Revenge")
ship1.addToCrew blackbeard
ship1.addToCrew jack

def ship2 = new Ship(name: "Royal Fortune")
ship2.addToCrew blackbeard
ship2.addToCrew bart

def ship3 = new Ship(name: "The Treasure")
ship3.addToCrew jack
ship3.addToCrew bart

[ship1, ship2, ship3]*.save()

session.flush()
session.clear()
}
}

void testQueryByAssoc() {
def ships = Ship.withCriteria {
crew {
eq("name", "Blackbeard")
}
order("name", "asc")
}

assertEquals 2, ships.size()
assertEquals "Queen Anne's Revenge, Royal Fortune", ships.name.join(", ")
assertEquals "Expected 2 crew but found ${ships[0].crew.name}", 2, ships[0].crew.size()
assertEquals "Expected 2 crew but found ${ships[1].crew.name}", 2, ships[1].crew.size()
}

void testQueryByAssocUsingAlias() {
def ships = Ship.withCriteria {
createAlias("crew", "c")
eq("c.name", "Blackbeard")
order("name", "asc")
}

assertEquals 2, ships.size()
assertEquals "Queen Anne's Revenge, Royal Fortune", ships.name.join(", ")
assertEquals "Expected 2 crew but found ${ships[0].crew.name}", 2, ships[0].crew.size()
assertEquals "Expected 2 crew but found ${ships[1].crew.name}", 2, ships[1].crew.size()
}
}

The first test fails as each Ship returned by the query only has Blackbeard in the crew despite the fact that they were created and saved with 2 crew members each. The second test retrieves the correct results.

Logging out the SQL generated by the Hibernate queries shows the difference in what it's doing under the hood. The first (incorrect) query is:

select * from ship
left outer join ship_crew on ship.id = ship_crew.ship_id
left outer join pirate on ship_crew.pirate_id = pirate.id
where pirate.name = ?
order by ship.name asc

The second (correct) query is:

select * from ship
inner join ship_crew on ship.id = ship_crew.ship_id
inner join pirate on ship_crew.pirate_id = pirate.id
where pirate.name = ?
order by ship.name asc

So the first query is using left outer joins and the second is using inner joins. Running those queries directly in SQuirreL returns basically the same result set so the discrepancy must be in how Hibernate treats the results. It seems Hibernate has populated the Ship instance and its crew collection after the first query and therefore considers the collection to be initialized, although actually the data in the result set was not the complete collection. In contrast, after the second query you can see the individual SQL select statements as the lazy-loading fires when the assertions are done, so Hibernate obviously only populated the root Ship instance from the query results and is treating the collection property as uninitialized.

Hacking on Grails scaffolding templates

Grails scaffolding is a fantastic mechanism for getting you up and running quickly. I love the fact that you can provide your own implementation of some controller actions or views and scaffolding will just fill in the gaps. That way you can start hand-crafting things when complexity increases past a certain point but still have Grails do a bunch of work for you.

I'd done some customising of scaffolding templates before for the Joda Time plugin but recently started playing with them again with a view to creating some I could re-use for future projects. Because scaffolding templates are not only used for dynamic views but also provide the basis of generated views that you go on to customise it's worth having a solid baseline. A couple of things I wanted to do were:

  1. Mark up create and edit forms without using tables
  2. Provide automatic indication of mandatory fields

I'm pretty happy with the result. This is how a standard create form now appears. The grab is from Safari 4 but the rendering is all but consistent across Firefox 3 on my Ubuntu box, Safari 4 on my Mac and even IE6, IE7, Google Chrome and Opera 9 on the Windows XP VirtualBox instances I use for cross-browser testing.

Forms Without Tables

Each form element is simply:

<div class="prop">
<label for="${p.name}">Property Name</label>
${renderEditor(p)}
</div>

Which is reasonable semantic markup. Styling it cross-browser took me a while (I know just enough CSS to make me dangerous) but with a few helpful pointers from our resident front-end guru Jeff I was able to achieve that with a lot less browser-specific tweaking than I would have thought would be necessary.

The necessary CSS is just:

.prop {
margin: 1em 0;
}
label {
display: inline-block;
margin-right: 1.5em;
text-align: right;
width: 8em;
}
input, select {
vertical-align: middle;
}
textarea {
vertical-align: top;
}

Making the label inline-block meant I can apply a width to it so all the fields will line up nicely but also keeps the label inline so I can then use vertical-align on the input to centre it on the text line of the label. The results are consistent cross-browser. Most solutions I've seen around the internet are horribly inconsistent between browsers (and operating systems with different font rendering) and often rely on nasty pixel-perfect margin and padding tweaks to try to align things nicely. That approach rapidly becomes a game of whack-a-mole as a tweak that fixes some alignment on IE will screw it up on Opera, fixing that will make Firefox do something odd, etc.

Automatically Indicating Mandatory Fields

A polite form should really indicate to the user what fields are mandatory and it turns out this isn't hard to achieve automatically in Grails scaffolded views. The scaffolding templates already use the constrained properties of the domain class to determine whether to display a form field for each property. It's a very small step to use the isNullable() and in the case of String properties isBlank() methods to decide whether to render a mandatory indicator.

I simply output a span with an asterisk inside the label then styled it with:

label {
/* other label properties as above */
position: relative;
}
label .mandatory {
color: #c00;
position: absolute;
right: -1.25em;
}

The absolute positioning takes the asterisk out of the flow of the page so the labels and inputs line up neatly regardless of whether there's an asterisk or not and the right: -1.25em shoves it over into the space of the label's right margin. Positioning the asterisk perfectly in between the label and the input is tricky and not reliable cross browser. On IE the asterisk is too far to the right.

I tried other techniques such as disabling the label's right margin when the asterisk is present and setting the asterisk's span to the exact same size the margin would have been. Unfortunately it seems 1.5em as an element width is not quite the same thing as 1.5em as a right margin so the alignment of the labels and inputs was thrown off. Absolute positioning is necessary to maintain that alignment which is far more important to the eye than pixel-perfect placement of the asterisk itself.

Source Code

Here's the source code. Any suggestions for improvements would be very welcome. I based the templates on Marcel Overdijk's excellent i18n-templates, the only differences are in the rendering of the form fields and the surrounding fieldset.

Something this exercise has driven home for me is that when it comes to cross-browser styling less is definitely more. Taking away everything, setting the font size consistently cross-browser, then gradually building up with the simplest markup and styling possible yields the best results.

15 May 2009

Faster, Pussycat! Kill! Kill!

I mentioned previously that we'd seen some speed improvements in our page load time after upgrading to Grails 1.1. It turns out that for the week 3rd May to 10th May Sky Showbiz ranked 8th in the UK for page response time in the Gomez Benchmark Report with an average of 1.84 seconds. We came in ahead of some heavyweights like Amazon, HSBC, British Airways, etc. Sure, we weren't even close to Google (0.35 seconds!) and we rely on heavy caching for most of our responsiveness, but it's not bad for a site that's basically 8 virtual nodes (6 web and 2 DB) running a Grails app on Jetty and PostgreSQL.

28 Apr 2009

Grails Upgrade

We've just finished upgrading our sites to Grails 1.1 and I thought it would be worth sharing some of the fun we had with the process.

First and foremost was a call site caching bug in Groovy 1.6.0 that caused chaos with our unit and integration tests. Basically any time we mocked a class then demanded behaviour on a static method or any time we used the metaClass to override a static method (among other things that's pretty much any unit test that goes anywhere near a domain class) the behaviour wouldn't get torn down again. This caused symptoms such as stubbed dynamic finders leaking from unit tests and breaking integration tests that would pass when re-run in isolation. We got as far as refactoring a whole bunch of test code that mocked static methods before Burt Beckwith pointed out to me that simply replacing $GRAILS_HOME/lib/groovy-all-1.6.0.jar with the newer version from the Groovy 1.6.1 or 1.6.2 release would fix the problem.

Unfortunately the same bug has another effect that was quite catastrophic for us. Any Hibernate proxy of an instance of a domain class involved in an inheritance hierarchy will throw ClassCastException when you try to access a subclass property or do an instanceof check. I blogged already about the instanceof issue but it's actually wider ranging than I realised at the time. It can cause very unpredictable behaviour because complex relationships between objects and the way they are loaded by a controller before a page is rendered can cause this error to pop up under obscure conditions that are very hard to nail down with test coverage. To solve the problem we've had to use eager fetching in places where associations are typed as the base class of an inheritance hierarchy and to use explicit checks for proxies such as:

if (o instanceof HibernateProxy) {
o = GrailsHibernateUtil.unwrapProxy(o)
}

Hopefully this bug will be fixed in Grails 1.1.1 and we will be able to use the default lazy loading behaviour in all relationships.

Other problems we encountered included:

  • The onLoad Hibernate event handler on domain classes now seems to run at a slightly different time in the object life cycle: before any eager fetched collections are loaded. We had one domain class that was doing some initialisation (calculating the percentage of votes each answer to a poll had received and storing it in a transient property) that no longer worked as the persistent collection it was trying to iterate over was always empty. This was simple to refactor out and in fairness was pretty horrible anyway.

  • Config.groovy and related external config files are no longer loaded when running unit tests so any unit test that excercises code doing ConfigurationHolder.config.some.value.or.other blew up. We solved this by simply adding the following to _Events.groovy to load up config prior to the unit tests running:
    eventTestPhaseStart = { phase ->
    if (phase == 'unit') {
    ConfigSlurper slurper = new ConfigSlurper(GrailsUtil.environment)
    def configClass = getClass().classLoader.loadClass("Config")
    def config = slurper.parse(configClass)
    ConfigurationHelper.initConfig config // this step loads the external environment config file(s)
    ConfigurationHolder.config = config
    }
    }

  • Logger configuration has completely changed (for the better) in Grails 1.1

  • Some of our tests were explicitly setting the level of particular loggers to 'OFF' because the test is deliberately causing an error condition and we didn't want the console polluted with a huge stack trace. This no longer works as the logging abstraction has changed to SLF4J which does not allow you to directly set the level on its Logger class. Having better things to do than unwrapping logging abstractions I just turned logging off altogether in the test Grails environment.
    log4j = {
    root {
    off()
    }
    }

  • It looks like binding errors don't get reported on nullable properties when using DomainClass.properties = params in a controller. I've raised a bug.

  • There's been a minor change to the <g:select> tag. Previously the disabled attribute followed the HTML convention (disabled="disabled") but now the attribute value needs to be a boolean. I guess this actually makes more sense than the goofy HTML convention but I really expect most of the attributes on those sorts of tags to be pure pass-through.

  • The mockDomain method used by unit tests seems to be a little inconsistent when dealing with inheritance heirarchies. If you do mockDomain(BaseClass) then try to use subClassInstance.subClassProperty it fails with a MissingPropertyException. I've raised a bug.

  • We had customised Package.groovy to deploy our app at the root context. It seems this is now directly supported as an option in Grails 1.1 by setting grails.app.context = '/' in Config.groovy. I think this option was already available in Grails 1.0.3 but our patch pre-dated us upgrading to 1.0.3. One of the things I was trying to achieve while upgrading was to ensure we were patching Grails and any plugins as little as possible.

  • I'd upgraded our selenium plugin (not the one in the Grails plugin repository) a while back to cope with Grails 1.1 and upgraded the selenium server it contained at the same time. It turns out the new selenium server will time out attempting to click any anchor that uses the javascript: protocol in its href. Luckily this was only being done in 2 places in our app and was easily fixed by using href="#" instead.

One other thing we decided to do was to replace our existing suite of webtests with functional tests. Webtest has never been popular with the developers on our team and we had made a number of modifications to version 0.4 of the plugin in order to support issues like config loading and running the app at the context root of the server. These modifications caused some headaches when trying to upgrade the plugin so we decided to drop it and port the tests over to the functional test plugin. Generally I'd still rather be writing Selenium tests than using either webtest or functional tests but the functional test syntax is a little nicer and less "pseudo-XML" than webtest's.

15 Apr 2009

When is a Pirate not a Pirate? When it's a HibernateProxy

At work we're in the middle of upgrading the Sky Entertainment sites from Grails 1.0.3 to Grails 1.1 - a long blog post will follow with a tale of our woes! One of the changes in Grails 1.1 is that one-to-one domain associations are now lazy by default. This raised an interesting problem for us as it meant we were now sometimes dealing with HibernateProxy instances where before we weren't.

For example, let's imagine we have a Pet domain class that is has an owner that is a Person and there exists another domain class, Pirate that is a specialisation of Person:

Pet.groovy

class Pet {
String type
String name
Person owner
}

Person.groovy

class Person {

String name

boolean equals(Object o) {
if (this.is(o)) return true
if (o == null) return false
if (!(o instanceof Person)) return false
return name == o.name
}


// hashCode and toString ommitted
}

Pirate.groovy

class Pirate extends Person {

String nickname

boolean equals(Object o) {
if (!super.equals(o)) return false
if (!(o instanceof Pirate)) return false
return nickname == o.nickname
}

// hashCode and toString ommitted
}

We want to test that either a regular Person or a Pirate can own a Pet. To do so we write an integration test like this:

void testAssignPersonAsPetOwner() {
Person terry = new Person(name: 'Terry Elbow')
Pet rex = new Pet(type: 'Dog', name: 'Rex', owner: terry)
Pet.withSession {session ->
assert terry.save(flush: true)
assert rex.save(flush: true)
session.clear()
}
assertEquals(terry, Pet.findByName('Rex').owner)
}

void testAssignPirateAsPetOwner() {
Person longJohn = new Pirate(name: 'John Silver', nickname: 'Long John')
Pet capnFlint = new Pet(type: 'Parrot', name: "Cap'n Flint", owner: longJohn)
Pet.withSession {session ->
assert longJohn.save(flush: true)
assert capnFlint.save(flush: true)
session.clear()
}
assertEquals(longJohn, Pet.findByName("Cap'n Flint").owner)
}

Simple enough. In both cases we just create a Pet and its owner, ensure they save properly, then assert that the owner is correct when we read the Pet back from the database. However the second test, where we assign a Pirate as the owner, fails. The final assertion fails with the message:

expected:<Pirate[Long John]> but was:<Pirate[Long John]>

Great... what?

When we read the Pet instance back from the database the owner association is set to lazy load so Pet.findByName("Cap'n Flint").owner is a HibernateProxy. The failure is caused by the fact that as owner is declared as being of type Person the proxy generated extends Person and therefore the instanceof check in Pirate's equals method fails...

if (!(o instanceof Pirate)) return false

In our case o is an instance of Person and an instance of HibernateProxy which if loaded would yield an instance of Pirate but is not itself an instance of Pirate.

Our options at this point seem to be...

  1. Set owner to eager fetch.
  2. Remove the instanceof check from the equals implementation in Pirate
  3. Initialise the HibernateProxy so equals is working with the real object

The first option is just admitting defeat! Loading objects from the database when it's not necessary is wasteful and we don't want to go creating that kind of tech debt just to get our test working. The second option is not acceptable as it would mean the equals implementation on Pirate would violate the general contract of equals as aPerson == aPirate would return false but aPirate == aPerson would throw MissingPropertyException when it tried to execute the line:

return nickname == o.nickname

This leaves us with figuring out a way to initialise the proxy so we're always dealing with real objects. You may think it's an undesirable side-effect of the equals implementation to potentially force a database read but consider that it will do so anyway to perform the comparison of the nickname property.

There is a convenience initialize method in org.hibernate.Hibernate that can force a proxy to load, but it is void so our equals method would still have a reference to the HibernateProxy that is not actually an instance of Pirate. What we need to do is:

if (o instanceof org.hibernate.proxy.HibernateProxy) {
o = o.hibernateLazyInitializer.implementation
}
if (!(o instanceof Pirate)) return false

As it turns out we can't do this directly in the equals implementation. It appears that getAt(String) is overridden in HibernateProxy's meta class so we get the error:

No such property: hibernateLazyInitializer for class: Person_$$_javassist_0

As luck would have it Grails has a utility method for doing exactly what we want and as it's written in Java no amount of meta class trickery will hide the hibernateLazyInitializer property from it. Our final, working equals implementation for Pirate looks like:

boolean equals(Object o) {
if (!super.equals(o)) return false
if (o instanceof HibernateProxy) {
o = GrailsHibernateUtil.unwrapProxy(o)
}
if (!(o instanceof Pirate)) return false
return nickname == o.nickname
}

Note: this is a simple example so we'll gloss over the fact that Pirate's equals isn't symmetric as

new Person(name: 'X') == new Pirate(name: 'X', nickname: 'Y')

returns true while flipping the operands causes it to return false. The problem and the solution apply any time inheritance and lazy-loading run up against class checking whether via instanceof, Class.isAssignableFrom, switch statements using a Class as a case, etc.

2 Apr 2009

Grails 1.1 Plugins and IntelliJ Idea

Good news. The recent release of the IntelliJ Idea EAP has added proper handling of the new plugin installation system in Grails 1.1 - i.e. it automatically picks up your plugins installed under ~/.grails/1.1/projects/<name>/plugins.

1 Apr 2009

Querying By Association With Grails Criteria

A common requirement is to select all instances of a domain class where one of its many-to-many associations contains a particular instance of another domain class. Consider these domain classes where a Ship has a crew composed of Pirates and any particular Pirate can be a part of the crew of several Ships:

class Ship {
static hasMany = [crew: CrewMember]
String name
}

class CrewMember {
static belongsTo = [ship: Ship]
Pirate pirate
}

class Pirate {
String name
}

How can we use a criteria query to find all the Ship instances where a particular Pirate is a member of the crew? You might think it's pretty simple, surely:

Ship.withCriteria {
crew {
eq('pirate', blackbeard)
}
}

However, this has a curious side-effect. For example:

Ship.withSession {session ->
blackbeard = new Pirate(name: 'Blackbeard')
jack = new Pirate(name: 'Calico Jack')
bart = new Pirate(name: 'Black Bart')
[blackbeard, jack, bart]*.save()

def ship1 = new Ship(name: "Queen Anne's Revenge")
ship1.addToCrew new CrewMember(pirate: blackbeard)
ship1.addToCrew new CrewMember(pirate: jack)

def ship2 = new Ship(name: "Royal Fortune")
ship2.addToCrew new CrewMember(pirate: blackbeard)
ship2.addToCrew new CrewMember(pirate: bart)

def ship3 = new Ship(name: "The Treasure")
ship3.addToCrew new CrewMember(pirate: jack)
ship3.addToCrew new CrewMember(pirate: bart)

[ship1, ship2, ship3]*.save()

session.flush()
session.clear()
}

def blackbeardsShips = Ship.withCriteria {
crew {
eq('pirate', blackbeard)
}
}
blackbeardsShips.each {
println "$it.name: ${it.crew.pirate.name.join(', ')}"
}

You might expect the output to be:

Queen Anne's Revenge: Blackbeard, Calico Jack
Royal Fortune: Blackbeard, Black Bart

but it is actually:

Queen Anne's Revenge: Blackbeard
Royal Fortune: Blackbeard

The criteria query has restricted the content of the associations to only the ones matching the eq('pirate', blackbeard) criterion. This is quite a problem as it may well not be immediately obvious that it's happened and even using ships*.refresh() (which would be a horrible hack, especially if we were likely to get more than a couple of results) doesn't seem to restore the missing entries. I don't think there is any criterion that does a 'contains' type match for a persistent collection. My guess is this problem isn't a Grails thing but a Hibernate thing - Grails' HibernateCriteriaBuilder is a very thin layer over Hibernate itself.

In this example there is an alternative as the association is bi-directional. We can query from the other side of the association:

def blackbeardsShips = CrewMember.withCriteria {
projections {
property('ship')
}
eq('pirate', blackbeard)
}

If the association wasn't bidirectional this wouldn't be possible and we'd probably have to resort to using HQL to make the query exhibit the correct behaviour.

31 Mar 2009

Joda-Time and Grails Auto-Timestamping

The Joda-Time Plugin docs state that Grails' auto-timestamping works with Joda-Time properties which is the case. However, when testing it can be useful to take advantage of Joda Time's DateTimeUtils class to mock the current time. This enables you to have new DateTime objects, for example, use a predictable timestamp. Unfortunately it doesn't play nicely with Grails' auto-timestamping which under the covers uses System.currentTimeMillis(). There are a couple of solutions to this. You can disable the auto-timestamping and define your own beforeInsert event which enables you to use DateTimeUtils.setCurrentMillisFixed. For example:

static mapping = {
autoTimestamp false
}

def beforeInsert = {
dateCreated = new DateTime()
}

The other option would be to mock out the value returned by System.currentTimeMillis(). This has the advantage of meaning you don't have to add code to your domain class to enable tests to work, but on the other hand it's all to easy to have such meta class modifications leak from test to test by not being torn down properly.

On a related note the next release of the Joda-Time plugin will bind additional methods to DateTimeUtils to scope mocking of the current timestamp, for example:

DateTimeUtils.withCurrentMillisFixed(aLong) {
// do some stuff that requires a mocked current time
}

No more forgetting to call DateTimeUtils.setCurrentMillisSystem() in your tearDown method!

10 Mar 2009

Internationalizing Domain Classes and Enums

It's common to provide a toString implementation on a domain object that may well end up being used in the view. However, this doesn't allow for internationalization in the view. A good solution that I've used a number of times is to have classes implement Spring's MessageSourceResolvable interface. Consider this domain class that represents an image file:

grails-app/domain/Image.groovy

class Image {
    String name
    String path
    User uploadedBy
    org.joda.time.DateTime dateCreated

    static transients = ['file']
    File getFile() {
        new File(ConfigurationHolder.config.image.base.dir, path)
    }

    String toString() {
        "$name uploaded by $uploadedBy.username on $dateCreated - ${file.size()} bytes"
    }
}

The toString implementation is all well and good if we're targeting an English-speaking audience but with some simple changes we can make it i18n compliant:

grails-app/domain/Image.groovy

class Image implements org.springframework.context.MessageSourceResolvable {

    // properties as above

    static transients = ["codes", "arguments", "defaultMessage"]

    Object[] getArguments() {
        [name, uploadedBy.username, dateCreated.toDate(), file.size()] as Object[]
    }

    String[] getCodes() {
        ['image.info'] as String[]
    }

    String getDefaultMessage() {
        "$name uploaded by $uploadedBy.username on $dateCreated - ${file.size()} bytes"
    }
}

In our message properties file we can add:

grails-app/i18n/messages.properties

image.info={0} uploaded by {1} on {2,date} - ${3,number,integer} bytes

In the view we can display our object like this:

<g:message error="${imageInstance}"/>

Yes, that is the error attribute we're passing to the message tag! Grails intends the attribute to be used for outputting validation errors but the underlying mechanism is the same - Spring's ObjectError implements MessageSourceResolvable and that's how Grails' message tag resolves the displayed error message. Rather than passing separate code, args and default attributes to the tag we can pass the single MessageSourceResolvable instance and its implementation will take care of supplying those values.

Note: I added a message attribute to the message tag to avoid the confusion caused by using error. This is in Grails from version 1.2-M1 onwards.

We can now add translations of our object description. For example:

grails-app/i18n/messages_af.properties

image.info={0} opgelaai deur {1} op {2,date} - ${3,number,integer} grepe

It's worth noting that the format of the dateCreated property will be automatically determined by the request locale so the value will be formatted correctly for the user.

I've found this technique can also be very useful on enum classes. For example:

src/groovy/com/mycompany/Season.groovy

package com.mycompany

enum Season implements org.springframework.context.MessageSourceResolvable {
    SPRING, SUMMER, AUTUMN, WINTER

    Object[] getArguments() { [] as Object[] }

    String[] getCodes() {
        ["${getClass().name}.${name()}"] as String[]
    }

    String getDefaultMessage() { name() }
}

grails-app/i18n/messages.properties

com.mycompany.Season.SPRING=Spring
com.mycompany.Season.SUMMER=Summer
com.mycompany.Season.AUTUMN=Autumn
com.mycompany.Season.WINTER=Winter

grails-app/i18n/messages_en_US.properties

com.mycompany.Season.AUTUMN=Fall

3 Mar 2009

Persisting DateTime with zone information

I was stuck a while ago trying to figure out how to map PersistentDateTimeTZ in a GORM class. It's an implementation of Hibernate's UserType interface that persists a Joda DateTime value using 2 columns - one for the actual timestamp and one for the time zone. The DateTime class contains time zone information but a SQL timestamp column is time zone agnostic so you can lose data when the value is saved (the same exact problem exists when persisting java.util.Date values).

I could never figure out how to map the user type to my domain class property correctly. Just doing:

static mapping = {
dateTimeProperty type: PersistentDateTimeTZ
}

Failed with:

org.hibernate.MappingException: property mapping has wrong number of columns.

I seem to remember someone on the Grails mailing list suggesting I tried treating the value as an embedded type. That also didn't work as GORM embedded types have to be Groovy classes in grails-app/domain and PersistentDateTimeTZ is written in Java and lives in a library jar.

I finally found the solution in the 2nd Edition of The Definitive Guide to Grails (which I can't recommend enough, by the way). The trick is to pass a closure specifying the two columns to the property definition in the mapping builder. The working code looks like this:

static mapping = {
dateTimeProperty type: PersistentDateTimeTZ, {
column name: "date_time_property_timestamp"
column name: "date_time_property_zone"
}
}

The order of the columns corresponds to the order of the values returned by the sqlTypes() method of whatever UserType implementation you're using.

2 Mar 2009

Why would I ever want to disable the L2 cache?

This question came up when pairing last week. We were going through our code-base adding the cache directive to a bunch of our domain classes. Grails is all about sensible defaults and it seems slightly odd that the level 2 cache is configured by default in DataSource.groovy but not actually used unless cache(true) is added to the mapping closure in each domain class. I wonder if anyone has any ideas why it might ever be a bad idea to use the L2 cache?

The only scenario I can come up with is situations where updates are made direct to the DB, bypassing Hibernate. This is, I would think, pretty rare (we do it for some rather naïve hit tracking and for voting on polls). Sure, in this circumstance the L2 cache will likely give you stale results. However, it's very much the exception rather than the rule.

Most other objections I've heard have been some variety of worry about caches eating up vast amounts of heap space and crashing the JVM (which is why cache implementations like ehcache use time-based and LRU eviction).

Oh, and yeah, we did have some issues with our changes but most seem to be to do with cruft and tech debt in our code (mostly now-redundant workarounds to GORM issues from older releases of Grails).

1 Mar 2009

Hibernate POGOs, Immutability and Encapsulation

I had a confusing experience this morning. I'm working on a simple web based game as a learning exercise.

I use a custom tag to determine if the currently logged in user is the active player (i.e. the player whose turn it is).

  <g:isNextPlayer>
<!-- display something only active player should see -->
</g:isNextPlayer>

The tag is used at various places in the page - displaying an "it's your turn" message, switching on bits of script, rendering buttons, etc. Suddenly I found the last couple of calls to the tag in a page weren't rendering the tag body.

The tag uses a transient property on the Game domain class that looks like this:

  Player getNextPlayer() {
return players.empty ? null : players[turn % players.size()]
}

The variable turn is simply an integer that gets incremented when a turn completes.

After poking around with debug logging I figured out that the implementation of getNextPlayer was fine and the value of turn wasn't being accidentally changed but the collection property players was getting re-ordered. What I'd done was introduce some code mid-way in the page that displays the players' names and scores - ordered by score.

  <g:each var="player" in="${gameInstance.players.sort { -it.score }}">
<tr>
<td>${player.user.username}</td>
<td>${player.score}</td>
</tr>
</g:each>

I had assumed when I did this that Collection.sort(Closure) would return a copy (which is what the docs state - not that I'd checked). However, it seems that is only the case if the collection it's called on is not a List. On List instances the method acts as a mutator and does an in-place sort.

  def c = [1,2,3] as Set
def s = c.sort { it }
assert !(c.is(s))

Remove the 'as Set' and the assertion fails.

Although I'd argue that Groovy's sort implementation doesn't exactly stick to the principal of least surprise that's not really what concerns me. In my domain it doesn't make sense for me to be able to mutate the players property of Game. Once a game is created the players are fixed, they can't leave, can't take turns out of order. The state of an individual Player can change - his score can change, for example, but not the collection property of Game. In a regular non-persistent class this sort of invariant would be enforced by overriding the getter and setter:

  private List players
List getPlayers() { players.asImmutable() }
void setPlayers(List players) {
this.players = []
this.players.addAll players
}

If my Game class was implemented that way I'd have got an UnsupportedOperationException from the sort call. If nothing else it would have saved me 5 minutes of "WTF?" and 10 minutes of trying to figure out if it was something to do with the second-level cache. Unfortunately, this technique doesn't quite work satisfactorily in a GORM domain class though. For a start declaring the property as private will result in a compilation failure - 'The field 'players' is declared multiple times.' Declaring the property without private gets you past the compilation phase but Grails 'addTo*' dynamic method isn't bound.

One of the things that's always nagged at the back of my mind when using GORM/Hibernate is the fact that all to often the domain classes end up resembling the anæmic domain model anti-pattern even to the extent of a design something like the cautionary tale of POTS. I like to put a certain amount of business logic in my domain classes and give them a reasonably rich API for managing their state without violating encapsulation but there's always an uncomfortable feeling that properties that really should be part of an object's private state are hanging out in the wind so that the persistence framework can access them.

12 Feb 2009

Watchmen Widget