Search code examples
javaspring-webflow-2

In my Spring web flow(SWF), flow can't travel anywhere and show first page again


I am using Spring Web Flow(SWF) for my conversation type page navigation. In that project, there is main flow called candidatemain-flow.xml and have subflow called candidate-flow.xml and matriculation-flow.xml. When I running my project, the main flow start and it transaction to the subflow called candidate-flow.xml and the registration page is rendered. But I fill some data in registration form and submit back to the subflow, it can't travel the second subflow called matriculation-flow.xml(I think) and show the registration form again and this flow step "execution=e1s1" show again.

This is my flow main definition:

<?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
        http://www.springframework.org/schema/webflow/spring-webflow.xsd">

<var name="candidate" class="com.wcg.lms.models.CandidateDTOFull"/>
<subflow-state id="candidateRegistrationFir" subflow="candidate">
    <input name="candidate" value="candidate" type="com.wcg.lms.models.CandidateDTOFull"/>
    <output name="candidate" value="candidate" type="com.wcg.lms.models.CandidateDTOFull"/>
    <transition on="candidateReady" to="candidateRegistrationSec" />
</subflow-state>

 <subflow-state id="candidateRegistrationSec" subflow="matriculation">
    <input name="candidate" value="candidate" type="com.wcg.lms.models.CandidateDTOFull"/>
    <transition on="matriculationReady" to="candidateRegistrationThir" />
</subflow-state> 

<subflow-state id="candidateRegistrationThir" subflow="academic">
    <input name="candidate" value="candidate"/>
    <transition on="academicReady" to="candidateRegistrationFourth" />
</subflow-state>

<subflow-state id="candidateRegistrationFourth" subflow="other">
    <input name="candidate" value="candidate"/>
    <transition on="otherReady" to="candidateRegistrationFifth" />
</subflow-state>

<subflow-state id="candidateRegistrationFifth" subflow="sourceoffinance">
    <input name="candidate" value="candidate"/>
    <transition on="sourceOfFinanceReady" to="candidateRegistrationSixth" />
</subflow-state>

<subflow-state id="candidateRegistrationSixth" subflow="parentdetails">
    <input name="candidate" value="candidate"/>
    <transition on="parentDetailsReady" to="addNewCandidate" />
</subflow-state>

<action-state id="addNewCandidate">
    <evaluate result="flowScope.candidate" expression="candidateDelegate.addNewCandidateDetails(candidate)"></evaluate>
    <transition to="thankCandidate"/>
</action-state>

<view-state id="thankCandidate" model="flowScope.candidate">
    <on-entry>
        <set name="flowScope.candidate" value="candidate" type="com.wcg.lms.models.CandidateDTOFull"/>
    </on-entry>
    <transition to="endState"/>
</view-state>

<end-state id="endState"/>

<global-transitions>
    <transition on="cancel" to="endState"/>
</global-transitions>
</flow>

This is candidate-flow.xml:

<?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
        http://www.springframework.org/schema/webflow/spring-webflow.xsd">

<input name="candidate" type="com.wcg.lms.models.CandidateDTOFull" required="true" />
<view-state id="candidateRegistrationViewFir" model="candidate">
    <on-entry>
        <evaluate result="viewScope.idTypeList" expression="idTypeDelegate.findAllIdType()"/>
        <evaluate result="viewScope.genderList" expression="T(com.wcg.yude.lms.components.common.Gender).values()"/>
        <evaluate result="viewScope.maritalStatusList" expression="T(com.wcg.yude.lms.components.common.MaritalStatus).values()"/>
        <set name="candidate.name" value="new com.wcg.yude.lms.components.student.Name()"/>
        <set name="candidate.address" value="new com.wcg.yude.lms.components.registrar.Address()" />
        <set name="candidate.contactInfo" value="new com.wcg.yude.lms.components.registrar.ContactInfo()" />
        <set name="candidate.photoAttachment" value="new com.wcg.lms.models.AttachmentHolderDTO()" />
    </on-entry>
    <transition on="submit" to="candidateReady"/>
</view-state>

<end-state id="cancel" />
<end-state id="candidateReady">
    <output name="candidate" type="com.wcg.lms.models.CandidateDTOFull" />
</end-state>

<global-transitions>
    <transition on="cancel" to="cancel" />
</global-transitions>
</flow>

This is matriculation-flow.xml:

<?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
        http://www.springframework.org/schema/webflow/spring-webflow.xsd">
