Announcement Announcement Module
Collapse
No announcement yet.
1.1M1 snapshot, <flow:enable-scopes> Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 1.1M1 snapshot, <flow:enable-scopes>

    I tried 1.1M1 snapshot, <flow:enable-scopes>.
    However, I failed to launch a new flow.

    summary of stacktrace:
    Code:
    2007-05-08 15:31:24,921 [http-8080-Processor25] ERROR org.apache.myfaces.lifecycle.PhaseListenerManager - Exception in PhaseListener RESTORE_VIEW(1) beforePhase.
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'PhonebookFlowData': Scope 'flow' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No flow execution context is bound to this thread
    Caused by: 
    java.lang.IllegalStateException: No flow execution context is bound to this thread
        at org.springframework.util.Assert.state(Assert.java:354)
        at org.springframework.webflow.execution.FlowExecutionContextHolder.getFlowExecutionContext(FlowExecutionContextHolder.java:55)
        at org.springframework.webflow.config.scope.AbstractWebFlowScope.getFlowExecutionContext(AbstractWebFlowScope.java:113)
        at org.springframework.webflow.config.scope.FlowScope.getScope(FlowScope.java:32)
    
        ...
    
        at org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl.getFlowDefinition(FlowDefinitionRegistryImpl.java:128)
        at org.springframework.webflow.executor.jsf.FlowPhaseListener.restoreFlowExecution(FlowPhaseListener.java:310)
    
        ...
    For more details:
    http://opensource.atlassian.com/proj...browse/SWF-163

  • #2
    Details

    If possible can I get some additional information from you? Specifically from the issue, what does 'PhonebookFlowAction refers PhonebookFlowData' mean? Is PhonebookFlowData passed in as an argument to the bean or is gained by dependency injection? Second, can you post in what your faces-config file shows?

    -Ben Hale

    Comment


    • #3
      Spring beans:
      Code:
        <bean name="PhonebookFlowAction"
            class="foo.phonebook.PhonebookFlowAction"
            scope="request"
            autowire="byType"
            dependency-check="objects">
      
        </bean>
      
        <bean name="PhonebookFlowData"
            class="foo.phonebook.PhonebookFlowData"
            scope="flow"
            autowire="no"
            dependency-check="none">
      
        </bean>
      
        <flow:executor id="flowExecutor" registry-ref="flowRegistry">
          <flow:repository type="simple" />
          <flow:execution-listeners>
            <flow:listener ref="jsfFlashMessageListener" />
          </flow:execution-listeners>
        </flow:executor>
      
        <flow:registry id="flowRegistry">
          <flow:location path="/WEB-INF/classes/foo/phonebook/**/*Flow.xml" />
        </flow:registry>
      
        <flow:enable-scopes />
      
        <bean id="jsfFlashMessageListener"
            class="foo.message.JsfFlashMessageListener" />
      
        ...
      faces-config.xml:
      Code:
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE faces-config PUBLIC
          "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
          "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
      <faces-config>
      
        <application>
          <navigation-handler>
            org.springframework.webflow.executor.jsf.FlowNavigationHandler
          </navigation-handler>
          <variable-resolver>
            org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver
          </variable-resolver>
        </application>
      
        <lifecycle>
          <phase-listener>
            org.springframework.webflow.executor.jsf.FlowPhaseListener
          </phase-listener>
        </lifecycle>
      
        <!-- for MyFaces -->
        <converter>
          <converter-for-class>java.math.BigDecimal</converter-for-class>
          <converter-class>javax.faces.convert.BigDecimalConverter</converter-class>
        </converter>
        <converter>
          <converter-for-class>java.math.BigInteger</converter-for-class>
          <converter-class>javax.faces.convert.BigIntegerConverter</converter-class>
        </converter>
      
      </faces-config>

      Comment


      • #4
        How are you achieving the request scope for the FlowAction? Are you using Spring's RequestContextListener?

        Comment


        • #5
          No. I'm using RequestContextFilter.

          Code:
            <filter>
              <filter-name>RequestContextFilter</filter-name>
              <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
            </filter>
          
            <filter-mapping>
              <filter-name>RequestContextFilter</filter-name>
              <url-pattern>*.faces</url-pattern>
            </filter-mapping>
          
            <filter-mapping>
              <filter-name>RequestContextFilter</filter-name>
              <url-pattern>*.jsp</url-pattern>
            </filter-mapping>

          Comment


          • #6
            Probably

            FlowPhaseListener.java:
            310 FlowDefinition flowDefinition = getLocator(context).getFlowDefinition(flowId);
            -> IllegalStateException
            313 FlowExecutionHolderUtils.setFlowExecutionHolder(ho lder, facesContext);
            -> flow-scoped bean enabled.

            Comment


            • #7
              It appears that the problem is how you are initializing your beans with different scopes. Since the request scope is created and initialized at a different time (in this case before) the flow scope is, when you try and do dependency injection it will fail with the exception you showed. There are two ways to solve this problem.

              First, you can solve this particular issue by simply adding <aop:scoped-proxy/> to your data bean if it implements an interface (http://static.springframework.org/sp...her-injection).

              Code:
              <bean name="PhonebookFlowData"
                      class="foo.phonebook.PhonebookFlowData"
                      scope="flow"
                      autowire="no"
                      dependency-check="none">
                  <aop:scoped-proxy/>
              </bean>
              Basically what will happen is a proxy will be injected in place of the real bean when the FlowAction is created. Then when the real object is needed (presumably within the flow execution) it will be looked up by the proxy and there should be no issue.

              That solution should solve the symptom you're seeing, but really you should think about a different manner of getting data to the FlowAction. Really you should be looking to have a conversation-scoped data object that is being bound to by the JSF components and then pass it as an argument to some method on the FlowAction. This way there is no dependency that needs to be proxied out and lazily injected.

              Comment


              • #8
                By adding <aop:scoped-proxy />, I can launch a new flow.
                However JSF value binding (ex. value="#{PhonebookFlowData.list}") does not work.
                In the flow scope,
                "PhonebookFlowData" attribute does not exist,
                and "scopedTarget.PhonebookFlowData" exists.
                This is caused by <aop:scoped-proxy />.

                Comment


                • #9
                  Sorry.
                  By adding org.springframework.web.jsf.DelegatingVariableReso lver,
                  value binding works well.
                  Thanks for your help.

                  Comment


                  • #10
                    JSF deferred expression (ex. value="#{PhonebookFlowData.list}") works,
                    but immediate expression (ex. value="${PhonebookFlowData.list}") does not work.

                    I expected that the bean of bean-action is instantiated when action performed.
                    However, the bean is instantiated before the start of the flow.
                    Can I delay the creation of the bean?
                    Or, do other ways exist?

                    Comment


                    • #11
                      I found a workaround.

                      SWF:
                      Code:
                        <start-state idref="start" />
                      
                        <action-state id="start">
                          <evaluate-action expression="externalContext.applicationMap['org.springframework.web.context.WebApplicationContext.ROOT'].getBean('phonebookFlowAction').start()" />
                        </action-state>
                      
                        <subflow-state id="INPUT_FLOW" flow="InputFlow">
                          <attribute-mapper>
                            <input-mapper>
                              <mapping source="externalContext.applicationMap['org.springframework.web.context.WebApplicationContext.ROOT'].getBean('phonebookFlowData').inputFlowParam" target="flowParam" />
                            </input-mapper>
                            <output-mapper>
                              <mapping source="flowParam" target="externalContext.applicationMap['org.springframework.web.context.WebApplicationContext.ROOT'].getBean('phonebookFlowData').inputFlowParam" />
                            </output-mapper>
                          </attribute-mapper>
                          <transition to="afterInputFlow" />
                        </subflow-state>
                      
                        <action-state id="afterInputFlow">
                          <evaluate-action expression="externalContext.applicationMap['org.springframework.web.context.WebApplicationContext.ROOT'].getBean('phonebookFlowAction').afterInputFlow()" />
                        </action-state>
                      
                        ...
                      Spring Beans:
                      Code:
                        <bean id="phonebookFlowAction"
                            class="foo.phonebook.PhonebookFlowAction"
                            scope="request"
                            autowire="byType"
                            dependency-check="objects" />
                      
                        <bean id="phonebookFlowData"
                            class="foo.phonebook.PhonebookFlowData"
                            scope="flow" />
                      
                        ...
                      However, I hope that SWF become easier.
                      Thanks.
                      Last edited by slopetown; May 17th, 2007, 11:49 AM.

                      Comment


                      • #12
                        Thanks so much for your reply,

                        I changed the scope to request. Added the following listener in the web.xml and things have started working.
                        <listener> <listener-class>org.springframework.web.context.request.Requ estContextListener</listener-class>
                        </listener>

                        I appreciate all your help.

                        Regards,
                        Shashi

                        Comment


                        • #13
                          I raised this issue.
                          http://opensource.atlassian.com/proj...browse/SWF-312

                          and Shashi, you are replying to a wrong thread.

                          Comment


                          • #14
                            I believe the changes I have submitted for SWF-287 and SWF-301 would allow this to work in a JSF environment as follows with no additional work:

                            Code:
                            <action-state id="start">
                                <evaluate-action expression="#{phonebookFlowAction.start()}" />
                              </action-state>
                            
                              <subflow-state id="INPUT_FLOW" flow="InputFlow">
                                <attribute-mapper>
                                  <input-mapper>
                                    <mapping source="#{phonebookFlowData.inputFlowParam}" target="flowParam" />
                                  </input-mapper>
                                  <output-mapper>
                                    <mapping source="flowParam" target="#{phonebookFlowData.inputFlowParam}" />
                                  </output-mapper>
                                </attribute-mapper>
                                <transition to="afterInputFlow" />
                              </subflow-state>
                            
                              <action-state id="afterInputFlow">
                                <evaluate-action expression="#{phonebookFlowAction.afterInputFlow()}" />
                              </action-state>
                            It might be interesting to consider how to also make this work in a non-JSF application that is configured to use the ELExpressionParser. This could be done rather simply by providing an alternate ELContext implementation that is preconfigured to use the DelegatingVariableResolver from the JSF integration.

                            -Jeremy

                            Comment


                            • #15
                              This is a very attractive idea.
                              <evaluate-action> is easier than <bean-action>.
                              However, I plan to use SWF+Struts.
                              If this doesn't work in non-JSF environment, I cannot use this.
                              Therefore, I think.
                              Why cannot OGNL be used for the same purpose?

                              Comment

                              Working...
                              X