CSC/ECE 517 Fall 2009/wiki2 3 pp: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
=<font color="windowtext">Implementations of the pattern provided by various frameworks</font>=
=<font color="windowtext">Research in refactoring tools</font>=


The basic idea of Synchronizer Token is to set a token in a session variable before returning a transactional page to the client. This page carries the token inside a hidden field. Upon submission, request processing first tests for the presence of a valid token in the request parameter by comparing it with the one registered in the session. If the token is valid, processing can continue normally, otherwise an alternate course of action is taken. After testing, the token resets to null to prevent subsequent submissions until a new token is saved in the session, which must be done at the appropriate time based on the desired application flow of control. This section will describe how the built in support for synchronizer token is provided by various frameworks.


==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Struts</font></span></span>==
Struts provides built in mechanism for handling tokens in '''<font color="black">[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html org.apache.struts.action.Action] class using </font>'''<span class="apple-style-span"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;">the</font></font></span><span class="apple-converted-space"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;"> </font></font></span><span class="apple-style-span">''<font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;">[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#saveToken(javax.servlet.http.HttpServletRequest) saveToken()]</font></font>''</span><span class="apple-converted-space"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;"> </font></font></span><span class="apple-style-span"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;">and [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) i''sTokenValid()'']</font></font></span><span class="apple-converted-space"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;"> </font></font></span><span class="apple-style-span"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;">methods</font></font>. ''[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#saveToken(javax.servlet.http.HttpServletRequest) saveToken()]''</span><span class="apple-converted-space"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;"> </font></font></span><span class="apple-style-span"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;">method creates a token (a unique string) and saves that in the user's current session, while ''[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()]''</font></font></span><span class="apple-converted-space"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;"> </font></font></span><span class="apple-style-span"><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;">checks if the token stored in the user's current session is the same as that was passed as the request parameter.</font></font></span><font color="black"><font face="&quot;Verdana&quot;,&quot;sans-serif&quot;"><br />
<br />
<span class="apple-style-span">To do this the JSP has to be loaded through an [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action]. Before loading the JSP call</span><span class="apple-converted-space"> </span><span class="apple-style-span">''[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#saveToken(javax.servlet.http.HttpServletRequest) saveToken()]''</span><span class="apple-converted-space">'' ''</span><span class="apple-style-span">to save the token in the user session. When the form is submitted, check the token against that in the session by calling ''[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()]'', as shown in the following code snippet:</span></font></font>


<font color="black"> </font>
=<font color="windowtext">Introduction</font>=


<div style="mso-element: para-border-div; border: solid black 1.0pt; mso-border-alt: solid black .75pt; padding: 8.0pt 8.0pt 8.0pt 8.0pt; background: #EEEEEE; margin-left: 7.5pt; margin-right: 7.5pt">


<font color="#666666">public<span style="mso-spacerun: yes">  </span>class PurchaseOrderAction extends DispatchAction {<br />
<span style="mso-spacerun: yes">  </span>public ActionForward load(ActionMapping mapping,<br />
<span style="mso-spacerun: yes">  </span><span style="mso-spacerun: yes">                          </span>ActionForm form,<br />
<span style="mso-spacerun: yes">  </span><span style="mso-spacerun: yes">                          </span>HttpServletRequest<span style="mso-spacerun: yes">  </span>request,<br />
<span style="mso-spacerun: yes">  </span><span style="mso-spacerun: yes">                          </span>HttpServletResponse response) throws Exception</font>


<font color="#666666"><span style="mso-spacerun: yes">  </span>{<br />
=<font color="windowtext">Improvements in the Refactoring Tools</font>=
<span style="mso-spacerun: yes">  </span><span style="mso-spacerun: yes">  </span>try {<br />
<span style="mso-spacerun: yes"> </span><span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes"> </span>//save the token<br />
<span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes">  </span>saveToken(request)<br />
<span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes">  </span>// rest of the code for loading the form<br />
<span style="mso-spacerun: yes">    </span><span style="mso-spacerun: yes">  </span>} catch(Exception ex){//exception}<br />
<span style="mso-spacerun: yes">  </span>}<br style="mso-special-character: line-break" />
<br style="mso-special-character: line-break" />
</font>


<font color="#666666"><span style="mso-spacerun: yes">  </span>public ActionForward submitOrder(ActionMapping mapping,<br />
<span style="mso-spacerun: yes">                                </span>ActionForm form,<br />
<span style="mso-spacerun: yes">                                </span>HttpServletRequest<span style="mso-spacerun: yes">  </span>request,<br />
<span style="mso-spacerun: yes">                                </span>HttpServletResponse response) throws Exception </font>


<font color="#666666"><span style="mso-spacerun: yes">   </span>{<br />
=<font color="windowtext">Academic underpinnings</font>=
<span style="mso-spacerun: yes">    </span><span style="mso-spacerun: yes">  </span>try {<br />
<span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes">    </span>// check the token. Proceed only if token is valid<br />
<span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes"> </span><span style="mso-spacerun: yes">  </span>if(isTokenValid(request,true)) {<br />
<span style="mso-spacerun: yes">          </span><span style="mso-spacerun: yes">  </span>//implement order submit functionality here<br />
<span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes">  </span>} else {<br />
<span style="mso-spacerun: yes">          </span><span style="mso-spacerun: yes">  </span>return mapping.findForward("failure");<br />
<span style="mso-spacerun: yes">      </span><span style="mso-spacerun: yes">  </span>}<br />
<span style="mso-spacerun: yes">    </span><span style="mso-spacerun: yes">  </span>} catch(Exception ex){//exception}<br />
<span style="mso-spacerun: yes">  </span>}<br />
}</font>


</div>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Extract Method</font></span></span>==


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt"> </font></font></font>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Code cloning and detection</font></span></span>==


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">This actually what is happening behind the scene in the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action] class. </font></font></font>


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">[http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#saveToken(javax.servlet.http.HttpServletRequest) saveToken()] has logic as below:</font></font></font>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Refactoring Annotations</font></span></span>==


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">[http://java.sun.com/products/servlet/2.2/javadoc/javax/servlet/http/HttpSession.html HttpSession] session = request.getSession();<span class="apple-converted-space"> </span><br /> String token = generateToken(request);<span class="apple-converted-space"> </span><br /> if (token != null) {<span class="apple-converted-space"> </span><br /><span style="mso-spacerun: yes">    </span>session.setAttribute([http://struts.apache.org/1.1/api/org/apache/struts/Globals.html#TRANSACTION_TOKEN_KEY Globals.TRANSACTION_TOKEN_KEY], token);<span class="apple-converted-space"> </span><br /> }</font></font></font>


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt"> </font></font></font>
=<font color="windowtext">Ongoing and Future Research</font>=
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Binary Refactoring</font></span></span>==


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">The method generates a random token using session id, current time and a [http://java.sun.com/j2se/1.4.2/docs/api/java/security/MessageDigest.html MessageDigest] and stores it in the session using a key name [http://struts.apache.org/1.1/api/constant-values.html org.apache.struts.action.TOKEN] (This is the value of the static variable [http://struts.apache.org/1.1/api/org/apache/struts/Globals.html#TRANSACTION_TOKEN_KEY TRANSACTION_TOKEN_KEY] in [http://struts.apache.org/1.1/api/org/apache/struts/Globals.html org.apache.struts.Globals] class). </font></font></font>


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">The [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action] class that renders the form (</font></font></font><font color="#666666">PurchaseOrderAction.load</font><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">) invokes the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#saveToken(javax.servlet.http.HttpServletRequest) saveToken()] method to create a session attribute with the above name. In the JSP, the token needs to be as a hidden form field as follows:</font></font></font>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Refactoring Functional Programs</font></span></span>==


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt"><input type="hidden"<span class="apple-converted-space"> </span><br /> name="<%=[http://struts.apache.org/1.x/struts-taglib/apidocs/org/apache/struts/taglib/html/Constants.html#TOKEN_KEY org.apache.struts.taglib.html.Constants.TOKEN_KEY]%>"<span class="apple-converted-space"> </span><br /> value="<bean:write name="<%=[http://struts.apache.org/1.1/api/org/apache/struts/Globals.html#TRANSACTION_TOKEN_KEY Globals.TRANSACTION_TOKEN_KEY]%>"/>"></font></font></font>


<font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">The embedded [http://struts.apache.org/1.2.x/userGuide/struts-bean.html#write <bean:write>] tag shown above, looks for a bean named [http://struts.apache.org/1.1/api/constant-values.html org.apache.struts.action.TOKEN] (which is the value of [http://struts.apache.org/1.1/api/org/apache/struts/Globals.html#TRANSACTION_TOKEN_KEY Globals.TRANSACTION_TOKEN_KEY]) in session scope and renders its value as the value attribute of the hidden input variable. The name of the hidden input variable is [http://struts.apache.org/1.x/struts-taglib/apidocs/constant-values.html org.apache.struts.taglib.html.TOKEN] (This is nothing but the value of the static variable [http://struts.apache.org/1.x/struts-taglib/apidocs/org/apache/struts/taglib/html/Constants.html#TOKEN_KEY TOKEN_KEY] in the class [http://struts.apache.org/1.x/struts-taglib/apidocs/org/apache/struts/taglib/html/Constants.html org.apache.struts.taglib.html.Constants]).</font></font></font>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Language Independent Refactoring</font></span></span>==


<span class="apple-style-span"><span style="line-height: 115%"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt"></font></font></font></span>When the client submits the form, the hidden field is also submitted. In the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action] that handles the form submission i.e. </span><font color="#666666">PurchaseOrderAction.submitOrder </font><span class="apple-style-span"><span style="line-height: 115%"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt"><span style="mso-spacerun: yes"> </span>(which most likely is different from the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action] that rendered the form), the token in the form submission is compared with the token in the session by using the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()] method. The method compares the two tokens and returns a true if both are same. Be sure to pass reset=”true” in the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()] method to clear the token from session after comparison. If the two tokens are equal, the form was submitted for the first time. However, if the two tokens do not match or if there is no token in the session, then it is a duplicate submission and handle it in the manner</font></font></font></span></span><span class="apple-converted-space"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"> </font></font></span><span style="line-height: 115%"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt"><br /><span class="apple-style-span">acceptable to your users.</span></font></font></font></span>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Use Case Refactoring</font></span></span>==


<span class="apple-style-span"><span style="line-height: 115%"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">Although the above approach is good, it requires application developer to add the token checking method pair – [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#saveToken(javax.servlet.http.HttpServletRequest) saveToken()] and [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()] in methods rendering and submitting the sensitive forms respectively. Since the two tasks are generally performed by two different [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action]s, the pairs need to be identified and added manually.</font></font></font></span></span>
==<span class="apple-style-span"><span style="mso-bidi-font-size: 12.0pt; line-height: 115%"><font color="windowtext">Hardware Refactoring</font></span></span>==
=<font color="windowtext">References</font>=


<span class="apple-style-span"><span style="line-height: 115%"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">If the form is spanned across the multiple pages, then every time the form is submitted before going from one page to another. You definitely want to validate token on every page submission. However you also want to allow the user to traverse back and forth using the browser back button until the point of final submission. If the token is reset on every page submission, the possibility of back and forth traversal using the browser button is ruled out. The solution is not disabling back button (using [http://en.wikipedia.org/wiki/JavaScript JavaScript] hacks) but to handle the token intelligently. This is where the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) reset parameter] is useful. The token is initially set before showing the first page of the form. The [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) reset parameter] is</font></font></font></span></span><span class="apple-converted-space"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"> </font></font></span><span class="apple-style-span"><span style="line-height: 115%"><font color="navy"><font face="&quot;Arial&quot;,&quot;sans-serif&quot;"><font size="10.0pt">false for all the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()] invocations except in the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html Action] for the last page. The last page uses a true value for the reset argument and hence the token is reset in the [http://struts.apache.org/1.x/apidocs/org/apache/struts/action/Action.html#isTokenValid(javax.servlet.http.HttpServletRequest, boolean) isTokenValid()] method. From this point onwards you cannot use back button to traverse to the earlier form pages and successfully submit the form.</font></font></font></span></span>
<font face="&quot;Times New Roman&quot;,&quot;serif&quot;"><font size="12.0pt"> </font></font>


5.2 <span style="mso-spacerun: yes"> </span>Spring Web Flow
[1] [http://portal.acm.org/citation.cfm?id=1176617.1176705&coll=ACM&dl=ACM&CFID=113271&CFTOKEN=65759170 Improving usability of refactoring tools] Emerson Murphy-Hill, October 2006, ACM
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Spring Web Flow was specifically designed to help developers implement complex conversations in web applications. <span style="mso-spacerun: yes"> </span>As a controller component in the MVC triad, Spring Web Flow integrates into hosting web MVC frameworks, serving as an application controller, handling screen navigation, and coordinating the flow of a business process</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Spring Web Flow captures business processes or conversations in modules called flows. A </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">flow </font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">is a blueprint for the interaction a user can have with a web application; it reacts to user events to drive the process to completion. You can look at a flow as a simple manifestation of a finite state machine (FSM), consisting of a number of states that define the activities to execute while progressing through the flow. A state can allow a user to participate in the flow, or it can call business services. The flow can move from one state to another using transitions triggered by events.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">As you have seen, business processes are commonly defined using UML state diagrams, and Spring Web Flow flow definitions use a similar model. The following screenshot shows a Spring Web Flow flow definition that mirrors the process definition in Figure</font></font></span><nowiki>:</nowiki>
 
<span style="mso-no-proof: yes">[[Image:image002.gif]]</span><span style="mso-spacerun: yes"> </span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Given the navigational rules set out in a flow definition, Spring Web Flow automatically takes care of navigational control. Using web continuations, Spring Web Flow can guarantee stable, predictable behavior of a web application even when the user uses the browser’s Back, Forward, or Refresh buttons; revisits bookmarked pages; or opens multiple windows in the same conversation. The POST-REDIRECT-GET idiom will also be automatically applied, without any need for developer intervention.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Typically, a web flow will define a process spanning multiple requests into the web application. While completing the process, the user interacts with the application through several different pages, accumulating data along the way. It is the responsibility of a </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">flow execution repository </font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">to maintain all data associated with a flow execution in between separate requests participating in that flow execution.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The flow-execution–related data that needs to be maintained consists of two types of information, both contained in a </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">object:</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">Application data</font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"><nowiki>: Application data can be in any of the flow execution scopes: flash, flow, and conversation. Note that the request scope is not stored, because it is tied to a single request into the flow execution and does not need to be maintained across individual requests.</nowiki></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">Housekeeping data</font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"><nowiki>: Mostly technical in nature, this data might include the currently active flow session in the flow execution and the current state.</nowiki></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">To properly maintain this information throughout the flow execution and across request boundaries, Spring Web Flow will store a flow execution in a repository when one request ends, restoring it on the next request that comes in for that flow execution. Spring Web Flow will identify the flow execution in which a particular request participates by looking at the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">_flowExecutionKey </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">request parameter.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">interface captures these core responsibilities,</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-no-proof: yes">[[Image:image004.jpg]]</span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">Line 5</font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"><nowiki>: To adequately manage flow executions, a flow execution repository needs to assign a unique key to each flow execution. Using </nowiki></font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">generateKey(flowExecution)</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">, a new </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutionKey </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">will be generated for a freshly launched flow execution. When an existing flow execution, with a key already assigned, needs to be persisted again, </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">getNextKey(flowExecution, previousKey) </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">generates the next key to use. This implies that a new key can be obtained every time a flow execution needs to be stored in a repository, allowing the repository to potentially change the key every time. </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutionKey </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">objects can be marshaled into a string form using their </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">toString() </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">method. This string form will be embedded in HTML pages and later travels back to the server using the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">_flowExecutionKey </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">request parameter. Using </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">parseFlowExecutionKey(encodedKey)</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">, you can unmarshal a string form of a flow execution key back into its object form.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">Line 12</font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"><nowiki>: To make sure all access to a flow execution object occurs in an orderly fashion, a flow execution repository provides a </nowiki></font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutionLock</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">. A flow execution needs to be locked before it is manipulated and unlocked afterward to ensure that all processing done by a flow execution is serialized: the next request is only processed when the previous one completed processing.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">Line 15</font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"><nowiki>: Finally, the </nowiki></font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">interface provides methods to store </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">objects in the repository (</font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">putFlowExecution(key, flowExecution)</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">), obtain them from the repository <span style="mso-spacerun: yes"> </span></font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">getFlowExecution(key)</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">), or remove them from the repository (</font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">removeFlowExecution(key)</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">). Before using any of these methods, the flow execution needs to be locked in the repository.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Spring Web Flow provides multiple types of repository implementations. An appropriate implementation can be chosen by using:</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="simple"/></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">In above example simple repository will be used.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">When using classic Spring bean definitions instead of the Spring Web Flow configuration schema, set the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">repositoryType </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">property to value </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">SIMPLE</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"><nowiki>:</nowiki></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><bean id="flowExecutor" class="org.springframework.webflow.config.FlowExecutorFactoryBean"></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><property name="definitionLocator" ref="flowRegistry"/></font></font></span>
 
'''<span style="mso-bidi-font-family: TheSansMonoConSemiLightBold"><font face="TheSansMonoConSemiLightBold"><font size="9.5pt"><property name="repositoryType" value="SIMPLE"</font></font></span>'''<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">/></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"></bean></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
'''<span style="mso-bidi-font-family: Utopia-Semibold"><font face="Utopia-Semibold"><font size="13.0pt">The Simple Repository</font></font></span>'''
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The simplest </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">implementation shipped with Spring Web Flow is, not surprisingly, called </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">SimpleFlowExecutionRepository</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">. It manages a single snapshot of an ongoing flow execution, guarding access to the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">object using the flow execution key. Figure illustrates this algorithm.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular; mso-no-proof: yes"><font face="Utopia-Regular"><font size="9.5pt">[[Image:image006.jpg]]</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">This results in a situation very similar to the use of a synchronizer token. The simple repository guards access to the flow execution by changing the flow execution key for every request. In other words, the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">getNextKey(flowExecution, previousKey) </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">method always returns a new key, different from the previous key. This ensures that a stale request, resulting from the user using the browser navigational aides (for instance, the Back button), can no longer access the flow execution. The end result is that use of the Back button or the browser history is completely disallowed. A user who tries to go back will receive an error stating that doing so is not allowed. The same is true, of course, when the conversation ends (because the flow reached an end state). At that point, Spring Web Flow will clean up all conversational state, preventing a user from resuming the terminated conversation or causing a double submits.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: HelveticaNeue-MediumCond"><font face="HelveticaNeue-MediumCond">Simple Repository Pros and Cons</font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The most important benefit of using the simple repository is that it only maintains a single copy of the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">data. These results in very low memory requirements, making this repository type ideal for environments where memory resources are scarce or load requirements are very high.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">As a downside, the simple repository does not support use of the browser Back button or navigation history and generates an exception if Back button usage is detected. This kind of strict no-Back-button policy enforcement is typically not suited for Internet facing applications. It can be ideal, however, in intranet settings, where you might be able to deploy a custom browser that can completely disable the browser navigational aids.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
'''<span style="mso-bidi-font-family: Utopia-Semibold"><font face="Utopia-Semibold"><font size="13.0pt">The Single Key Repository</font></font></span>'''
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The single key repository is a variation on the simple repository. Essentially, the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">SimpleFlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">will be configured to keep the flow execution key constant for the entire flow execution. Instead of changing the flow execution key on every request, as done by the simple repository, the single key repository maintains a single key for every flow execution. As a result, the single key repository allows use of the Back button. It does not really </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">support </font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">use of the Back button, however, since it maintains only a single snapshot of the flow execution (just like the simple repository).</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">When single key repository is used in combination with “always redirect on pause”, all pages of the flow will appear to have been served from exactly the same URL. The reason for this is the redirect Spring Web Flow issues before rendering a view. This redirect causes a flow execution refresh (that is, a </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">flow execution redirect</font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">). Since the flow execution key remains constant for the entire flow execution when using the single key repository, all pages of the flow will appear to have been served from a URL like this:</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">http://server/springbank/flows.html?_flowExecutionKey=ABCXYZ</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The cool thing here is that the browser will not notice that you are actually navigating from one page to another, because every page of the flow has exactly the same URL. The end result is that the browser does not build up a navigation history, making the Back button useless. If you click the Back button, you end up on the last page before the flow execution started! </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Just like all other repository implementations, the single key repository will also remove a flow execution when it ends. This prevents a user from jumping back into a terminated conversation or causing a double submit.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: HelveticaNeue-MediumCond"><font face="HelveticaNeue-MediumCond">Single Key Repository Pros and Cons</font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">Just like the simple repository, the single key repository has the important benefit of using very little memory (since it only stores a single flow execution snapshot). This makes it ideal for high-load or low-memory environments.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">While the simple repository completely disallows use of the Back button, the single key repository tricks the browser into not accumulating any browsing history </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">inside </font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">the flow execution. This makes going back in the flow using the Back button impossible. This compromise, unlike the strict rules enforced by the simple repository, is typically acceptable for Internet applications.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
'''<span style="mso-bidi-font-family: Utopia-Semibold"><font face="Utopia-Semibold"><font size="13.0pt">The Continuation Repository</font></font></span>'''
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The most powerful flow execution repository provided by Spring Web Flow is the continuation repository, implemented by the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">ContinuationFlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">class. As the name suggests, the continuation repository manages flow executions using a </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">web continuations </font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">algorithm. Web continuations are an elegant way to deal with complex navigation in web applications. They allow web applications to respond correctly if the user uses the browser Back button or navigation history or even if the user opens multiple windows on a single conversation. Spring Web Flow’s continuation repository will use such web continuations to allow the application to behave correctly when the user opens multiple windows on a single flow execution or uses the browser’s Back button. Essentially, the continuation repository will take a snapshot of the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution s</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">object at the end of every request that comes into the flow execution. In other words, the “game” is saved at the end of every request. Each continuation snapshot has a unique ID, which is part of the flow execution key. When a request comes in, Spring Web Flow restores the flow execution from the identified continuation snapshot and continues processing. Below figure shows this graphically. </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular; mso-no-proof: yes"><font face="Utopia-Regular"><font size="9.5pt">[[Image:image008.jpg]]</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"></font></font></span>
 
'''<span style="mso-bidi-font-family: HelveticaNeue-BoldCond"><font face="HelveticaNeue-BoldCond"><font size="9.0pt">1. </font></font></span>'''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The first request that comes into the flow executor does not contain a flow execution key. As a result, the flow executor launches a new flow execution for this simple three-state flow. The flow progresses from the first state to the second state, a view state, and pauses. Before control is returned to the browser, the flow execution repository takes a snapshot of the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">and assigns it a unique key. This key is embedded in the rendered view to make sure a next request can submit it again. At the end of the first request, the continuation repository contains a flow execution continuation snapshot, </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">snapshot1</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">, indexed by </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">key1</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">.</font></font></span>
 
'''<span style="mso-bidi-font-family: HelveticaNeue-BoldCond"><font face="HelveticaNeue-BoldCond"><font size="9.0pt">2. </font></font></span>'''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The second request coming into the flow contains </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">key1 </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">as a flow execution key. In response to this request, the flow executor restores the flow execution from the identified continuation, </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">snapshot1</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">. The flow resumes processing, moves to the third state, and pauses. At this point, the flow execution repository takes another snapshot of the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">and assigns it a new unique key, which is embedded in the rendered view.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The second request caused a second continuation snapshot, </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">snapshot2</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">, to be stored in the repository, indexed using </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">key2</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">. Notice that the first snapshot is still there. This allows the user to click the Back button, jumping back to the previous request (request two), and continue from that point onward. Opening a new browser window on the same conversation would allow the user to continue from the current snapshot (</font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">snapshot2</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">) independently in each window.</font></font></span>
 
'''<span style="mso-bidi-font-family: HelveticaNeue-BoldCond"><font face="HelveticaNeue-BoldCond"><font size="9.0pt">3. </font></font></span>'''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The third request continues from the continuation identified using </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">key2</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">. In this case, the flow resumes processing and terminates by reaching an end state. As a consequence, the flow execution, and all its continuation snapshots, will be removed from the repository. This prevents double submits, even when using web continuations: if the user clicks the Back button to go back to request two, an error will be produced because the identified continuation snapshot (</font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">snapshot2</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">) is no longer available. It was cleaned up along with all other snapshots when the third request terminated the overall conversation. To be able to associate continuation snapshots with the governing </font></font></span>''<span style="mso-bidi-font-family: Utopia-Italic"><font face="Utopia-Italic"><font size="9.5pt">logical </font></font></span>''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">conversation, Spring Web Flow needs to track both a continuation snapshot ID and the unique ID of the overall conversation. Both of these IDs are embedded in the flow execution key, which consists of two parts: </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">flows.htm?_flowExecutionKey=_c<conversation id>_k<continuation id></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"> </font></font></span>
 
'''<span style="mso-bidi-font-family: HelveticaNeue-BoldCond"><font face="HelveticaNeue-BoldCond"><font size="9.0pt">4. </font></font></span>'''<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The conversation ID is prefixed using </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">_c</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">, followed by the continuation ID prefixed with </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">_k</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">. The conversation ID always remains constant throughout a conversation, while the continuation ID changes on every request.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The continuation repository is the default repository in Spring Web Flow. You can explicitly configure a flow executor to use the continuation repository by specifying </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">continuation </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">as repository type (or </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">CONTINUATION </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">when using the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecutorFactoryBean</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">). The continuation repository has one additional property that can be configured: the maximum number of continuation snapshots allowed per conversation. Using a first-in-first-out algorithm, the oldest snapshot will be thrown away when a new one needs to be taken and the maximum has been reached. Here is a configuration example:</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><flow:executor id="flowExecutor" registry-ref="flowRegistry"></font></font></span>
 
'''<span style="mso-bidi-font-family: TheSansMonoConSemiLightBold"><font face="TheSansMonoConSemiLightBold"><font size="9.5pt"><flow:repository type="continuation" max-continuations="5"/></font></font></span>'''
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"></flow:executor></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The same configuration using classic Spring bean definitions follows:</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><bean id="flowExecutor"</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">class="org.springframework.webflow.config.FlowExecutorFactoryBean"></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><property name="repositoryType" value="CONTINUATION"/></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><property name="maxContinuations" value="5"/></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"></bean></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">By default, a maximum of 30 continuation snapshots per conversation are maintained. In practice, this is equivalent with an unlimited number of snapshots, since it allows a user to backtrack 30 steps in the browsing history—more than any normal user would ever do. Constraining the number of continuation snapshots is important to prevent an attacker from doing a denial of service attack by generating a large amount of snapshots.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: HelveticaNeue-MediumCond"><font face="HelveticaNeue-MediumCond">Continuation Repository Pros and Cons</font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The continuation repository allows you to have completely controlled navigation, while still allowing the user to use all of the browser navigational aides. This promise is a very compelling indeed and is the reason why this is the default repository used by Spring Web Flow.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The most important downside of the continuation repository is the increased memory usage caused by the multiple continuation snapshots that are potentially maintained for each flow execution. By appropriately configuring the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">maxContinuations </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">property, you can control this, however, making the continuation repository ideal for most web applications.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
'''<span style="mso-bidi-font-family: Utopia-Semibold"><font face="Utopia-Semibold"><font size="13.0pt">The Client Continuation Repository</font></font></span>'''
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The last type of flow execution repository provided by Spring Web Flow is the client continuation repository, implemented by the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">ClientContinuationFlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">class. As the name suggests, the client continuation repository also uses a web-continuations–based approach to flow execution management, similar to the default continuation repository. The difference between the two is in where they store the continuation snapshots. The default continuation repository stores continuation snapshots on the server side, in the HTTP session (using the </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">SessionBindingConversationManager</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">). The client continuation repository stores the continuation snapshots on the client side, avoiding use of any server-side state. To make this possible, the client continuation repository encodes the entire continuation snapshot inside the flow execution key. Here is an example of a hidden field in an HTML form, containing a flow execution key generated by the client continuation repository:</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"><input type="hidden" name="_flowExecutionKey"</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">value="_cNoOpConversation id_krO0ABXNyAGFvcmcuc3ByaW5nZnJhbWV3b3JrL \</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">ndlYmZsb3cuZXhlY3V0aW9uLnJlcG9zaXRvcnkuY29udGludWF0aW9uLlNlcmlhbGl6 \</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">lvbi5GbG93RXhlY3V0aW9uQ29udGludWF0aW9ujvgpwtO1430CAAB4cHoAAAQAAAAM- \</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">...</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">L3VDqmZZMURBDF7-I73_3g1IND_5AqBLBJQ14z4tUZQRPZFvz_gzBNwW37Z9uff3bRv \</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">V1SH-1h7xERqN7--u0Td_Y_VVNH6uJkmYYGLgpLzRWn1XHSxuS5tbgYniCt6hNPkGG3 \</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">OxFhQME1Wdb1B0jLVgMeee364-3eNtM_MW9xgp9c3n8v4NL2FNyjEbHcNZxcvqBbj8i \</font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">7lZtyOSeXy_0XxBYpbwUkAAABeA.."/></font></font></span>
 
<span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The continuation ID is a base-64–encoded, GZIP-compressed form of the serialized </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">FlowExecution </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">object.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: HelveticaNeue-MediumCond"><font face="HelveticaNeue-MediumCond">Client Continuation Repository Pros and Cons</font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The client continuation repository is a remarkable specimen. It has the major advantage of not requiring any server-side state. This has important benefits in terms of scalability, failover, and application and server management. Additionally, since this repository uses web continuations, it has complete support for use of the browser’s Back button. There is a high cost to pay however:</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• By default, the client continuation repository does not use a real conversation manager. As a consequence, it cannot properly prevent double submits and does not support the conversation scope. These issues can be resolved, however, by plugging in a real </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">ConversationManager</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• Because of the long flow execution key, applications are limited to using POST requests. This also rules out applying the POST-REDIRECT-GET idiom using “always redirect on pause”.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• Exchanging a relatively large flow execution key between the client and server on every request consumes quite a bit of bandwidth, potentially making the application slower for users on slow connections.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">• Storing state on the client has security implications. An attacker could try to reverse engineer the continuation snapshot, extracting sensitive data or manipulating certain data structures. The </font></font></span><span style="mso-bidi-font-family: TheSansMonoConSemiLight"><font face="TheSansMonoConSemiLight"><font size="9.5pt">ClientContinuationFlowExecutionRepository </font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">was designed for extensibility, however, allowing you to plug in continuation snapshot encryption. The client continuation repository provided by Spring Web Flow is an interesting experiment. Future versions of Spring Web Flow will certainly investigate this idea in more depth, for instance, in trying to manage conversations using state stored in client-side cookies. For now, make sure you understand the consequences of using the client continuation repository before deciding to use it.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
'''<span style="mso-bidi-font-family: Utopia-Semibold"><font face="Utopia-Semibold"><font size="13.0pt">Selecting a Repository</font></font></span>'''
 
'''<span style="mso-bidi-font-family: Utopia-Semibold"><font face="Utopia-Semibold"><font size="13.0pt"> </font></font></span>'''
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">The matrix shown in Figure makes it easy to pick the correct repository depending on whether or not you need to support browser Back button usage and on the memory constraints of the deployment environment.</font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular; mso-no-proof: yes"><font face="Utopia-Regular"><font size="9.5pt">[[Image:image010.jpg]]</font></font></span><span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"></font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt"> </font></font></span>
 
<span style="mso-bidi-font-family: Utopia-Regular"><font face="Utopia-Regular"><font size="9.5pt">In general, though, most applications are best served using the continuation repository. Since this is the default repository in Spring Web Flow, you don’t need to configure anything. Only select a different repository type if you have real requirements or constraints that force you away from the default repository. So unlike struts the complete token management and checking is done automatically without developer having to worry about pairing issues.</font></font></span>
 
7. References
 
1. Synchronizer Token using struts (http://www.jaxmag.com/itr/online_artikel/psecom,id,648,nodeid,147.html, http://www.java-samples.com/showtutorial.php?tutorialid=582)
 
2. Spring Web Flow (http://www.amazon.com/Definitive-Guide-Spring-Web-Flow/dp/1430216247)
 
</div>

Revision as of 05:20, 7 October 2009

Research in refactoring tools

Introduction

Improvements in the Refactoring Tools

Academic underpinnings

Extract Method

Code cloning and detection

Refactoring Annotations

Ongoing and Future Research

Binary Refactoring

Refactoring Functional Programs

Language Independent Refactoring

Use Case Refactoring

Hardware Refactoring

References

[1] Improving usability of refactoring tools Emerson Murphy-Hill, October 2006, ACM