GORM Gotchas (Part 3)

Peter Ledbrook

It's great to hear that people are finding these articles useful, so it's with great pleasure that I add another to the series. This time I'm going to talk about associations again, but with the focus on when they are loaded into memory.

It's cool to be lazy

One of the first things people learn about GORM relationships is that they are loaded lazily by default. In other words, when you fetch a domain instance from the database, none of its relations will be loaded. Instead, GORM will only load a relation when you actually use it.

Let's make this a bit more concrete by considering the example from the previous article:

class Location {
    String city
}

class Book {
    String title

    static constraints = {
        title(blank: false)
    }
}

class Author {
    String name
    Location location

    static hasMany = [ books: Book ]
}

If we fetch an Author instance, the only information we can use without another query being executed is the author's name. When we try to get the associated location or the books, more queries are kicked off to get the extra data we need.

This is really the only sensible default option, particularly with complex models that have long chains of associations. If eager fetching were the default, you could feasibly end up pulling in half the data from the database simply by fetching a single instance.

Nonetheless, this option is not without cost. I'll look at three side-effects of lazy associations so that you know what they are, can recognise the symptoms, and can fix any problems resulting from those side-effects.

Proxies

Lazy loading of associations involves some magic. After all, you don't want the location property above to return null, do you? So Hibernate uses proxies and custom collection classes to provide transparent access to the lazy-loaded collections and associations – you don't have to worry about the fact they're not in memory yet. Normally these proxies do a great job of hiding the work that goes on behind the scenes, but occasionally the implementation leaks through.

As an example, consider this domain model:

class Pet {
    String name
}

class Dog extends Pet {
}

It's a very simple inheritance hierarchy, so you wouldn't expect any nasty surprises. Now imagine that we have a Dog instance in the database with an ID of 1. What do you think will happen with the following code?

def pet = Pet.load(1)
assert pet instanceof Dog

Intuitively, this should work. After all, the pet with ID 1 is a Dog. So why does the assertion fail? Instead of fetching the underlying instance from the database, the load() method returns a proxy that executes the required query on demand, for example when you try to access a property other than id. This proxy is a dynamic subclass of Pet rather than Dog so the instanceof check fails. It continues to fail even after the instance is loaded from the database! In diagrammatic form:

Changing Pet.load() to Dog.load() will fix the problem, since the proxy will then be a dynamic subclass of Dog. You can also make it work by relacing load() with get(), because the implementation of the latter automatically unwraps the proxy and returns the underlying Dog instance. In fact, Grails works hard to perform this automatic unwrapping in many other situations, so you're unlikely to come across the issue. That's one of the reasons it comes as such as surprise when you do.

There is one other scenario that may cause some heartache, although it should be fairly rare. Imagine you have another class, Person, that has a relationship to Pet like so:

class Person {
    String name
    Pet pet
}

The pet relationship is lazy, so when you get the Person instance, the pet property will be a proxy. Normally this is hidden from you by GORM, but check out the behaviour of the following:

def p = Person.get(1)
assert p.pet instanceof Dog
assert Pet.get(1) instanceof Dog
assert Pet.findById(1) instanceof Dog
assert Pet.list()[0] instanceof Dog

Assuming that we have one Person instance and one Pet instance that's a Dog, and assuming that the two are related via the pet property, the first three assertions will succeed but the last one will not. Get rid of the other lines of code and suddenly that assertion will succeed. Huh?

This behaviour is undoubtedly confusing, but its roots lie in the Hibernate session. When you retrieve the Person from the database, its pet property is a proxy. That proxy is stored in the session and represents the Pet instance with ID 1. Now, the Hibernate session guarantees that no matter how many times you retrieve a particular domain instance from within a single session, Hibernate will return you the exact same object. So when we call Pet.get(1), Hibernate gives us the proxy. The reason the corresponding assertion succeeds is that GORM automatically unwraps the proxy. The same happens for findBy*() and any other queries that can only return a single instance.

