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.

8 comments:

  1. Hi Do you know how to set an external value to one of these scope? Eg: In my jsp form I have a field which is not bound to a model and I cannot send that as a URL parameter with the flowExecutionURL how do I just pass such value from JSP and access it from Spring Web Flow? Really appreciate your comment about this.

    Please refer the following stackoverflow question which I didn't get any answer yet.

    http://stackoverflow.com/questions/18138648/post-values-from-jsp-to-spring-web-flow-without-using-model-or-url

    ReplyDelete
  2. Can you try using a bean to get the field's value from HttpRequest and store it into those scopes?

    ReplyDelete
  3. Thanks for the quick response. How do I access the HTTPRequest and set the value to the scope..? could you please provide me an example.
    Thanks again

    ReplyDelete

  4. something like





    class Bean{
    public String setParam(ParameterMap map, MutableAttributeMap flowAttributes){
    String address = map.get("address");
    flowAttributes.setAttribute("address", address);
    }
    }

    FYI: I never tested the code. Just give you some idea.

    BTW: have you looked at this?
    http://stackoverflow.com/questions/5484136/spring-webflow-how-to-get-request-parameters-in-jsp

    ReplyDelete
  5. view-state id="view" model="personModel" view="personView"
    evaluate expression="bean.setParam(externalContext.requestParameterMap) result="flashSceop.address"/
    /view-state

    ReplyDelete
  6. Sorry, bean class should be like this:

    class Bean{
    public String setParam(ParameterMap map){
    return map.get("address");
    }
    }

    ReplyDelete
  7. "Delving into the intricacies of Spring Webflow, the trio of Request, Flash, and View Scope opens up a world of possibilities for managing data and navigation seamlessly. These scopes play a pivotal role in shaping the flow of information throughout the application, providing developers with the flexibility needed to create dynamic and responsive web experiences. A must-explore feature set for anyone navigating the Spring Webflow framework!

    ReplyDelete