Announcement Announcement Module
Collapse
No announcement yet.
Feedback requested: Redirect support in SWF Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Feedback requested: Redirect support in SWF

    We have extended/refined the support for redirects in Spring Web Flow; feedback on these refinements are much appreciated.

    1.0 introduced 3 redirect types: "conversation redirect", "flow redirect", and "external redirect".

    A conversation redirect allows redirect to the *current* (most recent) view-state of a conversation, at a single conversation URL, while the conversation remains active.

    A flow redirect requests that a entirely new execution of another flow be launched--used to support flow chaining and restart use cases.

    A external redirect redirects to an arbitrary external URL, with support for sending a flow execution key through the redirect.

    1.0 RC1 introduces a 4th type, called a "flow execution redirect". This supports redirecting to *any* previously traversed view-state of a flow execution at a unique "flow execution URL", to support post->redirect->get semantics with full support for back, forward, and refresh buttons while the conversation remains active.

    In addition, the semantics of "conversation redirect" and "flow execution redirect" are a bit different now--previously application view selections made by view states were cached through the redirect; now they're reconstituted via a new FlowExecution "refresh" operation on each redirect request. Note this causes any data in request scope of the request preceding the redirect to be lost (while data in flow scope is preserved of course).

    "itemlist" and "numberguess" samples demonstrate the "conversation redirect" (notice how back doesn't make any sense as the URL is stable throughout the flow, and it is best suited for a "SimpleFlowExecutionRepository").

    "sellitem" demonstrates the "flowExecutionRedirect". Notice how the URL changes on each submit and back/forward/refresh are fully supported. Also note how this is is suited for a "ContinuationFlowExecutionRepository" and does not make sense with client-side storage.

    Notice how post->redirect->get semantics can be configured globally for all flows (see FlowExecutor.redirectOnPause property) or on a per flow basis (see view-state redirect prefixes in "view" attribute DTD). Of course, redirection is optional, and samples like Phonebook don't do any redirects, relying on continuations + page caching to get stable navigation button behavior.

    Thoughts? We should release 1.0 RC1 once we are confident these remaining redirect challenges are right.

    Keith
    Last edited by Keith Donald; Apr 29th, 2006, 07:23 PM.

  • #2
    Hey, Keith,

    Just a question. In the description of sellitem, you mention that the "URL changes on each submit". Perhaps I'm using the wrong version of SWF (I'm on 1.0 EA) but I'm not seeing this. The URL remains consistently http://localhost:8080/swf-sellitem/p...lowId=sellitem.

    Thanks,

    Rob

    Comment


    • #3
      Yes, this is new in 1.0 RC1. Try out a 4/30 or > nightly build:
      http://static.springframework.org/do...pring-webflow/

      Comment


      • #4
        Sounds excellent Keith and I look forward to trying it out asap.

        Comment


        • #5
          Hi, Keith,

          I was trying to run through the sellitem example but am encountering this exception when I try to start the flow (using Jetty6.0.0beta14):
          Code:
          2006-05-02 10:01:07,521 DEBUG [org.springframework.webflow.executor.support.FlowRequestHandler] - <Request initiated by [ServletExternalContext@290e1513 requestParameterMap = map['_flowId' -> 'sellitem']]>
          :WARN:  EXCEPTION
          org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ArrayIndexOutOfBoundsException: 0
          Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
                  at org.springframework.webflow.ParameterMap.get(ParameterMap.java:144)
                  at org.springframework.webflow.ParameterMap.get(ParameterMap.java:128)
                  at org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor.extractFlowExecutionKey(FlowExecutorArgumentExtractor.java:267)
                  at org.springframework.webflow.executor.support.FlowRequestHandler.handleFlowRequest(FlowRequestHandler.java:100)
                  at org.springframework.webflow.executor.mvc.FlowController.handleRequestInternal(FlowController.java:198)
                  at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
                  at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
                  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:796)
                  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:727)
                  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
                  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:350)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:747)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:860)
                  at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:423)
                  at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:350)
                  at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:221)
                  at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:539)
                  at org.mortbay.jetty.Server.handle(Server.java:341)
                  at org.mortbay.jetty.Server.handle(Server.java:311)
                  at org.mortbay.jetty.HttpConnection.doHandler(HttpConnection.java:355)
                  at org.mortbay.jetty.HttpConnection.access$1500(HttpConnection.java:38)
                  at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:598)
                  at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:487)
                  at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:196)
                  at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:293)
                  at org.mortbay.jetty.nio.SelectChannelConnector$HttpEndPoint.run(SelectChannelConnector.java:710)
                  at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:412)
          :WARN:  Nested in org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ArrayIndexOutOfBoundsException: 0:
          java.lang.ArrayIndexOutOfBoundsException: 0
                  at org.springframework.webflow.ParameterMap.get(ParameterMap.java:144)
                  at org.springframework.webflow.ParameterMap.get(ParameterMap.java:128)
                  at org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor.extractFlowExecutionKey(FlowExecutorArgumentExtractor.java:267)
                  at org.springframework.webflow.executor.support.FlowRequestHandler.handleFlowRequest(FlowRequestHandler.java:100)
                  at org.springframework.webflow.executor.mvc.FlowController.handleRequestInternal(FlowController.java:198)
                  at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
                  at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
                  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:796)
                  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:727)
                  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
                  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:350)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:747)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:860)
                  at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:423)
                  at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:350)
                  at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:221)
                  at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:539)
                  at org.mortbay.jetty.Server.handle(Server.java:341)
                  at org.mortbay.jetty.Server.handle(Server.java:311)
                  at org.mortbay.jetty.HttpConnection.doHandler(HttpConnection.java:355)
                  at org.mortbay.jetty.HttpConnection.access$1500(HttpConnection.java:38)
                  at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:598)
                  at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:487)
                  at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:196)
                  at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:293)
                  at org.mortbay.jetty.nio.SelectChannelConnector$HttpEndPoint.run(SelectChannelConnector.java:710)
                  at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:412)
          :WARN:  /swf-sellitem/pos.htm:
          java.lang.ArrayIndexOutOfBoundsException: 0
                  at org.springframework.webflow.ParameterMap.get(ParameterMap.java:144)
                  at org.springframework.webflow.ParameterMap.get(ParameterMap.java:128)
                  at org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor.extractFlowExecutionKey(FlowExecutorArgumentExtractor.java:267)
                  at org.springframework.webflow.executor.support.FlowRequestHandler.handleFlowRequest(FlowRequestHandler.java:100)
                  at org.springframework.webflow.executor.mvc.FlowController.handleRequestInternal(FlowController.java:198)
                  at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
                  at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
                  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:796)
                  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:727)
                  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
                  at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:350)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:747)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:860)
                  at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:423)
                  at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:350)
                  at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:221)
                  at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:539)
                  at org.mortbay.jetty.Server.handle(Server.java:341)
                  at org.mortbay.jetty.Server.handle(Server.java:311)
                  at org.mortbay.jetty.HttpConnection.doHandler(HttpConnection.java:355)
                  at org.mortbay.jetty.HttpConnection.access$1500(HttpConnection.java:38)
                  at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:598)
                  at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:487)
                  at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:196)
                  at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:293)
                  at org.mortbay.jetty.nio.SelectChannelConnector$HttpEndPoint.run(SelectChannelConnector.java:710)
                  at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:412)
          ...
          I'll try running under Tomcat next, but just thought you'd like to know.

          Rob

          Comment


          • #6
            What version?

            Comment


            • #7
              What version of SWF?

              Comment


              • #8
                Last night's build.

                Comment


                • #9
                  That is a bug. Will fix promptly and add a test case.

                  Keith

                  Comment


                  • #10
                    Fixed. Good catch; I'm not sure why this showed up in Jetty just now, as the bug has been there. It's resolved now.

                    Comment


                    • #11
                      Thanks, Keith.

                      Comment


                      • #12
                        Keith,
                        I tried out the redirects briefly with the jsf integration, using redirect: and conversationRedirect: in front of the view url.
                        The redirect worked, but it redirected to the url of the posting page, not to the url of the new view.
                        i.e. I have a listUsers view that navigates to editUser
                        jsf always posts back to the same page, so listUsers posts back to itself. The navigation transition is fired, and the new view is editUser. However at this point swf redirects to listUsers.faces?_flowExecutionKey=...
                        (It does display the right view however)

                        So you still have the confusing problem of the url that's in the navigation bar being one page old.
                        Would it not be better to redirect to the url of the new view?

                        Cheers,

                        Jon

                        Comment


                        • #13
                          Hi Guys,

                          Got a quick question, I've tried switching all my flows, so that the redirectOnPause has been set to FLOW_EXECUTION. What seems to be happening, is everything in request scope is lost after the redirect, including form errors as a result of validation.

                          Am I missing something here?

                          Thanks,

                          -Kris

                          Comment


                          • #14
                            maybe view-redirect-stateful scope?

                            Keith,
                            great work with SWF redirection!
                            In one of my previous posts I described the problem with attributes set in RequestScope and not being visible in JSP page (RC1). There was no problem with flow scoped attrs. Now everything is clear - my flows have view redirecting set on, so on redirect all request attrs are gone.
                            Wouldn't be a good idea to give ability to rewrite request attrs on redirect - eg. by a property switch?
                            Or perhaps make another scope, which would be view-redirect-stateful but being destroyed on next step?

                            best regards,
                            Bali

                            Comment


                            • #15
                              We considered something like "flash scope" or "state scope" but decided it was too fuzzy to put into 1.0 RC1. We're interested in user's thoughts there, definitely.

                              Keith

                              Comment

                              Working...
                              X