Scope Basics

You'll notice from previous examples that we used a special object called flow to store objects within "flow scope". Grails flows have 5 different scopes you can utilize:

Grails service classes can be automatically scoped to a web flow scope. See the documentation on Services for more information.

Also returning a model map from an action will automatically result in the model being placed in flow scope. For example, using a transition action, you can place objects within flow scope as follows:

enterPersonalDetails {
   on("submit") {
         [person:new Person(params)]
   }.to "enterShipping"
   on("return").to "showCart"
}

Be aware that a new request is always created for each state, so an object placed in request scope in an action state (for example) will not be available in a subsequent view state. Use one of the other scopes to pass objects from one state to another. Also note that Web Flow:

  1. Moves objects from flash scope to request scope upon transition between states;
  2. Merges objects from the flow and conversation scopes into the view model before rendering (so you shouldn't include a scope prefix when referencing these objects within a view, e.g. GSP pages).

Flow Scopes and Serialization

When placing objects in flash, flow or conversation scope they must implement java.io.Serializable otherwise you will get an error. This has an impact on domain classes in that domain classes are typically placed within a scope so that they can be rendered in a view. For example consider the following domain class:

class Book {
	String title
}

In order to place an instance of the Book class in a flow scope you will need to modify it as follows:

class Book implements Serializable {
	String title
}

This also impacts associations and closures you declare within a domain class. For example consider this:

class Book implements Serializable {
	String title
	Author author
}

Here if the Author association is not Serializable you will also get an error. This also impacts closures used in GORM events such as onLoad, onSave and so on. The following domain class will cause an error if an instance is placed in a flow scope:

class Book implements Serializable {
	String title
	def onLoad = {
		println "I'm loading"
	}
}

The reason is that the assigned block on the onLoad event cannot be serialized. To get around this you should declare all events as transient:

class Book implements Serializable {
	String title
	transient onLoad = {
		println "I'm loading"
	}
}