However, GORM does not unwrap proxies for the results of list(), findAllBy*(), and other queries that can return multiple results. So Pet.list()[0] returns us the unwrapped proxy instance. If the Person isn't fetched first, Pet.list() will return the real instances: the proxy isn't in the session this time, so the query isn't obliged to return it.

You can protect yourself against this problem in a couple of ways. First, you can use the dynamic instanceOf() method instead of the instanceof operator. It's available on all GORM domain instances and is proxy-aware: Pet.get(1).instanceOf(Dog). Second, declare variables using def rather than static domain class types, otherwise you may see class cast exceptions. So, rather than

Person p = Person.get(1)
Dog dog = Pet.list()[0]    // Throws ClassCastException!

use

def p = Person.get(1)
def dog = Pet.list()[0]

With this approach, you will still be able to access any properties or methods that are specific to Dog, even though you're working with a proxy.

It has to be said, GORM does an amazing job of shielding developers from proxies. They only rarely leak through to your application code, particularly with more recent versions of Grails. Still, some people will run into issues with them so it's useful to be aware what the symptoms are and why they occur.

I showed in the last example how the behaviour of the session combined with lazy loading can produce some interesting results. That combination also lies behind a more common error: the org.hibernate.LazyInitializationException.

Lazy loading and the session

As I've already mentioned, when you have a lazily loaded relationship Hibernate has to execute an extra query if you then want to navigate that relationship at a later date. In the normal course of events this isn't a problem (unless you're worried about performance) since Hibernate does it transparently. But what happens if you try to access the relationship in a different session?

Let's say you have loaded the Author instance with ID 1 in a controller action and stored it in the HTTP session. At this point, no code has touched the books collection. On the next request, the user goes to a URL that corresponds to this controller action:

class MyController {
    def index = {
        if (session.author) {
            render "Author ${session.author.name} has written the books: ${session.author.books*.title}"
        else {
            render "No author in session"
        }
    }
    ...
}

The intention here is that if our HTTP session contains an author variable, the action renders the titles of that author's books. Except in this case it doesn't. It throws a LazyInitializationException instead.

The problem is that the Author instance is what we call a detached object. It was loaded in one Hibernate session, but then that session was closed at the end of the request. Once an object's session is closed, it becomes detached and you cannot access any properties on it that will result in a query.

"But a session is open in my action, so why the problem?" I hear you cry. That's a good question. Unfortunately, this is a new Hibernate session and it doesn't know anything about our Author instance. Only when the object is explicitly attached to the new session will you be able to access its lazy associations. There are several techniques for doing just that:

def author = session.author

// Re-attach object to session, but don't sync the data with the database.
author.attach()

// Re-attach object, but merge any changes with the data in the database.
// You *must* use the instance returned by the merge() method.
author = author.merge()

The attach() method is useful in cases where the domain instance is unlikely to have changed in the database since the detached object was retrieved. If that data may have changed, then you'll have to be careful. Check the Grails reference guide for information on the behaviour of merge() and refresh().

Now If you get a LazyInitializationException, you'll know that it's because your domain object is not attached to a Hibernate session. You'll also have a good idea of how to resolve the issue, although I'll introduce another approach to solving the problem soon. Before I get to that, I want to have a look at another classic side effect of lazy initialisation: the N + 1 select problem.

N + 1 selects

Let's go back to the author/book/location example from earlier in the article. Imagine we have four authors in the database and we run the following code:

Author.list().each { author ->
    println author.location.city
}

How many queries will be executed? The answer is five: one to get all the authors, and then one per author to retrieve the corresponding location. This is known as the N + 1 select problem and it's very easy to write code that suffers from it. The example above certainly looks harmless enough at first glance.

During development this isn't really a problem, but executing so many queries will harm the responsiveness of your application when it's deployed to production. Because of this, it's a good idea to analyse the database usage for your application before it's opened up to end users. The simplest approach is to enable Hibernate logging in grails-app/conf/DataSource.groovy, which ensures that all queries are logged to stdout:

dataSource {
    ...
    loggingSql = true
}

You can of course enable it on a per-environment basis. An alternative approach is to use a special database driver like P6Spy that intercepts the queries and logs them.

So how do you avoid these extra queries? By fetching associations eagerly rather than lazily. This approach also solves the other issues related to lazy loading that I've mentioned.

Being eager

GORM allows you to override the default lazy loading behaviour on a per-relationship basis. For example, we can configure GORM to always load an author's location along with the author via this mapping:

class Author {
    String name
    Location location

    static hasMany = [ books: Book ]

    static mapping = {
        location fetch: 'join'
    }
}

In this case, not only is the location loaded with the author, but it's retrieved in the same query using a SQL join. So this code:

Author.list().each { a ->
    println a.location.city
}

will only result in a single query. You can also use the lazy: false option in place of fetch: 'join' but that will result in an extra query to load the location. In other words, the association is loaded eagerly, but with a separate SQL select. Most of the time you'll probably want to use fetch: 'join' to minimise the number of queries that are executed, but sometimes it can be the more expensive approach. It really depends on your model.

There are other options, but I won't go into them here. They are fully documented in sections 5.3.4 and 5.5.2.8 of the Grails user guide if you want to know more (although I would wait for the 1.3.4 release of Grails, which will come with some important documentation updates).

The downside to configuring eager loading in the domain class mapping is that the association will always be loaded eagerly. But what if you only need that information occasionally? Any page that just wants to display an author's name will be slowed down unnecessarily because the location must also be loaded. The cost may be low for a simple association like this, but it will be greater for collections. That's why you also have the option to eagerly load associations on a per-query basis.

Queries are context sensitive, so they're the ideal place to specify whether particular associations should be eagerly loaded or not. Let's say we've reverted to the default behaviour for Author and now we want to get all authors and display their cities. In this context, we obviously want to retrieve the locations when we get the authors. Here's how:

Author.list(fetch: [location: 'join']).each { a ->
    println a.location.city
}

All we've done is add a fetch argument to the query with a map of association names -> fetch modes. If the code also displayed the titles of the authors' books, we'd add the books association to the map too. The dynamic finders support the exact same fetch option:

Author.findAllByNameLike("John%", [ sort: 'name', order: 'asc', fetch: [location: 'join'] ]).each { a->
    ...
}

We can also achieve the same thing with criteria queries:

def authors = Author.withCriteria {
    like("name", "John%")
    join "location"
    join "books"
}

That's all there is to it. The main effort goes into profiling an application's database access to determine where associations should be fetched with a join.

Wrapping up

As you've seen, lazy loading of associations raises a variety of issues, particularly when combined with the Hibernate session. Despite those issues, lazy loading is an important feature that remains a sensible default for object graphs. The problems that tend to crop up are easily identified once you know about them and are typically easy to solve too. And if nothing springs to mind, you can always fall back to judicious use of eager loading.

All that said, as the Grails version number has gone up, users have progressively become less and less likely to come across these issues. When you consider what's happening behind the scenes with Hibernate, that's a pretty impressive trick!

Spring MVC 3 Showcase

Keith Donald

Since the big Spring 3 release last year, I've been working on a number of application development projects and extracting "showcases" of various framework features. These "showcases" are not reference applications or tutorials, they're more like acceptance tests for specific framework capabilities. After seeing a showcase, you should have a good idea of what the technology can do.

The first showcase I've put together is for Spring MVC 3, our web framework. It includes a sample project, along with a supporting slide presentation and screencast. After digging in, you should have a good understanding of what Spring MVC can do and get a feel for how easy it is to use.

mvc-showcase

In this showcase you'll see the following in action:

  • The simplest possible @Controller
  • Mapping Requests
  • Obtaining Request Data
  • Generating Responses
  • Message Converters
  • Rendering Views
  • Type Conversion
  • Validation
  • Forms
  • File Upload
  • Exception Handling

I use jQuery to drive feature illustration by applying progressive Ajax techniques. I highly recommend using Firebug or equivalent to gain insight into the client/server interactions. I find it very educational to inspect the request and response details from the client-side, then jump to the code that executed on the server-side.

Get the code by checking out the mvc-showcase project from our spring-samples repository. Simply import the project into STS and drag-n-drop the project onto the "SpringSource tc Server Developer Edition" Server to run.

View the supporting slide show:

Spring MVC 3 Showcase Slideshow

See the showcase live in this 8 minute screencast:

Spring MVC 3 Showcase Screencast

The mvc-showcase screencast contains music by the band The Smashing Pumpkins. The mvc-showcase screencast is not affiliated with or endorsed by The Smashing Pumpkins. All audio in the screencast is licensed for non-profit use per the terms and conditions of the live music archive at archive.org.

Summary

I hope you find mvc-showcase useful and discover some "hidden gems" you might not have known about before. Please let me know also if you'd like to contribute your own additions. mvc-showcase covers a lot of ground today, but there's always opportunity to cover more!

Grails tooling improvements in SpringSource Tool Suite 2.3.3 M2

aclement

The recently released STS 2.3.3 M2 introduced a series of enhancements to our Grails support for Eclipse. In this article I'll be discussing what you can expect to find if you try it out (grab it here: SpringSource Tool Suite).

Groovy-Eclipse

The grails tools actually build on and extend the Groovy-Eclipse support, which is developed by the same team at SpringSource. Earlier this year the Groovy-Eclipse tools won 'Best Open Source Developer Productivity Tool' at Eclipse-Con 2010. You can read more about the latest enhancements in the recent Groovy-Eclipse 2.0.2 release here: New and Noteworthy. I'm not going to focus on Groovy-Eclipse here, but some highlights from that release were:

  • refactoring support: now supporting extract method, extract constant, extract local variable
  • improvements in code formatting and indentation

Now, onto Grails!

Getting a new perspective

There is now a new Grails perspective to better organize the views and widgets we have been adding to STS. You can open the perspective in the normal way (Window>OpenPerspective>Grails). In the new perspective the first thing to notice is that the Eclipse project explorer is open, rather than the package explorer. The project explorer is using a custom content provider that shows a view of a grails project that should be more familiar to a grails developer:


Grails Perspective

New labels and icons are in place for the groups of similar entities: domain objects, controllers, views, etc. However the biggest change is the new plugins folder. Previously when working with a grails project the plugin dependencies were tricky to see in the UI, being hidden in the classpath container and via some Eclipse linked source folder entries. Now in the project explorer it is much more obvious what the application dependencies are.

Also, related to plugins, we have a new Grails Plugin Project wizard. This is very similar to the Grails Project Wizard, but instead of running create-app, it will cause the create-plugin command to run. With this new wizard and the new support we have for local (inplace) plugins, it is much easier to develop your application following a plugin oriented architecture.

Here is an example using a local/inplace plugin configuration:


InplacePlugins

In that shot you can see two Eclipse projects. The main grails application 'MyFirstGrailsApp' and a plugin project 'MyFirstGrailsPlugin'. By editing the BuildConfig.groovy in the main application a dependency has been expressed onto the plugin project:

grails.plugin.location.MyFirstGrailsPlugin="../MyFirstGrailsPlugin"

After specifying that dependency and running a 'Refresh Dependencies' against the application, the 'plugins' folder has updated (see the above screenshot) with a new entry for my new dependency and a different kind of icon which indicates that it is a different kind of plugin dependency.

In Command

For enabling users to be more productive, the command prompt has been enhanced. It now allows project selection, and can be pinned in place (so it isn't accidentally closed), but most importantly it now has a history function. The history enables you to quickly re-run the same command or run similar commands. For accessing the prompt you can use the same 'claw' keypress (Alt+Shift+Ctrl+G on my windows machine), or if your hand doesn't bend that way you can use the new grails icon on the grails perspective toolbar to launch it. The pulldown next to the grails icon provides another route to accessing the command history, showing the commands and the project against which they were run:

history

Selecting any entry in the pulldown history will open the prompt with that command pre-filled, it can be edited prior to execution or simply re-run. If the prompt is open then the other route to accessing the history is simply to press Up-Arrow:

grailsprompt

To speed up navigation around your applications, STS now includes a number of new keyboard shortcuts for grails projects. When in a controller, service, taglib or domain class, you can use Alt+G then one of D, C, S, T to jump to the related domain class/controller/service/taglib in the editor. Jumping is also possible by clicking the new icons on the toolbar:
jumping

Managing plugins

To make it easier to organize the plugins a project is using we have a new grails plugin manager. Rather than trying to remember the name of the plugin you want, you can open up the manager (through the context menu RightClick>Grails Tools>Grails Plugin Manager..., or via keypress Alt+G,M) and browse the available plugins:

GrailsPluginManager

The plugin manager enables you to:

  • install new plugins
  • update existing plugins
  • uninstall plugins

It also provides the detailed descriptions and any available links to documentation.

The list of available plugins is cached but you can press Refresh to ensure you are working with the latest list. By default the manager is showing you all available plugins, but as you scroll down you will see what you already have installed (installed plugins have a green tick against them). Importantly if any of the installed plugins have had an update released, the UI will indicate that to you and you can update if you wish (a blue up-arrow icon indicates an update is available). Due to the act of installing/uninstalling a plugin not being instantaneous (it takes a few moments for grails to actually do it), as you interact with the UI and mark plugins for install/update/etc you are basically scheduling a series of grails commands to run. The changes you have requested won't actually execute until you press the OK button to close the manager. If at any time you think you've messed up you can cancel the manager (or reset the manager) and your project will be in its original state.

GSPs

As well as many minor fixes, gsp editing has been improved by the addition of code assist for taglibs:

gsptags

Here you can see I have a new taglib called TextInserter defining a tag alphabet, in the gsp editor I can code complete on that tag. (following the current model for jsp editing, the code assist Ctrl+Space must be performed prior to typing).

Dynamic finders

This doesn't really fit into the sections above but is a nice improvement. The groovy editor will now recognize the usage of dynamic finders and provide them in code assist:

dynamicfinders

Here you can see against my Song object (which only has a title and duration) any attempt to use invalid finders is marked with underlining in the editor, and code assist is providing the valid choices.

That's it! Quite a lot of change for STS M2 – go and grab a copy now and try it out: SpringSource Tool Suite

Any feedback is appreciated. Improvements to debugging is something we are going to be looking at in the near term, but if you wish to raise new requirements on comment on existing issues, please see the STS issue tracker.

Latest comments across all posts

Recent Team Posts

Ben Alex

post Spring Roo 1.1.0.M2 Released

I'm pleased to announce we've just released Spring Roo 1.1.0.M2 (download here). We've also concurrently released SpringSource Tool Suite 2.3.3.M2, which offers the latest integration with this new Spring Roo release. For production use we recommend you continue to use Spring Roo 1.0.2, although we know a very large number of people are happily using [...]


Jeremy Grelle

post Introducing the Flex Addon for Spring Roo

Recently we released the first milestone of the Flex Addon for Spring Roo as a part of the Spring BlazeDS Integration 1.5.0.M1 distribution. This addon aims to bring the productivity and usability benefits of Spring Roo to the development of Spring-based RIAs with Flex. The below 15 minute screencast (split into two parts) serves as [...]


Glyn Normington

post 5x startup performance boost in Virgo milestone M02

Virgo 2.1.0.M02-incubator is available for download. Apart from completing the "getting started guide", this milestone dramatically reduces startup time – by as much as 5x on some systems. This should be a further incentive for users of dm Server to migrate to Virgo: Virgo is the codebase for future development, has more liberal licensing, and [...]

Older Posts

GORM Gotchas (Part 2)

First Eclipse Gemini Blueprint Milestone Ships

STS on Eclipse 3.6

First Eclipse Gemini Web Milestone Ships