Spring Web Flow
  1. Spring Web Flow
  2. SWF-238

Add support for a global "back" transition that can transition to the previous view state

    Details

      Description

      This code allows the definition of a global 'back' transition using:

      <transition on="back" to="$

      {flowScope.previousViewStateId}

      "/>

      See forum http://forum.springframework.org/showthread.php?p=95731 for background information.

      ------------------------------------------------------------------------------
      import java.util.LinkedList;

      import org.springframework.webflow.definition.StateDefinition;
      import org.springframework.webflow.engine.ViewState;
      import org.springframework.webflow.execution.FlowExecutionListenerAdapter;
      import org.springframework.webflow.execution.FlowSession;
      import org.springframework.webflow.execution.RequestContext;

      public class BackToLastViewStateFlowExecutionListener
      extends FlowExecutionListenerAdapter
      {

      private String viewStatesName = "GLOBAL_BACK_LISTENER_VIEW_STATES";
      private String backEventId = "back";

      public void setViewStatesName(final String viewStatesName)

      { this.viewStatesName = viewStatesName; }

      public void setBackEventId(final String backEventId)

      { this.backEventId = backEventId; }

      @Override
      public void sessionStarted(final RequestContext context,
      final FlowSession session)

      { session.getScope().put(viewStatesName, new LinkedList<String>()); }

      private LinkedList<String> getViewStates(final RequestContext context)

      { @SuppressWarnings("unchecked") final LinkedList<String> viewStates = (LinkedList<String>)context.getFlowScope().get(viewStatesName); if (viewStates == null) throw new IllegalStateException("viewStates is null"); return viewStates; }

      @Override
      public void stateEntered(final RequestContext context,
      final StateDefinition previousState,
      final StateDefinition state)
      {
      // If there's no previous ViewState, there's nothing we can do...
      if (!(previousState instanceof ViewState))
      return;

      // If we're entering the same state (due to a reload or
      // binding error), ignore that...
      if (previousState.getId().equals(state.getId()))
      return;

      final LinkedList<String> viewStates = getViewStates(context);

      final String previousStateId;

      if (context.getLastEvent().getId().equals(backEventId))

      { viewStates.removeLast(); previousStateId = viewStates.isEmpty() ? "" : viewStates.getLast(); }

      else

      { previousStateId = previousState.getId(); viewStates.add(previousStateId); }

      context.getFlowScope().put("previousViewStateId", previousStateId);
      }

      }
      ------------------------------------------------------------------------------

      Best

      Oliver

        Activity

        Hide
        Doug Breaux added a comment -

        We've been using this technique for a while now, and I just discovered that it doesn't take into consideration the transition history attribute.

        But further, this uncovered what may be a fundamental misunderstanding for me. I guess we want a pseudo "end-state" that does not allow the user back to a previous view-state but doesn't force the whole flow to start over either. I was thinking this was what history="invalidate" did - the documents are worded that way - but clearly not the way I was expecting.

        That is, I would have expected the above implementation to indeed have had a bug if this "back" transition was allowed from a place where history had been invalidated, but once I discovered that, I was surprised that the so-allowed transition actually worked rather than throwing some kind of exception.

        So... is the solution to make the above implementation more sophisticated, checking the history attribute? Or to ensure that back is never available from states that are after an invalidate? (Which seems a bit fragile to maintain.) Or to change the removeFlowExecutionSnapshot(), removeAllFlowExecutionSnapshots() behaviors so that the prior view-states are simply not allowed, no matter how to try to reach them? (If that's even possible.)

        Show
        Doug Breaux added a comment - We've been using this technique for a while now, and I just discovered that it doesn't take into consideration the transition history attribute. But further, this uncovered what may be a fundamental misunderstanding for me. I guess we want a pseudo "end-state" that does not allow the user back to a previous view-state but doesn't force the whole flow to start over either. I was thinking this was what history="invalidate" did - the documents are worded that way - but clearly not the way I was expecting. That is, I would have expected the above implementation to indeed have had a bug if this "back" transition was allowed from a place where history had been invalidated, but once I discovered that, I was surprised that the so-allowed transition actually worked rather than throwing some kind of exception. So... is the solution to make the above implementation more sophisticated, checking the history attribute? Or to ensure that back is never available from states that are after an invalidate? (Which seems a bit fragile to maintain.) Or to change the removeFlowExecutionSnapshot(), removeAllFlowExecutionSnapshots() behaviors so that the prior view-states are simply not allowed, no matter how to try to reach them? (If that's even possible.)
        Hide
        Oliver Siegmar added a comment -

        Please keep in mind, that I've written this code more than six years ago for SWF 1.0.5 - a lot of things have changed during that time. I'm even surprised, that it does still work (almost)

        Show
        Oliver Siegmar added a comment - Please keep in mind, that I've written this code more than six years ago for SWF 1.0.5 - a lot of things have changed during that time. I'm even surprised, that it does still work (almost)
        Hide
        Doug Breaux added a comment -

        No worries, Oliver. I'm just still hoping for this to be included in the core, and even if it's not, I wanted somebody "in the know" to comment on the history behavior.

        Show
        Doug Breaux added a comment - No worries, Oliver. I'm just still hoping for this to be included in the core, and even if it's not, I wanted somebody "in the know" to comment on the history behavior.

          People

          • Assignee:
            Keith Donald
            Reporter:
            Oliver Siegmar
          • Votes:
            19 Vote for this issue
            Watchers:
            21 Start watching this issue

            Dates

            • Created:
              Updated:

              Development