0

I've been working with SWF for about 3 weeks now and I successfully ported a Spring MVC/JSP recipe entry form into 4 separate views, consisting of 1) basic info, 2) ingredients, 3) instructions and 4) optional info. I would like to enhance the flow so that #2 and/or #3 can be executed 1 to x times based upon a user entry on #1. An example would be a recipe that includes a set of ingredients for a cake and a separate set for the icing - the user would indicate there are 2 sets of ingredients on view #1 and view #2 would be displayed twice.

I've read through the docs and tons of posts and I'm still really confused as to the best way to approach this. In essence I need to set a variable in view #1 that webflow will evaluate and do a kind of for loop on view #2.

Currently, the number of iterations is not part of the model used by the views, but it seems like most of the examples and posts I've looked at point to needing to add it to the model then do an <evaluate> in the flow to determine the number of times to iterate view #2. Alternatively, is there a way to set a <var> in the webflow.xml that can be updated in the view #1 jsp form and then evaluated in view #2 without calling a server function? Or is using <input> and output a possible solution? Or could I use a requestparam?

I have to admit being a bit flummoxed by this. Any help with pointing me to examples, docs, other posts that I somehow missed would be greatly appreciated.

LWK69
  • 1,070
  • 2
  • 14
  • 27

1 Answers1

0

Brief Explanation:

I think you're misunderstanding the intended purpose of a 'view-state' and Spring webflow in general.

Spring Webflow = An xml file that describes a "Sequential" logical flow of states that achieve a single goal (e.g 'Book an airline ticket', 'Gather information for cooking receipes', etc...)

"Sequential" here means that every single state (e.g view-state, action-state, decision-state, end-state) is a SINGLE UNIT of EXECUTION inside Spring webflow. Where each state EXPLICITLY defines what the 'next' state is going to be once it completes execution. For instance,

(view-state A) -> (action-state B) -> (decision-state C) -> (end-state D)

There is no concept of iteration defined with in each state because they are single units of execution. Once a state finishes execution it must go to the next state as defined by the 'transition' tag.

<view-state id="stateA">
     <transition to="stateB"/>
</view-state>

Also notice I wrote "Sequential" in quotes because although the flow is sequential (from state -> state)... we can still jump back to any state we wish like so.

(view-state A) -> (action-state B) -> (decision-state C) -> (view-state A)

So...your interpretation of internal view-state iteration does not exist.


Answer to your question:

There are several ways to achieve the 'state' iteration you desire but it sounds like you need a decision-state to delegate the flow based on some flowScope variable. Basically you want to keep track of the num of times you want to execute a particular state then everytime you execute the state you decrement the variable by ( 1 ) and reevaluate it until the num of executions == 0.

Sample flow defined below with comments ( not based on the example code just from your description ).

    <!-- define the 'global' flowScope variable that will track the num of times you want to execute the ingredients state --> 
    <set name="flowScope.numOfTimesToExecuteIngredientsState" value="0" type="java.lang.Integer"/>


        <view-state id="basicInfoState" model="basicInfoModel">

        <!-- initially goto the decision state and make sure to set the num of execution inside the transition to the 'global' flowScope tracking variable -->
        <transition on="save" to="ingredientsIteratorDecisionState">
 <!-- assuming ingredients is an initialized Set<Ingredients>... get the size and put inside a flowScope var -->
             <set name="flowScope.numOfTimesToExecuteIngredientsState" value="basicInfoModel.getIngredients().size()"/> 
        </transition>

        </view-state>

        <decision-state id="ingredientsIteratorDecisionState">
            <!-- if # of executions is more than 0 go back to ingredientState otherwise move on to instructionsState -->  
            <if test="flowScope.numOfTimesToExecuteIngredientsState > 0" then="ingredientsState" else="instructionsState"/>
        </decision-state>

        <view-state id="ingredientsState">

            <transition on="save" to="ingredientsIteratorDecisionState">
              <! -- upon a successful save... decrement numOfIngredientsSelected by ( 1 ) -->
              <set name="flowScope.numOfTimesToExecuteIngredientsState" value="flowScope.numOfTimesToExecuteIngredientsState - 1"/>
            </transition>
        </view-state>

Disclaimer: the flow definitions above were not tested. I just wrote it from memory. There might be syntax errors.

You also asked:

Alternatively, is there a way to set a in the webflow.xml that can be updated in the view #1 jsp form and then evaluated in view #2 without calling a server function? Or is using and output a possible solution? Or could I use a requestparam?

No. There will always be a call to the server. Why not just deduce the # of recipes from the collection object's size stored on your model?

You could enable SWF the handling of ajax requests and send a requestParam to a transition with no defined 'to=' state. (meaning it will stay in the current view-state) and inside the transition tag do your custom logic (see: How to include a pop-up dialog box in subflow)

but I think this is a design problem. All the values you pass should be in a single http request (and therefore part of your model).

Community
  • 1
  • 1
Selwyn
  • 3,118
  • 1
  • 26
  • 33
  • Thanks so much for your detailed response. I spent all of yesterday dynamically creating an href with the flowExecutionUrl, eventId, and number of required iterations as a requestParam, which actually worked until I turned validation of the basics page back on and it became apparent that the form wasn't being submitted properly. Ultimately it makes the most sense to add @Transient fields to the model as you suggested and use them in a decision state. Lesson learned: don't use a saw to hammer a nail. Thanks again for your help. – LWK69 Nov 16 '15 at 14:19
  • just a quick followup to let you know I was able to get the instructions flow to work based upon your suggestions. It took a fair amount of code and messing with indexes because the model includes 2-dimensional autopopulating lists (main list for section headers and sub list for actual instructions). As I worked through this, though, I'm still not completely convinced that allowing for repeating a single page within the SWF paradigm would necessarily be a bad thing. The flow would still be "sequential", but a given page would simply be presented x times to the user. – LWK69 Nov 20 '15 at 13:13
  • Ran out of space, but to finish, it's unlikely regardless that this suggestion for iteration would ever be considered since it seems that Spring is not that interested in enhancing this project. The last major release, 2.0, was in April, 2008. Nevertheless, it has been fun to work with and I've been able to achieve what I wanted. Thanks again for your help. – LWK69 Nov 20 '15 at 13:21
  • @LWK69 glad to hear it worked out. They just released a minor revision a couple of months ago. Although it doesn't seem like SWF is being actively worked on... Submit an enhancement request on the jira page I bet you'll get a response with in a day or 2. – Selwyn Nov 20 '15 at 14:08
  • @LWK69 also, if you want this functionality to be "extensible" you could place it inside an abstract parent flow and leverage the flow inheritance to utilize it. This would be a tad bit complex but that is an alternate solution. – Selwyn Nov 20 '15 at 18:44
  • thanks for the suggestion but that's probably beyond my capabilities at the moment. I'm still a newb in the Java, Spring, Hibernate, etc. arena - I've only been at this for a bit more than 6 months. I retired in May after 35 years in IT, started in COBOL and spent a lot of time in C/C++, but mostly was management. I'm learning the Java/web stack to get some occasional part-time work so I don't go batty sitting at home. I'm enjoying it immensely but it's a challenge to pick up everything on my own. SO is a great resource thanks to contributors like you. – LWK69 Nov 20 '15 at 22:17