Announcement Announcement Module
Collapse
No announcement yet.
Menu options in Spring Webflow Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Menu options in Spring Webflow

    I have set-up an application using Spring Web flow. The application contains around 50 menu options which are currently available on the home page and a main web-flow.xml. When a menu option is clicked another sub-flow is started and so on.

    The problem I have is that I want all the menu options to be available on every page throughout the application so a user can move to any screen. I cannot do this in spring web-flow without coping every menu action to every web-flow.xml configuration.

    Is is possible to define menu options globally and use them in sub flows?

  • #2
    My first impression is that is that with so many menu items, it might not be appropriate to use Spring Web Flow with your app. Are these menu options representing different steps in a single navigation flow? If so, then each menu choice effectively short-circuits your navigation flow, and you probably shouldn't be using SWF for it.

    If, on the other hand, each menu choice starts a separate and independent navigation flow, then SWF may work.

    With SWF 2.0.x, you can use flow inheritance. You can define an abstract flow (one that must be inherited, and can't be invoked on its own) with global transitions defined for each menu choice, each one going to an end-state which performs a flow-redirect to the appropriate flow.

    Then, for every flow where you need this global navigation available, you add
    Code:
    parent="myGlobalTransitionsFlow"
    to the flow element. See the SWF reference guide for more info on flow inheritance.

    Comment


    • #3
      First things thanks for the reply.

      Each menu option starts a new flow. In each flow there exists several actions which are specific the that flow (screen). Such as creating new records, editing records, viewing record, performing other operations, etc. The menu options are simply the actions to start each sub-flow.

      So in the response to your question I think this is the second option in that each menu starts a separate and independent navigation flow. Well I think it is the second but I could be wrong.

      We are currently using spring Webflow 1.x and due to upgrade in a couple of months. It sounds like this could be possible in Spring Webflow 2.x?

      Comment


      • #4
        Should be possible. I forgot a few important details on using this pattern, however.

        If I recall correctly, flow-redirects in end-states are not evaluated unless they are ending a top-level flow (so they are ignored in subflows). This means you will need to be sure to apply your globalTransitions flow as a parent for pretty much every flow of your app where your menu options are selectable. This way, no matter how many subflows deep you are, selecting the menu option will "bubble up" the flow of control, transitioning to the current flow's end-state, which returns control to the calling flow causing a transition to the calling flow's end-state, returning control to its calling flow etc. until it reaches the end-state in your top-level flow, at which point the flow-redirect defined in your end-state executes.

        The problem with this is that your conversation scope gets wiped out, since you're ending your top-level flow and starting a new one. I believe your messages also get wiped out (though I posted some code to preserve messages across flow redirects a couple days ago).

        In my particular case, I want to have a single top-level flow for my app for the entire session. To do this and support my global links, I don't put flow-redirects in the end-states in my global flow. They're just regular empty end-states. I make sure my main top-level flow does not inherit the globalTransitions flow, since I don't want to inherit the end-states. I then add my own global transitions to the main flow, sending them to subflow-states instead of end-states.

        I don't know which strategy makes the most sense with your app, but I hope this helps you out. You should be able to cut down on the xml explosion from the sheer number of transitions you're supporting through good use of flow inheritance.

        Comment


        • #5
          I want to do something similar. Would you mind posting your flow configuration files.

          Comment


          • #6
            Can you describe what it is you're trying to do? The configuration files are different depending on if you want to keep one top-level flow for the entire app, or if you want each option to end the top-level flow and start a new one.

            Comment


            • #7
              Sorry, I should have been more specific. I would like to have one top level flow that starts subflows. I've pretty much gotten that to work but I'm wondering if there is a generic way to do this. I'm trying to avoid having to create a global transition and subflow entry for each new flow that I create. Here is what I have:

              Code:
                  
                  <global-transitions>
                      <transition on="flow1" to="flow1"></transition>
                      <transition on="flow2" to="flow2"></transition>
                      <transition on="flow3" to="flow3"></transition>
                  </global-transitions>
              
                  <subflow-state id="flow1" subflow="flow1"></subflow-state>             
                  <subflow-state id="flow2" subflow="flow2"></subflow-state>             
                  <subflow-state id="flow3" subflow="flow3"></subflow-state>
              Previously I had one global transition that each menu option would call. That transition would end the current flow and then redirect to a new flow based on a request parameter. I'm wondering if I can do something similar but instead of redirecting to a new flow, just start a sub flow. Here's what I had previously in my common abstract flow. All of my flows inherited from this.

              Code:
                  
                  <var name="targetFlow" class="java.lang.String" />
                  
                  <end-state id="redirect" view="externalRedirect:contextRelative:#{targetFlow}" />
              
                  <global-transitions>
                      <transition on="closeCurrentFlow" to="redirect">
              	<set name="targetFlow" value="requestParameters.destPage" />
                     </transition>
                  </global-transitions>

              Comment


              • #8
                I've seen this question about menu handling come up a number of times on this forum but there doesn't seem to be a good answer. It looks like you can go the route of global transitions where you end the current flow and redirect to a new flow or you make your menu navigation separate views that don't require SWF.

                The first part seems like a bit of hack because every menu link on a page needs to link back to this global transition with a redirect parameter. This can get messy when you have a header, navigation, and footer menu.

                The second approach seems a little more logical but how do you handle all the JSF related stuff with just separate views. Also, does it make sense that the application should hide the menu once a user starts through a flow and only show some kind of "cancel" button?

                Do the SWF developers have any input? A navigation menu seems like a very common use case for a web site.

                -mike

                Comment


                • #9
                  I found a nasty, nasty trick to solving this issue of having global menus in SWF and having flows and subflows exit gracefully. It is not an elegant work-around, but it works and it is simple to implement. Hope it can still help someone.

                  First things first, you need the global abstract flow, where you let each of your flow inherit via
                  Code:
                  parent="commonFlow"
                  .

                  Second, here is what the global commonFlow.xml should contain:
                  Code:
                  	<!-- we assume a maximum of 3 subflows deep for the whole application -->
                  	<end-state id="endCurrentFlowLevel1" view="flowRedirect:newFlow">
                  	</end-state>
                  	<end-state id="endCurrentFlowLevel2" view="flowRedirect:newFlow">
                  	</end-state>
                  	<end-state id="endCurrentFlowLevel3" view="flowRedirect:newFlow">
                  	</end-state>
                  	...
                  	<global-transitions>
                  	<!-- If Menus are triggered on subflows, we end them first. We assume at most 3 levels deep of subflows -->
                  	<transition on="endCurrentFlowLevel1" to="endCurrentFlowLevel2"/>
                  	<transition on="endCurrentFlowLevel2" to="endCurrentFlowLevel3"/>
                  	</global-transitions>
                  The trick here is, if the current flow is already a top level flow, SWF would not bubble up the parent and will just execute the flow redirect.

                  If, however, the current flow is a subflow, SWF will not execute the redirect on the subflow, but instead will bubble up to the parent first, looking for a matching transition for the current subflow that just ended. It would continue doing this until it finds the top-level flow in which case it would execute the redirect, effectively ending all subflows in the process as well.

                  Comment

                  Working...
                  X