Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Struts Wiki" for change 
notification.

The following page has been changed by MichaelJouravlev:
http://wiki.apache.org/struts/RolloverScope

The comment on the change is:
Added use cases and code samples

------------------------------------------------------------------------------
  
  Because of issues related to using session, many developers abstain from 
using it, and prefer fighting with double submit problems and POSTDATA messages 
instead. They rarely split input and render tasks into two actions; when they 
do, they use in-server forwarding instead of redirection, because request 
object does not survive between requests. This is unfortunate because 
Redirect-After-Post pattern is a simple and proven solution for creating 
user-friendly and error-resistant interfaces.
  
- Starting from Struts 1.4 it will be possible to store data related to a 
multi-request conversation in the Rollover Scope.
+ Starting from Struts 1.4 it will be possible to store a multi-request 
conversation data in the Rollover Scope.
  
  inline:rollover.gif
  
  == Rollover scope in a nutshell ==
  
- Physically, a rollover scope is a map stored within session scope. One 
session object can store several associated rollover scopes.
+ A rollover scope is essentially a map stored within session scope. One 
session object can store several associated rollover scopes.
  
  Rollover scope can be used in the following ways:
   * Directly from application code by calling methods of RolloverScope class. 
[not tested]
@@ -45, +45 @@

  
  == Using rollover scope to store an action form ==
  
- In a Struts application a rollover scope can be used in action mapping 
definition just as request and session scopes. To declare a rollover scope for 
an action form specify {{{scope="rollover"}}} in action mapping definition. 
Below is an example of a standard redirect-after-post pattern: one mapping for 
submitting user data from browser, another mapping for rendering a web page. A 
rollover scope is used to store form bean in between requests. The input action 
inherits from !EventDispatchAction and is used as event processor. Render 
action uses login/logout state to render an appropriate view.
+ In a Struts application a rollover scope can be used in action mapping 
definition just as request and session scopes. To declare a rollover scope for 
an action form specify {{{scope="rollover"}}} in action mapping definition. 
Below are examples of a standard redirect-after-post pattern: one mapping for 
submitting user data from browser, another mapping for rendering a web page. A 
rollover scope is used to store form bean in between requests. 
  
- Events are defined in 'parameter' attribute (see !EventDispatchAction for 
details). Notice that 'scope' has 'rollover' value. A removal strategy of with 
lifetime of one request is defined for rollover scope - perfect for most 
redirect-after-post use cases. 
+ === Rollover-scoped action form, example 1 ===
  
- Besides automatic removal based on removal strategy, a rollover scope can be 
removed based on action outcome. In the sample below, if an input action 
chooses 'cancel' or 'userhome' outcomes, then rollover scope is removed when 
action finishes.
+ This is the simplest way of configuring the rollover scope: just declaring 
the scope as "rollover". The input action inherits from !EventDispatchAction 
and is used as event processor. Events are defined in 'parameter' attribute 
(see !EventDispatchAction for details). Notice that 'scope' has 'rollover' 
value. A removal strategy of with lifetime of one request is defined for 
rollover scope - perfect for most redirect-after-post use cases. Render action 
uses login/logout state to render an appropriate view.
  
