7.5.4 Flow Scopes 2.3.8

See the light - agile, industrial strength, rapid web application development made easy

(Quick Reference) # 7.5.4 Flow Scopes - Reference Documentation Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari Version: 2.3.8 ## 7.5.4 Flow Scopes #### 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 five different scopes you can utilize: `request` - Stores an object for the scope of the current request `flash` - Stores the object for the current and next request only `flow` - Stores objects for the scope of the flow, removing them when the flow reaches an end state `conversation` - Stores objects for the scope of the conversation including the root flow and nested subflows `session` - Stores objects in the user's session Grails service classes can be automatically scoped to a web flow scope. See the documentation on Services for more information. 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: Moves objects from flash scope to request scope upon transition between states; 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` or an exception will be thrown. 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
    }
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"
        }
    }
or as methods:

    class Book implements Serializable {    String title    def onLoad() {
            println "I'm loading"
        }
    }
> The flow scope contains a reference to the Hibernate session. As a result, any object loaded into the session through a GORM query will also be in the flow and will need to implement Serializable. If you don't want your domain class to be Serializable or stored in the flow, then you will need to evict the entity manually before the end of the state:
>     flow.persistenceContext.evict(it)
| Quick Reference (hide)