How I will enter into web flow from any point in Spring MVC web app? Spring Web Flow webapp is not working

StackOverflow https://stackoverflow.com/questions/21808883

Question

I have been trying to develop an multi-page user registration form using Spring Web Flow but could not completed. Later on I am going to paste my application code in this post. I would be grateful to one who identify the missing part or error and guide me to resolve the same.

My webapp name is 'UserRegistrationSWF'. Here is the directory structure:

UserRegistrationSWF
     -Java Resources
         -src
            -org.nitest.controller
                -UserRegistrationController.java
            -org.nitesh.model
                -User.java
     -WebContent
         -WEB-INF
            -config
                -swf-config.xml
                -web-application-config.xml
            -swf
                -swf-flow.xml
                -userRegistrationPage2.jsp
                -userRegistrationLastPage.jsp
            -view
                -cancel.jsp
                -success.jsp
                -userRegistrationStartPage.jsp
            -web.xml     
         -index.jsp

I am using Spring MVC and my welcome page is 'index.jsp'. Here is the code:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome Page</title>
</head>
<body>
<a href="userRegistrationStartPage.htm">User Registration</a>
</body>
</html>

Here is 'web.xml' code:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-    app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

  <display-name>UserRegistrationSWF</display-name>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/config/web-application-config.xml</param-value>
  </context-param>

  <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>User Registration</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>User Registration</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>

</web-app>

Here is the 'web-application-config.xml' code:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">

    <mvc:annotation-driven/>
    <context:component-scan base-package="org.nitesh" />

    <bean id="jspViewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

<import resource="swf-config.xml"/> 

</beans>

Here is the 'swf-config.xml' code:

<?xml version="1.0" encoding="UTF-8"?>
<beans xsi:schemaLocation=" http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
http://www.springframework.org/schema/webflow-config 
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd" 
xmlns:webflow="http://www.springframework.org/schema/webflow-config" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://www.springframework.org/schema/beans">

<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location path="/swf/swf-flow.xml" />
</webflow:flow-registry>

<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
</webflow:flow-executor>

<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
    <property name="flowExecutor" ref="flowExecutor" />
</bean>

<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
    <property name="flowRegistry" ref="flowRegistry"/>
</bean>

</beans>

Here is the 'swf-flow.xml' code:

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">

<view-state id="userRegistrationStartPage" view="userRegistrationStartPage.htm" model="user">
<transition on="cancel" to="cancel"></transition>
<transition on="proceed" to="userRegistrationPage2"></transition>
</view-state>

<view-state id="userRegistrationPage2" view="userRegistrationPage2.htm">
<transition on="revise" to="userRegistrationStartPage"></transition>
<transition on="proceed" to="userRegistrationLastPage"></transition>
<transition on="cancel" to="cancel"></transition>
</view-state>

<view-state id="userRegistrationLastPage" view="userRegistrationLastPage.htm">
<transition on="revise" to="userRegistrationPage2"></transition>
<transition on="confirm" to="success"></transition>
<transition on="cancel" to="cancel"></transition>
</view-state>

<end-state id="success" view="swf/success.jsp"></end-state>

<end-state id="cancel" view="swf/cancel.jsp"></end-state>

</flow>

Here is the 'userRegistrationStartPage.jsp' code:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>User Registration Start Page</title>
</head>
<body>
<form:form commandName="user" method="POST">

<table>
<tr>
<td>Name:</td>
<td><form:input path="name"/></td>
</tr>

<tr>
<td>Email:</td>
<td><form:input path="email"/></td>
</tr>

<tr>
<td>Password:</td>
<td><form:password path="password"/></td>
</tr>

<tr>
<td><input type="submit" name="_eventId_cancel" value="Cancel"></td>
<td><input type="submit" name="_eventId_proceed" value="Next"></td>
</tr>

</table>
</form:form>
</body>
</html>

The 'cancel.jsp' and 'success.jsp' simply prints cancel and success message respectively. The 'User' class is a userRegistrationStartPage form bean class. The 'userRegistrationPage2.jsp' and 'userRegistrationLastPage.jsp' Simply prints messgage for now.

Here is web app controller 'UserRegistrationController.java' code:

package org.nitesh.controller;

import org.nitesh.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class UserRegistrationController {

    @RequestMapping(value = "userRegistrationStartPage.htm")
    public ModelAndView showUserRegistrationFormStartPage(@ModelAttribute("user") User user)
    {
        return new ModelAndView("userRegistrationStartPage");
    }

}

Preceding is the web app codes. Now I would like to come to my questions: 1. How I will enter into web flow from any point in Spring MVC web app? I mean how I will take entry into web flow by clicking following link in 'index.jsp':

<a href="userRegistrationStartPage.htm">User Registration</a>
  1. Above mentioned webapp is not working, what more is missing that do I need to add or change in order to make it working?

I am really looking forward to hear the answer from one.

Thanks.

Was it helpful?

Solution

You're almost there:

It's a best practice to add all elements of your flow in one folder. So move the first page of your flow named 'userRegistrationStartPage.jsp' from /view/ to /swf/

-WebContent
    -WEB-INF
        -config
            -swf-config.xml
            -web-application-config.xml
        -swf
            -swf-flow.xml
            -userRegistrationStartPage.jsp
            -userRegistrationPage2.jsp
            -userRegistrationLastPage.jsp
        -view
            -cancel.jsp
            -success.jsp                
        -web.xml     
     -index.jsp

Because you defined a flow in your swf-config.xml

<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location path="/swf/swf-flow.xml" />
</webflow:flow-registry>

The mapping to start that flow will be swf (the first part of the path) Change your index.jsp to the following

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Welcome Page</title>
    </head>
    <body>
        <a href="swf">User Registration</a>
    </body>
</html>

Also, because you're using a User object to store the registration information, you need to create one at the start of the flow. See the the booking-mvc example of spring webflow where a Hotel object is needed at the start of the flow:

<flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <input name="hotelId" required="true" />

    <on-start>
        <evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
    </on-start>

    <view-state id="enterBookingDetails" model="booking">
        etc...
    </view-state>
</flow>

Here they use a service to get a hotel from the database, YMMV.

Lastly, the UserRegistrationController isn't needed, so you can remove it.

Update

The quickest way to create a new User object at the start of your flow would be to add the following line at the beginning of swf-flow.xml:

<on-start>
    <evaluate expression="new org.nitesh.model.User()" result="flowScope.user" />
</on-start>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top