Thursday, March 02, 2006

Keith Donald answers my, rather stupid, questions on Spring Web Flow

Shortly after writing a blog entry that talked about various webflow options in web applications I received an e-mail from Keith Donald. I hope Keith doesn't mind my reproducing the content of his e-mails here as I'm sure they would be useful to the world and especially to fellow stupid developers! Keith said:

I noticed a blog entry of yours where you noted Spring Web Flow as "promising" but it didn't like it could easily do some things you needed. If you could let me know what you would like to accomplish with the framework, perhaps I can provide some insight there.

After telling everybody I knew that THE Keith Donald had e-mailed me and receiving mixed responses from my colleagues. I tried to string together an intelligent response to his request based on the immediate questions I had been facing.

  1. How to use Spring Web Flow with Struts
  2. At stages in my "wizard" web application form selections are made which govern the path that the rest of the wizard is going to take. The examples of Spring Web Flow I have seen have always been couched in terms success or error outcomes (rather than optionA, optionB or error).
  3. Similarly I didn't see an example of how best to include a page that references itself (but not as an error). For example, let's say I had a form in my wizard app that was the basis of an RSS feed and had submit buttons that would result in adding/deleting news items to the page (okay an odd example but you get the idea). I actually have quite a few occurrences of this kind of behaviour in my applications which I currently handle using the Struts nested taglib and the LookupDispatchAction.

These are Keith's responses to my questions:

Reponse to Question 1

The birthdate sample app shows Spring Web Flow + Struts integration. It's in PR5 and will also be in the upcoming 1.0 rc1.

Response to Question 2

Spring Web Flow can route differently on the type of event that occurs:

For example:

<view-state id="displayForm" view="form">
<transition on="submit" to="determinePath">
<!-- bind and validate input on the form bean on submit -->
<action bean="formAction" method="bindAndValidate"/>

<!-- after binding, determine path -->
<decision-state id="determinePath">
<if test="${flowScope.formBean.option == 'optionA'}" then="optionAPath"/>
<if test="${flowScope.formBean.option == 'optionB'}" then="optionBPath"/>
<if test="${flowScope.formBean.option == 'error'}" then="error"/>

As an alterative to the decision-state above, you could also use an action state there, if you don't like putting expressions in XML:

<action-state id="determinePathAlternate">
<action bean="formAction" method="determinePath"/>
<transition on="optionA" to="optionAPath"/>
<transition on="optionB" to="optionBPath"/>
<transition on="error" to="error"/>

Response to Question 3

Going back to the same view-state (to re-render the same page) isstraightforward:

<view-state id="displayItems" view="newsItems">
<transition on="add" to="addItem"/>
<transition on="remove" to="removeItem"/>

<action-state id="addItem">
<action bean="formAction" method="addItem"/>
<transition on="success" to="displayItems"/>

<action-state id="removeItem">
<action bean="formAction" method="removeItem"/>
<transition on="success" to="displayItems"/>