<var name="matriculationDetails" class="com.wcg.lms.models.CandidateMatriculationStandardDetailsDTO"/>
<input name="candidate" type="com.wcg.lms.models.CandidateDTOFull" required="true" />
<view-state id="candidateRegistrationViewSec" model="candidate">
    <on-entry>
        <set name="viewScope.photoAttachment" value="new com.wcg.lms.models.AttachmentHolderDTO()" />
    </on-entry>
    <transition on="submit" to="matriculationReady">
        <evaluate expression="candidate.setMatriculationStandardDetails(matriculationDetails)"></evaluate>
    </transition>
</view-state>

<end-state id="cancel" />
<end-state id="matriculationReady" />

<global-transitions>
    <transition on="cancel" to="cancel" />
</global-transitions>
</flow>

This is candidateRegistrationViewFir.jsp for registration:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>YUDE_Spring_Test</title>
    <link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
    <link href="<c:url value="/resources/css/bootstrap.css"/>" rel="stylesheet">
    <link href="<c:url value="/resources/css/thuStyle.css"/>" rel="stylesheet">
</head>
<body>
    <div class="container-fluid">

        <div class="row">
            <img class="img-rounded" alt="" src="<c:url value="/resources/img/YUDE-Banner3.jpg"/>" style="width: 100%; height: 300px;">
        </div>

        <br/>
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="well">
                    <sf:form cssClass="form-horizontal" commandName="candidate">                    
                        <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"/>
                        <label>flowExecutionKey: ${flowExecutionKey}</label>
                        <div class="form-group">

                            <label for="firstName" class="col-md-3 control-label">First Name :</label>
                            <div class="col-md-3">
                                <sf:input path="name.firstName" cssClass="form-control" size="15" id="firstName" placeholder="Full Name" />
                            </div>

                            <label for="street1" class="col-md-3 control-label">Street-1 :</label>
                            <div class="col-md-3">
                                <sf:input path="address.street1" cssClass="form-control" size="50" id="street1" placeholder="Street-1" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="middleName" class="col-md-3 control-label">Middle Name :</label>
                            <div class="col-md-3">
                                <sf:input path="name.middleName" cssClass="form-control" size="15" id="middleName" placeholder="Middle Name" />
                            </div>

                            <label for="street2" class="col-md-3 control-label">Street-2 :</label>
                            <div class="col-md-3">
                                <sf:input path="address.street2" cssClass="form-control" size="50" id="street2" placeholder="Street-2" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="lastName" class="col-md-3 control-label">Last Name :</label>
                            <div class="col-md-3">
                                <sf:input path="name.lastName" cssClass="form-control" size="15" id="lastName" placeholder="Last Name" />
                            </div>

                            <label for="city" class="col-md-3 control-label">City :</label>
                            <div class="col-md-3">
                                <sf:input path="address.city" cssClass="form-control" size="15" id="city" placeholder="City" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="dob" class="col-md-3 control-label">Date Of Birth :</label>
                            <div class="col-md-3">
                                <sf:input path="dob" cssClass="form-control" size="15" id="dob" placeholder="Date Of Birth" />
                            </div>

                            <label for="state" class="col-md-3 control-label">State :</label>
                            <div class="col-md-3">
                                <sf:input path="address.state" cssClass="form-control" size="15" id="state" placeholder="State" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="nationality" class="col-md-3 control-label">Nationality :</label>
                            <div class="col-md-3">
                                <sf:input path="nationality" cssClass="form-control" size="15" id="nationality" placeholder="Nationality" />
                            </div>

                            <label for="country" class="col-md-3 control-label">Country :</label>
                            <div class="col-md-3">
                                <sf:input path="address.country" cssClass="form-control" size="15" id="country" placeholder="Country" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="race" class="col-md-3 control-label">Race</label>
                            <div class="col-md-3">
                                <sf:input path="race" cssClass="form-control" size="15" id="race" placeholder="Race" />
                            </div>

                            <label for="phone1" class="col-md-3 control-label">Phone-1 :</label>
                            <div class="col-md-3">
                                <sf:input path="contactInfo.phone1" cssClass="form-control" size="15" id="phone1" placeholder="Phone1" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="idType" class="col-md-3 control-label">IdType :</label>
                            <div class="col-md-3">
                                <sf:select path="idType" cssClass="form-control" id="idType">

                                    <c:forEach var="idType" items="${idTypeList}">
                                        <sf:option value="${idType}">${idType.name}</sf:option>
                                    </c:forEach>
                                </sf:select>
                            </div>

                            <label for="phone2" class="col-md-3 control-label">Phone-2 :</label>
                            <div class="col-md-3">
                                <sf:input path="contactInfo.phone2" cssClass="form-control" size="15" id="phone2" placeholder="Phone2" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="idNo" class="col-md-3 control-label">Id No :</label>
                            <div class="col-md-3">
                                <sf:input path="idNo" cssClass="form-control" size="15" id="idNo" placeholder="IdNo" />
                            </div>

                            <label for="phone3" class="col-md-3 control-label">Phone-3 :</label>
                            <div class="col-md-3">
                                <sf:input path="contactInfo.phone3" cssClass="form-control" size="15" id="phone3" placeholder="Phone3" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label class="col-md-2 control-label">MALE</label>
                            <div class="col-md-1">
                                <sf:radiobutton path="gender" cssClass="form-control" value="${gender.MALE}" />
                            </div>
                            <label class="col-md-2 control-label">FEMALE</label>
                            <div class="col-md-1">
                                <sf:radiobutton path="gender" cssClass="form-control" value="${gender.FEMALE}" />
                            </div>

                            <label for="email1" class="col-md-3 control-label">Email-1 :</label>
                            <div class="col-md-3">
                                <sf:input path="contactInfo.email1" cssClass="form-control" size="15" id="email1" placeholder="Email-1" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="maritalStatus" class="col-md-3 control-label">MaritalStatus :</label>
                            <div class="col-md-3">
                                <sf:select path="maritalStatus" cssClass="form-control" id="maritalStatus">
                                    <c:forEach var="maritalStatus" items="${maritalStatusList}">
                                        <sf:option value="${maritalStatus}">${maritalStatus}</sf:option>
                                    </c:forEach>
                                </sf:select>
                            </div>

                            <label for="email2" class="col-md-3 control-label">Email-2 :</label>
                            <div class="col-md-3">
                                <sf:input path="contactInfo.email2" cssClass="form-control" size="15" id="email2" placeholder="Email-2" />
                            </div>

                        </div>
                        <div class="form-group">

                            <label for="occupation" class="col-md-3 control-label">Occupation :</label>
                            <div class="col-md-3">
                                <sf:input path="occupation" cssClass="form-control" size="15" id="occupation" placeholder="Occupation" />
                            </div>

                            <div class="form-group">
                                <label for="photoAttachment" class="col-md-3 control-label">File input</label>
                                <div class="col-md-3">
                                    <sf:input path="photoFile" type="file" id="photoAttachment" />
                                </div>
                            </div>

                        </div>
                        <div class="form-group">
                            <div class="col-md-3 pull-left">
                                <button type="submit" class="btn btn-primary" name="_eventId_cancel" disabled="disabled">&larr; Older</button>
                            </div>
                            <div class="col-md-3 pull-right">
                                <input type="submit" class="btn btn-primary" name="_eventId_submit" value="Newer &rarr;"/>
                            </div>

                        </div>

                    </sf:form>
                </div>
            </div>
         </div>

