Welcome!

Java Authors: Maureen O'Gara, Bruce Armstrong, Liz McMillan, Walter H. Pinson, III, Yakov Werde

Related Topics: Java

Java: Article

The Promise of Handling Complex Page Navigations in Any Web Application

The promise of handling complex page navigations in any Web application

At any given time the FlowExecution manages a stack of flow sessions. A flow session is a placeholder for flow variables and flow state. Action implementations can access the flow-scoped parameters using the RequestContext interface. When the flow execution enters a sub-flow state, the flow execution creates a new flow session and adds it as the top item in the flow session stack. This session remains as the active session until the sub-flow completes execution and the flow execution activates its parent flow session. A parent flow can pass its flow session parameters to the newly spawned sub-flow using an attribute mapping as shown in the above configuration. An input element can map a flow-scoped parameter in the parent flow and copy it to the sub- flow session. Similarly, an output element copies the parameter value from the sub-flow back to the parent flow when the flow completes.

An attribute mapper configuration can optionally reference a FlowAttributeMapper implementation defined in Spring's context using the 'bean' element attribute. In this case the input and output elements aren't necessary. If no flow attribute mapper implementation is referenced, SWF will use a default implementation

ParameterizableFlowAttributeMapper uses the input and output element mappings to do the attribute mapping.

Integration with Struts
SWF provides a FlowAction class, which is a struts action class that can act as the front controller entry point into the Web flow system. Typically, a single parameterized (by flow id) FlowAction can manage all flow executions. The FlowAction delegates every request to a FlowExecutionManager. This class is also aware of a BindingActionForm adapter that adapts Spring's binding facility to the struts action form model. A flow action can be configured as shown below in the 'struts-config.xml' configuration file.

<action path="/checkout" type="org.springframework.web.flow.struts.FlowAction"
name="bindingActionForm" scope="request"
className="org.springframework.web.flow.struts.FlowActionMapping">
<set-property property="flowId" value=" CheckoutFlow" />
   </action>

A struts action form with the name 'bindingActionForm' and the class 'org.springframework.web.struts.BindingActionForm' has to be defined in the struts-config.xml file.

The FlowAction controller maps all logical view names returned from a view state and end state as action forward mappings (typically global forwards) in the struts configuration.

The use of Spring's binding-aware action form requires some additional struts configuration. A custom binding action-aware request processor is required to defer the form population.

<controller processorClass="org.springframework.web.struts.BindingRequestProcessor"/>

A binding plug-in is also needed to plug in an errors-aware jakarta-commons-beanutils adapter:

<plug-in className="org.springframework.web.struts.BindingPlugin"/>

Integration with Spring MVC
SWF has a very natural integration with the Spring MVC framework. It provides a Spring FlowController class that can act as a front controller for executing Web flows. A single FlowController instance can be parameterized (using the flow id parameter) to execute different flows.

Making the Back Button Work
A page flow system like SWF uses server-side state management to direct page navigation. This can easily conflict with browser back button use. The easiest way to tackle this is to not use the browser back button.

However, if required you can support browser back button functionality by sending the current state id (_currentStateId) explicitly with every request to the flow controller. This way the FlowExecution will know which state to use and result in correct navigation even when the back button is used.

<form name="someForm" action="checkout">
<input type="hidden" name="_flowId"
value="<%=request.getAttribute("flowId")%>">
<input type="hidden" name="_currentStateId" value="viewShippingAddress">
<input type="hidden" name="_eventId" value="next">
<input type="hidden" name=" _flowExecutionId"
value="<%request.getAttribute("flowExecutionId")%>">
....

However, this approach won't work if there are sub-flows. In this case, there's still confusion as to what flow (sub-flow or its parent flow) should be used. SWF provides a continuation-based approach to solve this problem. In SWF a continuation is a snapshot of the flow execution state (serialized form of FlowExecution instance) at any given point of time. To support this, an HttpSessionContinuationFlowExecutionStorage mechanism should be used instead of the default HttpSessionFlowExecutionStorage.

<action path="/checkout" type="org.springframework.web.flow.struts.FlowAction"
name="bindingActionForm" scope="request"
className="org.springframework.web.flow.struts.FlowActionMapping">
<set-property property="flowId" value=" CheckoutFlow" />
<set-property property="storage" value="sessionContinuation">
   </action>

This way, for every request, a serialized form of the current FlowExecution instance is stored in the HTTP session (under a separate flow execution id attribute). For a new client request (with the flow execution id parameter), the FlowExecutionManager will de-serialize the saved FlowExecution instance and uses it to process the event. Hence, every request will be processed using the correct context.

Conclusion
Spring Web Flow is a very powerful and elegant Web flow solution. It's definitely a promise for handling complex page navigations in any Web application.

References

More Stories By Kishore Kumar

Kishore Kumar works as a Java architect at U.S. Technology (www.ustri.com). He specializes in J2EE applications.

Comments (5) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Eelco Hillenius 08/02/06 11:58:26 AM EDT

'Page navigation' is a knee-jerk reaction that doesn't solve any real problems. See http://chillenious.wordpress.com/2006/07/16/on-page-navigation/

JD 08/01/06 06:53:29 PM EDT

This article is really good. Two things missing in this article. The link or references to the actual JSPs and the link to the whole zipped source so people could run it and see for themselves.

news desk 12/04/05 04:18:34 AM EST

Java & SOA - The Promise of Handling Complex Page Navigations in Any Web Application. Page navigation requirements become more demanding as Web applications get bigger and more complex. Hard-coded page flow rules make applications less resilient to changes. In this scenario, reusing business logic is one aspect and reusing page flow becomes another aspect. Especially in situations that demand a wizard-kind behavior, it's essential to capture application page flow logic in a declarative fashion.

jdj news desk 12/04/05 03:29:55 AM EST

The Promise of Handling Complex Page Navigations in Any Web Application. Page navigation requirements become more demanding as Web applications get bigger and more complex. Hard-coded page flow rules make applications less resilient to changes. In this scenario, reusing business logic is one aspect and reusing page flow becomes another aspect. Especially in situations that demand a wizard-kind behavior, it's essential to capture application page flow logic in a declarative fashion.

Jeanne 09/29/05 12:36:59 PM EDT

Listings 2 and 3 are not linked in the article.