Announcement Announcement Module
No announcement yet.
flowExecutionKey difficulties Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • flowExecutionKey difficulties

    I have a problem with calling an external service. My application is a simple booking system. At one point in the flow I have to call an external service that handles payment. The payment service exposes a web service that I use to set up the transaction. One of the parameters to this web service is the page that I want it to redirect the user back to, and the return value is the url that I have to redirect the user to to start payment. There are also some other data that I am passing in the web service call (user information, amount, currency etc.)

    The problem is that I don't know what url to send to the payment service for the 'redirect back to' field. I tried jumping to the payment service like this:

    	<view-state id="processPayment" view="externalRedirect:${flowScope.redirect}" >
    			<action bean="paymentAction" method="pay"/>
    		<transition on="success" to="finish"/>
    .. but I lose the correct flowExecutionKey. It's sent along as an url parameter by externalRedirect, but that's no use to me. The flowExecutionKey that's current in the call is not correct for the redirect back to the flow.

    Any ideas?


  • #2
    Why is it not correct? If it's sent via the external redirect you should be able to take that key and use it to redirect back to the flow execution to continue with a "success" event from your "processPayment" view state.


    • #3
      The one that is included in the redirected url is correct, but I don't have control of the external service, so I'm unable to pick it up. The one that is active when my entry-action is run (which is where I set up the 'callback') seems to be the flowExecutionKey for the previous state.



      • #4
        Any ideas for how I can get around this? It's a showstopper for our project.



        • #5
          do some debugging mate,

          for a while put the external service to a page written by you. check whether you get _flowExecutionKey and _x_eventId

          it should not be a problem as it is very straightforward.

          Is it also not possible that one of the flow methods call the webservice and you make the decision rather than going to the external page. AS you say it is a webservice.


          • #6
            I think I have been unable to explain my problem. I know that the flow execution key that is appended to the url that the user is redirected to is correct. But I need that key _before_ the redirect, so that I can use it in my web service call, when I set up the callback. The external service that I'm using has this usage pattern:

            1. call a web service to set up a payment transaction. I send payment details and the 'callback url' and get a payment id and a redirection url back.

            2. redirect the user to the redirection url that I received in step 1.

            3. the payment service takes the user through a number of steps, and then redirects the user to the callback url I sent in step 1.

            4. my application makes another webservice call to confirm the payment, using the payment id that I received in step 1.

            And my problem is that the flow execution key that I need to include in my 'callback url' is not available to me before the redirection is done.



            • #7
              I see Magnus.

              So to confirm what you need here: you need a flow action to invoke your web service and pass it the flow execution key. You're having trouble because you don't know how to get a hold of this key from inside your flow execution.




              • #8
                I think that is correct, yes. I tried
                String key = rc.getExternalContext().getRequestParameterMap().get("_flowExecutionKey")
                but that gets me the previous key, of course.

                Last edited by Mammux; Jun 19th, 2006, 04:17 AM.


                • #9

                  try using the SingleKeyFlowExecutionRepository flow execution factory, bean setup like
                  	<bean id="flowExecutor"
                  		<constructor-arg ref="repositoryFactory"/>
                  		<property name="redirectOnPause" value="false"/>
                  	<bean id="repositoryFactory" class="">
                  		<constructor-arg ref="flowRegistry"/>
                  	<bean id="flowRegistry"
                  		<property name="flowLocations" value="/WEB-INF/flows/**/*-flow.xml"/>
                  (not sure about the redirectOnPause attribute though). I think this factory came with rc2.

                  I got this solution working with a similar scenario as yours. I capture the flow execution key the same way as you earlier in the flow. The controller handling the feedback from the external service returns a redirect with the flow id, key and event name back to the client which is then able to resume the flow.



                  • #10
                    I would do that or something similar, but I am otherwise very happy with the behaviour that the ContinuationFlowExecutionRepository gives me. I hestitate to sacrifice good back-button behaviour to get this.

                    Your reply made me a bit uncertain, Keith. Is there a way to get the current flow exection key inside an action?



                    • #11
                      This problem is still frustrating me. Can I get at the flow execution key inside my action (using ContinuationFlowExecutionRepository)?



                      • #12
                        Frustrating me too.
                        Please enlighten us Keith
                        Last edited by Kees de Kooter; Aug 15th, 2006, 09:07 AM.


                        • #13
                          Well, the problem is the "new" flow execution key is not assigned until after execution request processing, when the active execution (now paused) is placed back into its repository. This makes sense, as the execution could end at which is should be removed from the repository all together (and no new key generated at all).

                          One possible solution may be to have a hook within the repository for issuing this web service call, introspecting on flow state to make it. That would be possible I guess, though it's not the most object oriented solution in the world, as within the repository you'd have to introspect the flow execution to see if it paused in the state mandating the WS call. In addition, you'd also have to override the view selection so you could make the proper redirect selection outside the control of the flow.

                          I guess past we could eagerly generate the new key, bind it to the current thread, and just throw it away if the execution ends. Not sure if I like that either, though.

                          So I just don't see an elegant solution yet... ideas appreciated. I guess there is a fundamental question if the execution itself should have knowledge of its key for a given request, and what that key really means in that context... so far we've treated the key as a repository-only concept. It's in the repository package for that reason.

                          Last edited by Keith Donald; Aug 17th, 2006, 01:58 PM.


                          • #14
                            Hack to get flowExecutionKey

                            I'm pretty sure this is a hack that's ugly beyond belief, but this worked for me:
                            Create a new class

                            public class MyFlowExecutorArgumentExtractor extends FlowExecutorArgumentExtractor {
                            	public String createExternalUrl(ExternalRedirect redirect, FlowExecutionKey flowExecutionKey, ExternalContext context) {
                            		String result = super.createExternalUrl(redirect, flowExecutionKey, context);
                            		String key = new FlowExecutionKeyFormatter().formatValue(flowExecutionKey);
                            		result = result.replaceAll("NEWFLOWKEY", key);
                            		return result;
                            and use this as the ArgumentExtractor in the FlowController

                            <bean name="flowController" class="org.springframework.webflow.executor.mvc.FlowController">
                            	<property name="flowExecutor" ref="flowExecutor"/>
                            	<property name="argumentExtractor" ref="myFlowExecutorArgumentExtractor"/>
                            Finally, adapt your flow.xml:

                            <view-state id="myView" view="externalRedirect:">
                            Now, you can use this NEWFLOWKEY in everything you put in the query parameters, so also in an XML-like parameter.

                            I'll be much interested in a cleaner solution, though.


                            • #15
                              Return to previous state

                              I'm not sure if you've already solved the issue, but I've just gone throught the same type problem, with the same steps as you outlined with your payment provider.

                              The way I got through the webflow structure, was to return the user to the state they were in before they left, so you actually just reuse the old flowExecutionKey, but provide a new eventId when building the callback url.

                              This may not quite follow web flow's intended usage pattern, it does achieve what you want to get done, and is clean

                              Hope that helps.