Monday 22 October 2012

Request, Flash, View Scope in Spring webflow


What is the difference among these 3 scopes?

According to the Java doc:

Request: Attributes placed in request scope exist for the life of the current request into the flow execution. When the request ends any attributes in request scope go out of scope.

Flash: Attributes placed in flash scope exist through the life of the current request and until the next view rendering. After the view renders, flash scope is cleared. Flash scope is typically used to store messages that should be preserved until after the next view renders.

View: Attributes placed in view scope exist through the life of the current view state and until the view state exits in a subsequent request. View scope is typically used to store view model objects manipulated over a series of Ajax requests.

I don't think I can see their distinction clearly from the definitions above. So I am going to run some experiments to find out myself.

In the spring-web-flow.xml, I create a <view-state>.

<view-state id="dummy">
    <on-entry>
        <set name="viewScope.viewScopeAttribute" value="'v'" />
        <set name="flashScope.flashScopeAttribute" value="'f'" />
        <set name="requestScope.requestScopeAttribute" value="'r'" />
    </on-entry>
</view-state>

the dummy.xhtml JSF page is very simple:

request scope: #{requestScopeAttribute}
flash scope: #{flashScopeAttribute}
view scope: #{viewScopeAttribute}

I was expecting to see all 3 attributes displayed, but the request scope attribute is missing.

Let's change the <view-state> to

<view-state id="dummy">
    <on-render>
        <set name="viewScope.viewScopeAttribute" value="'v'" />
        <set name="flashScope.flashScopeAttribute" value="'f'" />
        <set name="requestScope.requestScopeAttribute" value="'r'" />
    </on-render>
</view-state>

All 3 attributes display this time. why?

This is because every time Spring webflow needs to render a view, it will issue a redirect causing the view to be rendered in the subsequent GET request. This is useful because when the user hit Refresh or Back button, the browser won't give any warning.

The actions in <on-entry> occur during the first request and any attributes in this request's scope will have been blown off by the time the view is rendered. Because the view is rendered in the second request.

The actions in <on-render> occur during the second request, so the attributes in this request's scope will be kept when the view is rendered.

As for the difference between viewScope and flashScope, I really cannot tell any as long as they are in <view-state>.  I think they can be used interchangeably in <view-state>. (I could be very wrong here).

However, viewScope cannot be used in <action-state> or <decision-state>.

flashScope will retain in memory until after the view is rendered. For example:

<action-state id="dummy0">
    <on-entry>
        <set name="flashScope.flashScopeAttribute" value="'f'" />
    </on-entry>
    <evaluate expression="new java.lang.String()" />
    <transition to="dummy"/>
</action-state>
 
<view-state id="dummy" /> 

The flash scope attribute still displays on the page.