Fork me on GitHub

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.