+ By default, removal strategy is by request count, and maximum lifetime is one 
request. This means, that when you navigate from this action, the "loginform" 
action form will mature, and on a next request it will be removed from session.
+ 
+ {{{<action path = "/logininputaction"
+         type = "org.apache.struts.samples.login.LoginInputAction"
+         name = "loginform"
+         scope = "rollover"
+         validate = "false"
+         parameter = 
"initEvent=init,loginEvent=login,cancelEvent=cancel,logoutEvent=logout">
+ 
+         <forward name = "render" path = "/loginrenderaction.do" redirect = 
"true"/>
+         <forward name = "userhome" path = "/userhome.do" redirect = "true"/>
+         <forward name = "cancel" path = "/main.do" redirect = "true"/>
+ </action>
+ 
- {{{<action path = "/logininputaction"
+ <action path = "/loginrenderaction"
-         type = "org.apache.struts.samples.login.LoginInputAction"
+         type = "org.apache.struts.samples.login.LoginRenderAction"
          name = "loginform"
          scope = "rollover"
-         validate = "false"
+         validate  = "false">
+ 
+         <forward name = "notloggedin" path = 
"/logindialog/logincomponent-login.jsp"/>
+         <forward name = "loggedin" path = 
"/logindialog/logincomponent-logout.jsp"/>
+ </action>}}}
+ 
+ === Rollover-scoped action form, example 2 ===
+ 
+ This is more complex example which defines the removal strategy and limit 
explicitly using action mapping properties. Properly "rolloverStrategy" 
specifies strategy by timout, and property "rolloverLimit" specifies maximum 
lifetime of the idle rollover scope - 3 minutes.
+ 
+ {{{<action path = "/logininputaction"
+         type = "org.apache.struts.samples.login.LoginInputAction"
+         name = "loginform"
+         scope = "rollover"
+         validate = "false"
          parameter = 
"initEvent=init,loginEvent=login,cancelEvent=cancel,logoutEvent=logout">
+ 
+         <set-property key="rolloverStrategy" value="timeout" />
+         <set-property key="rolloverLimit" value="3" />
+ 
+         <forward name = "render" path = "/loginrenderaction.do" redirect = 
"true"/>
+         <forward name = "userhome" path = "/userhome.do" redirect = "true"/>
+         <forward name = "cancel" path = "/main.do" redirect = "true"/>
+ </action>
+ 
+ <action path = "/loginrenderaction"
+         type = "org.apache.struts.samples.login.LoginRenderAction"
+         name = "loginform"
+         scope = "rollover"
+         validate  = "false">
  
          <set-property key="rolloverStrategy" value="rcount" />
          <set-property key="rolloverLimit" value="1" />
+ 
+         <forward name = "notloggedin" path = 
"/logindialog/logincomponent-login.jsp"/>
+         <forward name = "loggedin" path = 
"/logindialog/logincomponent-logout.jsp"/>
+ </action>}}}
+ 
+ === Rollover-scoped action form, example 3 ===
+ 
+ In addition to explicit removal strategy (by request, maximum lifetime is 5 
requests to a session), this configuration specifies conditions for immediate 
removal of the rollover scope. They are defined with "rolloverRelease" 
property, which contains action outcomes for which the rollover scope should be 
deallocated. In the sample below, if the input action chooses 'cancel' or 
'userhome' outcomes, then rollover scope is removed when action finishes. If 
the render action displays user info page a.k.a. logout page, then rollover 
scope is not needed either.
+ 
+ {{{<action path = "/logininputaction"
+         type = "org.apache.struts.samples.login.LoginInputAction"
+         name = "loginform"
+         scope = "rollover"
+         validate = "false"
+         parameter = 
"initEvent=init,loginEvent=login,cancelEvent=cancel,logoutEvent=logout">
+ 
+         <set-property key="rolloverStrategy" value="rcount" />
+         <set-property key="rolloverLimit" value="5" />
          <set-property key="rolloverRelease" value="cancel,userhome" />
  
          <forward name = "render" path = "/loginrenderaction.do" redirect = 
"true"/>
@@ -74, +134 @@

          validate  = "false">
  
          <set-property key="rolloverStrategy" value="rcount" />
-         <set-property key="rolloverLimit" value="1" />
+         <set-property key="rolloverLimit" value="5" />
          <set-property key="rolloverRelease" value="loggedin" />
  
          <forward name = "notloggedin" path = 
"/logindialog/logincomponent-login.jsp"/>
          <forward name = "loggedin" path = 
"/logindialog/logincomponent-logout.jsp"/>
  </action>}}}
+ 
+ === Rollover-scoped action form, example 4 ===
+ 
+ In previous samples the rollover scope was not given name explicitly, so 
action form name was used as rollover scope name: "loginform". It is possible 
to give an explicit name to the rollover scope, using "rolloverId" property, 
for example:
+ 
+ {{{<action path = "/logininputaction"
+         type = "org.apache.struts.samples.login.LoginInputAction"
+         name = "loginform"
+         scope = "rollover"
+         validate = "false"
+         parameter = 
"initEvent=init,loginEvent=login,cancelEvent=cancel,logoutEvent=logout">
+ 
+         <set-property key="rolloverId" value="MyLoginRollover" />
+ 
+         <forward name = "render" path = "/loginrenderaction.do" redirect = 
"true"/>
+         <forward name = "userhome" path = "/userhome.do" redirect = "true"/>
+         <forward name = "cancel" path = "/main.do" redirect = "true"/>
+ </action>
+ 
+ <action path = "/loginrenderaction"
+         type = "org.apache.struts.samples.login.LoginRenderAction"
+         name = "loginform"
+         scope = "rollover"
+         validate  = "false">
+ 
+         <set-property key="rolloverId" value="MyLoginRollover" />
+ 
+         <forward name = "notloggedin" path = 
"/logindialog/logincomponent-login.jsp"/>
+         <forward name = "loggedin" path = 
"/logindialog/logincomponent-logout.jsp"/>
+ </action>}}}
+ 
+ === Rollover-scoped action form, example 5 ===
+ 
+ It is possible to have several instances of rollover scope per action. 
Consider a typical CRUD application, it displays a list of customer orders. 
Every order line contains !View and !Edit links. If you click on !Edit link, 
then an order edit form is displayed. To select a specific order, an order id 
is passed to the server as HTTP parameter. Say, you want to open several order 
forms in different windows. You would like to right-click the !Edit link and 
select "Open in separate browser window". This would be hard to do with saving 
state in the session, but is easy with rollover scope.
+ 
+ All you need to do is to define your !Edit link so that it contained 
parameter with the same name as value of "rolloverId" parameter. The value of 
this HTTP parameter will be concatenated with base rollover id to form a 
complete name. This is easier to show with code sample. 
+ 
+ {{{<action path = "/orderinputaction"
+         type = "org.apache.struts.samples.OrderInputAction"
+         name = "orderform"
+         scope = "rollover"
+         validate = "false"
+         parameter = "editEvent=edit,viewEvent=view>
+ 
+         <set-property key="rolloverId" value="orderId" />
+ 
+         <forward name = "render" path = "/orderrenderaction.do" redirect = 
"true"/>
+         <forward name = "cancel" path = "/orderlist.do" redirect = "true"/>
+ </action>
+ 
+ {{{<action path = "/orderrenderaction"
+         type = "org.apache.struts.samples.OrderRenderAction"
+         name = "orderform"
+         scope = "rollover"
+         validate  = "false">
+ 
+         <set-property key="rolloverId" value="orderId" />
+ 
+         <forward name = "edit" path = "/order/editorder.jsp"/>
+ </action>}}}
+ 
+ The mapping above is similar to mapping in Example 4. Now the crucial part: 
the Edit links. They may look like this: 
+ 
+ {{{
+ orderrenderaction?itemId=1701
+ }}}
+ 
+ When this request is submitted, rollover scope manager will look up 
"rolloverId" property in the action mapping, it has value "orderId". Then it 
will look up "orderId" request parameter and read its value, it is "1701". Then 
it will concatenate parameter name and value, producing "orderId1701", this 
will be the name of rollover scope for order 1701.
+ 
+ As you see, for this particular use case the natural ID makes a perfect 
rollover scope name. For other use cases you may need to create artificial IDs.
  
  == Changes to Struts core classes ==
  Several core classes have been updated to accommodate usage of rollover 
scope. Two new commands have been added to default chain.

Reply via email to