</div>
</body>
</html>

This is the candidateRegistrationViewSec.jsp:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>YUDE_Spring_Test</title>
    <link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
    <link href="<c:url value="/resources/css/bootstrap.css"/>" rel="stylesheet">
    <link href="<c:url value="/resources/css/thuStyle.css"/>" rel="stylesheet">
</head>
<body>
    <blockquote>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
        <footer>Someone famous in <cite title="Source Title">Source Title</cite></footer>
    </blockquote>
</body>


Solution

  • Your comment is partially right but not validator but it need converter or formatter. Although I directly fill data by call ref-type dot its value type variable, "IdTypeDTO" object and "Gender" enum are binding as String to its model class's property's property(means "candidateModelBean.candidate.idType" property is reference type and I bind that property as String).

    So I simply add custom formatter for that type of property like this :

    public class GenderFormatter implements Formatter<Gender>{
    
    @Override
    public String print(Gender gender, Locale local) {
        return gender.getLabel();
    }
    
    @Override
    public Gender parse(String value, Locale local) throws ParseException {
        if(Gender.valueOf(value) == Gender.MALE) {
            return Gender.MALE;
        } else {
            return Gender.FEMALE;
        }
    }
    

    }

    and registered in formatter registray and config in web flow config file and every things go well and transition to page 2(candidateRegistrationViewSec.jsp). However because of your comment, I check again and realize the solution. Thank for answering Prasad :)