Announcement Announcement Module
Collapse
No announcement yet.
How to access to conversationId from a flow action ? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to access to conversationId from a flow action ?

    I'm stumped. Sorry if I have missed something obvious. I am using the SimpleFlowExecutionRepository.

    I want to get access to the conversationId of the current flow in some action-state actions *before* the first view-state of the flow. It seems to me that the only way to programatically determine the conversationId is via the flowExecutionKey from the current repository:
    Code:
    repository.getCurrentFlowExecutionKey(serialisedConversationId)
    and then get the conversationId from the returned flowExecutionKey.

    However this needs the *conversationId* (presumably returned from a view)?

    I understand that a flowExecutionKey represents a particular conversation at a specific point in time, which is indeterminate until the flow is paused. So, how about an accessor to the conversationId from the current FlowSession?

    My use case is two-fold:
    1. Use the conversationId as a key for external monitoring, logging and persistence systems (initialised before the first view-state).
    2. Explicitly write the conversationId out to the first view so that the browser can use it (as suggested by Keith here http://forum.springframework.org/sho...6&postcount=27)
    .. which makes me sure I must be missing some api method somewhere ?

    thanks again!
    davidv

  • #2
    more understanding ...

    hmm .. I see that the conversationId is generated by the repository, and only used as a map entry key for the flowExecution within that repository.

    Therefore the conversationId is not really a property of the flowExecution at all, but only meta-data created by the repository.

    I presume this is a deliberate design choice.

    Any reason that the repository.createFlowExecution(flowId) could not be extended to be:
    Code:
     repository.createFlowExecution(flowId, conversationId)
    and then expose the conversationId from the flowExecution, and use that as the map entry key ?

    Comment


    • #3
      Really the FlowExecution itself should not know what conversation its associated with; that's a higher level concern, and yes was a deliberate design choice.

      With regard to accessing the conversationId from your view: each application view selection made from a view-state is exposed several flow execution context attributes--

      - the flowExecutionKey, which is basically an encoded string containing both the conversationId and continuationId -- used to continue a conversation from a specific view-state.
      - the flowExecutionContext, allowing access to the state of the flow execution for the current request.

      The conversationId itself isn't exposed; however I'm confused as to why your view would need just it, instead of the flowExecutionKey (which is what you need to *continue* a conversation).

      Now when you select a converastion redirect from a view state the redirect is done at a well-defined/refreshable conversation URL. Not sure if this will help you, but see the itemlist sample as an example.

      One thing I have considered adding is some sort of flow execution repository hook (like a listener) for responding to flow execution create/access/put and invalidate events. This is where you would have access to such a conversation identifier for logging/auditing, etc. However, the use case for needing that repository context information within the flow itself isn't completely clear to me. I guess one option would be to expose the repository context information in a ThreadLocal...

      Keith

      Comment


      • #4
        Thanks for the prompt reply, Keith,
        Originally posted by Keith Donald
        One thing I have considered adding is some sort of flow execution repository hook (like a listener) for responding to flow execution create/access/put and invalidate events. This is where you would have access to such a conversation identifier for logging/auditing, etc.
        +1
        That would perfectly address those use-cases, I would be delighted to help with testing or documenting this ..
        Another use-case is billing :-)

        Originally posted by Keith Donald
        The conversationId itself isn't exposed; however I'm confused as to why your view would need just it, instead of the flowExecutionKey (which is what you need to *continue* a conversation).
        Well this arises from trying to do something similar (I think) to the ajax pattern, but with SimpleFlowExecutionRepository. The use case here comes from the VXML browser world again. For each view rendered by SWF it is possible/probable that the VXML browser will make several requests to another (eg spring-mvc) controller for grammar and prompt resources. These resources need to be dynamically rendered, wrt to the current state of the SWF conversation (and beans in its scopes), but will not change the state of the flow, and so *do NOT continue* the conversation (I think the term you have used is in docs is indempotent ?).
        The obvious key to paramaterise these 'flow external' requests with is the flow conversationId, hence the requirement to write it out to the view, as per your suggestion in this post http://forum.springframework.org/sho...6&postcount=27
        sorry you will need to review the thread before it .. very similar requirement I think ..
        I have pasted your quote below ..
        Originally posted by Keith Donald
        You really should write out and submti back the conversationId instead of relying on parsing the flow execution key like that--your controller seems a little brittle elsewise.
        But how would I do this for the *first* view-state in the flow? How do I access the first flowExecutionKey, before the view is rendered, or as per my first post, I would rather just access the conversationId directly :-)

        thanks again !
        davidv

        Comment


        • #5
          How to get the value of conversationId

          I have the same requirement.

          Is there any way to get the value of the conversationId within a view (JSP) *without* parsing the flowExecutionKey?

          Comment


          • #6
            After some digging...

            I am able to proceed at the moment with the following code:

            String flowExecutionKey = request.getParameter("_flowExecutionKey");
            ServletExternalContext ctx = new ServletExternalContext(getServletContext(), request, response);
            FlowExecutionRepository repository = flowExecutionRepositoryFactory.getRepository(ctx);
            FlowExecutionKeyFormatter formatter = new FlowExecutionKeyFormatter();
            FlowExecutionKey key = (FlowExecutionKey) formatter.parseValue(flowExecutionKey, null);
            FlowExecution flow = repository.getFlowExecution(key);
            ItemSearch itemSearch = (ItemSearch) flow.getActiveSession().getScope().get("itemSearch ");

            Is there a better way? By using the "FlowExecutionKeyFormatter" at least I avoid manual parsing, and rely on the SWF api.

            Another concern: that is a lot of steps to just get hold of a flowExecution. I would expect this would be required a lot when you are combining AJAX and SWF for instance.

            A helper or something to ease this process would be nice.

            Comment


            • #7
              What do you need to do with the FlowExecution? The FlowExecutor has been designed as a coarse grained entry point into the SWF execution system and exposes a set of logical use cases. There is also a FlowRequestHandler that aids with extracting arguments needed by the executor from the external context and invoking it.

              Take a look at how FlowController (Spring MVC integration and HTTP aware) uses FlowRequestHandler to invoke FlowExecutor in 1.0 RC1. Note the use of FlowExecutorArgumentExtractor as a helper. Are the current use cases supported sufficient?

              Comment


              • #8
                Let me explain my requirement...

                Keith: I have a complex web-flow and at some point in the flow, I need to get hold of the HttpServletResponse and stream a binary file out for the client browser to download.

                Mainly because of problems with Hibernate and lazy initialization, I am using the SimpleFlowExecutionRepositoryFactory. ( I am facing problems similar to http://forum.springframework.org/showthread.php?t=20322 )

                I initially used an action with a transition to a NullView to do the HttpServletResponse stuff. If I don't use a NullView, SWF tries to render the view state (after transition) and fails because the response has already been flushed.

                So with nothing rendered after the download completes, the previous JSP still remains as the current page. But because the download event is a state transition, (and since I am not using continuations) the webflow hyperlinks on the page that the user was downloading from (including the download link itself) are not valid any more.

                So I am now trying to use your advice from this thread ( http://forum.springframework.org/sho...1&postcount=16 ). I am now using a Spring MVC MultiActionController which has been injected with the FlowExecutionRepositoryFactory to handle the download. The code I posted above works fine.

                I went through the FlowController and FlowRequestHandler like you suggested , butI'm not sure if they can help in this case where:
                - I need read only access to a particular flow scope
                - I don't want to do anything that changes the state of the flow
                - I'm not using continuations (because of Hibernate problems)
                - I need to grap the httpresponse and stream content out, so a view cannot be rendered by the controller

                Apologies if I am missing something, would really appreciate your comments and suggestions.

                Comment


                • #9
                  Updated code after seeing FlowExecutorArgumentExtractor

                  Revisited this after a while, apologies and realized I missed one of Keith's points about FlowExecutorArgumentExtractor. So no need to manually deal with the flowExecutionKey

                  So here's the updated code. flowExecutionRepositoryFactory is assumed to be available (i.e. through dependency injection)

                  Code:
                  ExternalContext externalContext = new ServletExternalContext(getServletContext(), request, response);
                  FlowExecutionRepository repository = flowExecutionRepositoryFactory.getRepository(externalContext);
                  FlowExecutorArgumentExtractor flowExecutorArgumentExtractor = new FlowExecutorArgumentExtractor();        
                  FlowExecutionKey flowExecutionKey = flowExecutorArgumentExtractor.extractFlowExecutionKey(externalContext);
                  FlowExecution flowExecution = repository.getFlowExecution(flowExecutionKey);
                  Would like to know if this looks ok. Also, would be great to hear experiences of anyone using DWR / AJAX with SWF.

                  Comment


                  • #10
                    The application we are developing executes several flows at the same time in the same user session. Then, we need to store several external contexts per session in order to execute FlowExecutor's signalEvent method.

                    We would like to use conversationId's as the keys to store the external contexts in a Map.

                    Reading above, I suppose there isn't a way to get the value of the conversationId without parsing the flowExecutionKey.

                    But flowExecutionKey can't be used as the key to store the external context because changes (the continuationId part).

                    Is there any way to get the value of the conversationId without parsing the flowExecutionKey?

                    Comment

                    Working...
                    X