Announcement Announcement Module
Collapse
No announcement yet.
Spring Web Flow 2 bare-bones app Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Web Flow 2 bare-bones app

    I've been trying to create a bare-bones SWF application. I'm using SWF 2.0.3, Spring and Spring-webmvc 2.5.5, JSF (using MyFaces 1.1.5), and Facelets 1.1.14. My IDE is JDeveloper 10.1.3.3.

    So far, no success. I can get a simple app up using MyFaces and Facelets, but nothing when I try to add in Spring MVC and SWF.

    I'm not able to download the sample applications at work, so I have no runnable reference apps to compare to.

    I think the source of much of my confusion is with the configuration in web.xml and other config files, and how a web flow is invoked once everything is configured correctly.

    I've looked at the SWF 2.0 docs for JSF integration. I'm not certain if I also need to follow the section on Spring MVC integration (doesn't SWF need Spring MVC to run?).

    So here's what I have so far:

    /WEB-INF/web.xml
    Code:
    <web-app>
      <!-- It's using servlet 2.4, I'm not allowed to post URLs on this forum yet-->
    
      <!-- The master configuration file for this Spring web application -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>
    			/WEB-INF/config/web-application-config.xml
    		</param-value>
    	</context-param>
      
      <!-- Use JSF view templates saved as *.xhtml, for use with Facelets -->
      <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
      </context-param>
      <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>true</param-value>
      </context-param>
      
      <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
      </listener>
      
        <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
        
      <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
      </servlet-mapping>
      
      <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
      </servlet-mapping>
      
      <!-- Serves static resource content from .jar files such as spring-faces.jar -->
      <!--<servlet>
        <servlet-name>Resource Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>Resource Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
      </servlet-mapping>-->
    </web-app>
    /WEB-INF/faces-config.xml
    Code:
    <faces-config><!--Still not allowed to post URLs-->
      <application>
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
        <variable-resolver>org.springframework.faces.webflow.SpringBeanWebFlowVariableResolver</variable-resolver>
      </application>
    </faces-config>
    /WEB-INF/config/web-application-config.xml
    Code:
    <beans>
        <!--Can't post URLs!-->
               <!-- Executes flows: the central entry point into the Spring Web Flow system -->
    	<webflow:flow-executor id="flowExecutor" />
    
    	<!-- The registry of executable flow definitions -->
    	<webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/WEB-INF">
    		<webflow:flow-location-pattern value="**/*-flow.xml" />
    	</webflow:flow-registry>
    
    	<!-- Configures the Spring Web Flow JSF integration -->
    	<faces:flow-builder-services id="facesFlowBuilderServices"/>
    </beans>
    /WEB-INF/flows/tutorial-flow.xml
    Code:
    <flow start-state="guess">
      <!--No URLs allowed!-->
    
      <var class="tutorial.NumberBean" name="NumberBean"/>
      
      <view-state id="guess" view="/guess.xhtml">
      </view-state>
    </flow>
    NumberBean exists. guess.xhtml is in my web directory above WEB-INF, and uses facelets. The page itself works fine when I tested it with just Facelets and MyFaces using ".../app-context-root/guess.faces"

    So, based on the above configuration files...

    1. Does anyone see anything wrong or missing in my configuration files? Or where any of my files are located?

    2. What URL do I need to use to start the tutorial web flow? I've used ".../app-context-root/tutorial", ".../app-context-root/tutorial-flow", ".../app-context-root/flows/tutorial" and ".../app-context-root/flows/tutorial-flow" without success.

    3. If anyone's extremely generous or happens to have the time on their hands, I'd love to see a tested and working bare-bones hello world app.

    Thanks in advance!

  • #2
    Okay, I've been referencing the swf-booking-faces example project, trying to mimic the config files and get something to work. Still no luck. Here's what I've got:

    /WEB-INF/web.xml
    I added the Resource Servlet and the ContextLoaderListener.
    Code:
    <web-app> 
    <!-- It's using servlet 2.4, I'm not allowed to post URLs on this forum yet-->
    
    <!-- The master configuration file for this Spring web application -->
    	<context-param>
    		<param-name>contextConfigLocation</param-name>
    		<param-value>
    			/WEB-INF/config/web-application-config.xml
    		</param-value>
    	</context-param>
      
      <!-- Use JSF view templates saved as *.xhtml, for use with Facelets -->
      <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
      </context-param>
      <context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
        <param-value>true</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.validateXml</param-name>
        <param-value>true</param-value>
      </context-param>
      <context-param>
        <param-name>com.sun.faces.verifyObjects</param-name>
        <param-value>true</param-value>
      </context-param>
      
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
      </listener>
      
      <servlet>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
      </servlet>
        
      <servlet-mapping>
        <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
        <url-pattern>/spring/*</url-pattern>
      </servlet-mapping>
      
      <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
      </servlet-mapping>
      
      <!-- Serves static resource content from .jar files such as spring-faces.jar -->
      <servlet>
        <servlet-name>Resource Servlet</servlet-name>
        <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
        <load-on-startup>0</load-on-startup>
      </servlet>
      
      <servlet-mapping>
        <servlet-name>Resource Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
      </servlet-mapping>
    </web-app>
    /WEB-INF/faces-config.xml
    I removed the variable resolver. The booking example app doesn't use it.
    Code:
    <faces-config><!--Still not allowed to post URLs-->
      <application>
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
      </application>
    </faces-config>
    /WEB-INF/config/web-application-config.xml
    It's now referencing two separate config files
    Code:
    <beans>
    	<import resource="webmvc-config.xml" />
    	<import resource="webflow-config.xml" />
    </beans>
    /WEB-INF/config/webmvc-config.xml
    Copied from the booking project.
    Code:
    <beans>
    	<!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->			
    	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
        <property name="flowRegistry" ref="flowRegistry"/>
    		<property name="defaultHandler">
    			<!-- Selects view names to render based on the request URI: e.g. /main selects "main" -->	
    			<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
    		</property>
    	</bean>
    
    	<!-- Maps logical view names to Facelet templates (e.g. 'search' to '/WEB-INF/search.xhtml' -->
    	<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    		<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
    		<property name="prefix" value="/WEB-INF/" />
    		<property name="suffix" value=".xhtml" />
    	</bean>
      
      <!-- Dispatches requests mapped to org.springframework.web.servlet.mvc.controller implementations -->
      <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
      
      <!-- Dispatches requests mapped to flows to FlowHandler implementations -->
      <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
        <property name="flowExecutor" ref="flowExecutor"/>
      </bean>
    		
    </beans>
    /WEB-INF/config/webflow-config.xml
    Copied from booking project.
    Code:
    <beans>
    	<!-- Executes flows: the central entry point into the Spring Web Flow system -->
    	<webflow:flow-executor id="flowExecutor">
    	</webflow:flow-executor>
    	
    	<!-- The registry of executable flow definitions -->
    	<webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices" base-path="/WEB-INF/flows">
    		<webflow:flow-location-pattern value="/**/*-flow.xml" />
    	</webflow:flow-registry>
    	
    	<!-- Configures the Spring Web Flow JSF integration -->
    	<faces:flow-builder-services id="facesFlowBuilderServices" development="true"/>
    
    </beans>
    /WEB-INF/flows/main/main.xml
    My only flow definition.
    Code:
    <flow>
      <var class="tutorial.NumberBean" name="NumberBean"/>
      
      <view-state id="guess">
      </view-state>
    </flow>
    /WEB-INF/flows/main/guess.xhtml
    /WEB-INF/flows/main/response.xhtml
    Simple Facelets xhtml files. These work correctly with just Facelets.

    /intro.xhtml
    A simple facelets page, with
    Code:
    <a href="main">Start</a>
    , as seen in the intro.xhtml page in the booking project. The link should start off the flow.

    With the configuration files such above, I get a "Cannot find server", even when I try to hit /intro.xhtml. It's like facelets stops working. Nothing I try, any combination of "/main", "/spring/main", etc. invokes the flow.

    Curiously, when I remove the ContextLoaderListener from web.xml, I'm able to hit /intro.xhtml, so facelets is working on its own again. However, clicking the link (or manually trying to form the URL to invoke the flow) gets me a page not found.

    On a separate note, I was able to follow a different tutorial and set up a project using Spring MVC and SWF, so I know it's possible to use them with my setup. I just need to get this SWF / JSF integration down.

    So, any help, suggestions, or insights?

    Thanks in advance!
    Last edited by InverseFalcon; Dec 4th, 2008, 05:37 PM.

    Comment


    • #3
      Where's your Spring controller mapping? you might need something like this:


      <!-- Maps request URIs to controllers -->
      <bean
      class="org.springframework.web.servlet.handler.Sim pleUrlHandlerMapping">
      <property name="mappings">
      <props>
      <prop key="/f/*">flowController</prop>
      </props>
      </property>
      <property name="defaultHandler">
      <bean
      class="org.springframework.web.servlet.mvc.UrlFile nameViewController" />
      </property>
      </bean>

      Comment


      • #4
        It wasn't there in my first post. I copied over the configuration info from the sample booking project. See the webmvc-config.xml in my second post.

        Comment


        • #5
          Did you take a look at this example? I think it has everything that you need

          java.dzone.com/articles/spring-web-flow-crud-tutorial

          Comment


          • #6
            Thanks, md10024, that project is a much better guide. I was able to DL the project on my personal laptop and use that as a guide for a HelloWorld app on my work machine. Still no luck, though. When I put it all together, I can't even get it to open up a simple html or facelets .xhtml file without a Page Not Found. The console isn't giving me anything to work with either, besides the invalid TLD 2.1 message. I don't think that's the showstopper, though. I'm not trying to use anything other than simple JSF and Facelets tags (both of which ran fine before I tried introducing Spring MVC and SWF).

            I tried to make this project as simple as possible. I'm not using any .java files at all, just trying to get the SWF and view files working. Here are the relevant files for this new HelloWorld project.

            /WEB-INF/web.xml
            Code:
            <web-app>
              <context-param>
                <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                <param-value>.xhtml</param-value>
              </context-param>
              <context-param>
                <param-name>facelets.DEVELOPMENT</param-name>
                <param-value>true</param-value>
              </context-param>
              <context-param>
                <param-name>facelets.REFRESH_PERIOD</param-name>
                <param-value>1</param-value>
              </context-param>
                
              <listener>
                <listener-class>
                  project1.Listener
                </listener-class>
              </listener>
                
              <servlet>
                <servlet-name>faces</servlet-name>
                <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
              </servlet>
              
              <servlet-mapping>
                <servlet-name>faces</servlet-name>
                <url-pattern>*.faces</url-pattern>
              </servlet-mapping>
              
              <!-- Spring MVC front controller. Automatically loads mycart-servlet.xml
                     based on servlet name. -->
                <servlet>
                    <servlet-name>dispatcher</servlet-name>
                    <servlet-class>
                        org.springframework.web.servlet.DispatcherServlet
                    </servlet-class>
                    <init-param>
                      <param-name>contextConfigLocation</param-name>
                      <param-value>/WEB-INF/config.xml</param-value>
                    </init-param>
                    <load-on-startup>2</load-on-startup>
                </servlet>
              
                <servlet-mapping>
                    <servlet-name>dispatcher</servlet-name>
                    <url-pattern>/s/*</url-pattern>
                </servlet-mapping>
            </web-app>
            /WEB-INF/faces-config.xml
            Code:
            <faces-config>
              <application>
                <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
              </application>
            </faces-config>
            /WEB-INF/config.xml
            Code:
            <beans>
            <!-- SPRING MVC STUFF -->
                <!-- Maps flow requests from DispatcherServlet to flowController -->
                <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                    <property name="mappings">
                        <props>
                          <prop key="/f/*">flowController</prop>
                        </props>
                    </property>
                    <property name="defaultHandler">
                      <!-- Selects view names to render based on the request URI: e.g. /main selections "main" -->
                      <bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
                    </property>
                </bean>
                
                
                <!-- SPRING WEB FLOW STUFF -->
                
                <bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController"/>
              
                <!-- Maps logical view names to Facelet templates (e.g. 'search' to '/WEB-INF/search.xhtml' -->
                <bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
                  <property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
                  <property name="prefix" value="/WEB-INF/"/>
                  <property name="suffix" value=".xhtml"/>
                </bean>
            
                <webflow:flow-executor id="flowExecutor"/>
                
                <!-- This creates an XmlFlowRegistryFactory bean -->
                <webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices">
                    <webflow:flow-location-pattern value="/WEB-INF/flows/**/*.xml"/>
                </webflow:flow-registry>
                
                <faces:flow-builder-services id="facesFlowBuilderServices"
                        expression-parser="expressionParser"/>
                        
                <bean id="expressionParser" class="org.springframework.webflow.expression.WebFlowOgnlExpressionParser"/>
            </beans>
            /WEB-INF/layouts/standard.xhtml
            Template for facelet views
            Code:
            <html>
              <f:view>
                <head>
                  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
                </head>
                <body>
                  <p>Hello!</p>
                  <ui:insert name="content"/>
                </body>
              </f:view>
            </html>
            /WEB-INF/flows/home.xhtml
            Code:
            <ui:composition template="/WEB-INF/layouts/standard.xhtml">
              <ui:define name="content">
                <h:form>
                  <h:outputText value="Testing"/>
                  <h:commandButton value="Say Hello" action="sayHello"/>
                </h:form>
              </ui:define>
            </ui:composition>
            /WEB-INF/flows/helloWorld.xhtml
            Code:
            <ui:composition template="/WEB-INF/layouts/standard.xhtml">
              <ui:define name="content">
                <h:form>
                  <h:outputText value="Hello, World!"/>
                  <h:commandButton value="Done" action="done"/>
                </h:form>
              </ui:define>
            </ui:composition>
            /WEB-INF/flows/home.xml
            This is the only flow definition.
            Code:
            <flow>
                <!-- By default, the first state is the start state. -->
                <view-state id="home">
                    <transition on="sayHello" to="helloWorld"/>
                </view-state>
                
                <view-state id="helloWorld">
                  <transition on="done" to="goodbye"/>
                </view-state>
                
                <end-state id="goodbye"/>
            </flow>
            /index.html
            Startup file, should launch the flow
            Code:
            <html>
              <head>
                <meta http-equiv="Refresh" content="0; URL=s/f/home">
              </head>
            </html>
            /test.xhtml
            Test facelets view, a sanity check to see if at least facelets is working. It's currently not working for my project, thus at least some part of the project is insane.
            Code:
            <ui:composition template="/WEB-INF/layouts/standard.xhtml">
              <ui:define name="content">
                <h:form>
                  <h:outputText value="If you can see this, it might be working"/>
                </h:form>
              </ui:define>
            </ui:composition>
            /WEB-INF/lib
            Project dependencies and such
            Code:
            commons-beanutils-1.7.jar
            commons-codec-1.3.jar
            commons-collections.3.2.jar
            commons-digester-1.8.jar
            commons-fileupload-1.0.jar
            commons-lang-2.3.jar
            commons-logging-1.0.4.jar
            jakarta-oro-0.0.0.jar
            jsf-facelets-1.1.14.jar
            myfaces-api-1.1.5.jar
            myfaces-impl-1.1.5.jar
            ognl-2.6.9.jar
            org.springframework.binding-2.0.3.jar
            org.springframework.faces-2.0.3.jar
            org.springframework.js-2.0.3.jar
            org.springframework.webflow-2.0.3.jar
            spring-2.5.5.jar
            spring-webmvc-2.5.5.jar
            As for the rest of the environment, IDE is JDeveloper 10.1.3.3, and I think I'm using Servlet 2.4 and JSP 2.0.

            Whatever is going wrong, it's stopping me dead in my tracks. I've got a servlet listener to at least let me know the app is running, but I can't access any html or xhtml files or launch the flow by any means. The console's giving me nothing but this:

            Code:
            Dec 8, 2008 4:08:39 PM oracle.jsp.logger.JspMessages warningInvalidTldVersion
            WARNING: Invalid or unsupported tld version: 2.1
            08/12/08 16:08:39 listener created
            08/12/08 16:08:39 Context initialized

            Comment


            • #7
              Finally got SWF up and running!

              Adding log4j to the project finally let me see some error messages.

              I had to switch over to MyFaces 1.2.3 and add the el-api and el-impl jar files, as well as commons-discovery.

              I also forgot to add the flowExecutor property to my flowController bean:

              Code:
              <bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
                    <property name="flowExecutor" ref="flowExecutor"/>
              </bean>
              Also, added the MyFaces StartupServletContextListener to web.xml would have helped:

              Code:
              <listener>
                  <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
              </listener>

              Comment


              • #8
                You might want to upgrade to 2.0.5 which has greatly reduced the amount of setup config required to get Web Flow up and running. booking-faces's mvc-config.xml and webflow-config.xml shows the new setup.

                Keith

                Comment


                • #9
                  Hi Keith,

                  I have upgraded to 2.0 and checked the API for FlowNavigationHandler, but could not find that.

                  Code:
                  <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>

                  I am using Webflow2.0 with IceFaces. Everything works fine with Webflow1.x.

                  Please let me know the similar handlers and listeners.

                  Thanks,
                  Vijay

                  Comment


                  • #10
                    did you every getting this working? I am trying to do the same thing now and having no luck

                    Comment


                    • #11
                      I still could not get my HelloWorld working.. can someone look at this war

                      I posted the war with the source here on dropbox https://www.dropbox.com/s/5mojqctfqk...oWorldFlow.war

                      Please let me know if you can help

                      Comment

                      Working...
                      X