springjunit4spring-webflowspring-webflow-2

not able to get the flow scope variable from one state transition to another state transition junit


When I transit from view state to decision state or action state all the input set is lost while transitioning to another state. How to do I get the flow scope variable for decision state or action state on transitioning from view state to decision state and action state in junit ?

In my flow definition right now I am in view state when I set the event Id as submit it moves to registerEnroll decision state where it needs flowScope.regform.loyaltyLookUp value. When I see the flow execution variable map there is nothing inside apart from RegForm object, even though I have set variable in MutableAttributeMap.

How to set the flow scope variable which will be always available on transitioning to state on junit test case for spring webflow?

In second test case flow is going to else part of decision state even though I have provide flowScope.regform.loyaltyLookUp in input. What mistake I am doing I am not able to figure out .

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-2.4.xsd" 
     start-state="confirmsuccess">

    <var name="regform" class="com.shc.ecom.usr.form.Regform" />
    <var name="enrollresponse" class="com.shc.ecom.usr.service.adapter.ResponseVO" />

    <!-- <input-mapper> <input-attribute name="service" /> <input-attribute 
        name="regform" /> <input-attribute name="success" /> </input-mapper> <start-state 
        idref="confirmsuccess" /> -->

    <input name="service" />
    <input name="regform" />
    <input name="success" />
     <input name="enrollresponse"/> 


    <decision-state id="confirmsuccess">
        <if test="flowScope.success!=null" then="serviceticketvalidation"
            else="saveQueryParamInSession" />
    </decision-state>
    <decision-state id="serviceticketvalidation">
        <if test="flowScope.success=='yes'" then="sywNumAction" else="ssoerrorredirect" />
    </decision-state>


    <!-- <action-state id="enterCustInfo"> <action bean="regEnrollFormAction" 
        method="setupForm" > </action> <transition on="success" to="renderform"/> 
        </action-state> -->

    <!-- save query parameter in session -->
    <action-state id="saveQueryParamInSession">
        <evaluate expression="saveQueryParamInSession.doExecute(flowRequestContext)" />
        <transition on="success" to="renderform" />
    </action-state>


    <view-state id="renderform" view="/regenroll"  >
        <on-entry>
            <evaluate expression="regEnrollFormAction.setupForm(flowRequestContext)" />
                <set name="flowScope.sourceSite" value="requestParameters.sid" /> <!-- scope="flow" -->
                <set name="flowScope.service" value="requestParameters.service" />
                <set name="flowScope.clienthost" value="requestParameters.clienthost" />
                <set name="flowScope.target" value="requestParameters.target" />
                <set name="flowScope.switchForm" value="requestParameters.switchForm" />
                <set name="flowScope.oldlogin" value="requestParameters.oldlogin" />
                <set name="flowScope.emailId" value="requestParameters.emailId" />
                <set name="flowScope.confirmEmail" value="requestParameters.emailConfirm" />
                <set name="flowScope.fname" value="requestParameters.fname" />
                <set name="flowScope.lname" value="requestParameters.lname" />
                <set name="flowScope.zipCode" value="requestParameters.zip" />
                <set name="flowScope.modifyservice" value="requestParameters.modifyservice" />
                <set name="flowScope.ocpPage" value="requestParameters.ocpPage" />
                <set name="flowScope.fullpage" value="requestParameters.fullpage" />
                <set name="flowScope.emailValidateFlag" value="requestParameters.emailValidateFlag" />
                <set name="flowScope.mode" value="requestParameters.mode" />
                <set name="flowScope.phone" value="requestParameters.phone" />
                <set name="flowScope.number" value="requestParameters.number" />
                <set name="flowScope.irp" value="requestParameters.irp" />
                <set name="flowScope.sywmax" value="requestParameters.sywmax" /> 
        </on-entry>
        <transition on="submit" to="registerEnroll">
          <evaluate expression="regEnrollFormAction.bindAndValidate(flowRequestContext)"></evaluate>
        </transition>
    </view-state>

    <decision-state id="registerEnroll">
        <if test="flowScope.regform.loyaltyLookUp!=null" then="processEnroll"
            else="activateEnroll" />
    </decision-state>

    <action-state id="processEnroll">
        <evaluate
            expression="ssoGatewayService.register(flowScope.regform,externalContext)" result="flowScope.enrollresponse" result-type="com.shc.ecom.usr.service.adapter.ResponseVO" />
            <transition on="success" to="postenroll" />
    </action-state>


    <decision-state id="postenroll">
        <if test="flowScope.enrollresponse.responseCode ==200" then="ccenroll"
            else="enrollerror" />
    </decision-state>

    <decision-state id="ccenroll">
        <if test="flowScope.regform.craftsmanAffinity!=null" then="ccAffinityUpdate"
            else="go_to_login_flow" />
    </decision-state>


    <action-state id="ccAffinityUpdate">
        <evaluate
            expression="ssoGatewayService.updateCCAffinity(flowScope.regform, flowScope.enrollresponse)"
            result="enrollresponse" />
            <transition on="success" to="postccupdate" />
    </action-state>

    <decision-state id="postccupdate">
        <if test="flowScope.enrollresponse.responseCode==200" then="go_to_login_flow"
            else="ccupdateerror" />
    </decision-state>
    <decision-state id="enrollerror">
        <if test="flowScope.enrollresponse.existingUserInd!=null" then="existingUserLogin"
            else="captchaValidation" />
    </decision-state>

    <decision-state id="captchaValidation">
        <if test="flowScope.enrollresponse.errorCode eq '401.1'" then="captchaValidationError"
            else="loyaltydown" />
    </decision-state>

    <decision-state id="loyaltydown">
        <if test="flowScope.enrollresponse.loyaltyDown!=null" then="loyaltydownerror"
            else="showerror" />
    </decision-state>

    <action-state id="activateEnroll">
        <evaluate expression="ssoGatewayService.onlineActivation(flowScope.regform, requestParameters.clienthost,
        externalContext, requestParameters.mode, requestParameters.number, requestParameters.phone)"
         result = "enrollresponse" />
        <transition on="success" to="postenroll" />
    </action-state>

    <subflow-state id="go_to_login_flow" subflow="shclogin-flow">
        <input value="flowScope.regform.password" name="logonPassword"/>
        <input value="flowScope.regform.email" name="loginId"/>
        <input value="flowScope.regform.sid" name="sourceSiteId"/>
        <input value="flowScope.regform.service" name="service"/>
        <input value="flowScope.regform.redirectUrl" name="redirectUrl"/>
        <input value="flowScope.reglogin" name="reglogin"/>
        <input value="flowScope.enrollresponse" name="enrollresponse"/>

        <transition on="finish" to="process_and_redirect" />
        <transition on="redirect" to="process_and_redirect" />
        <transition on="sendtickettomodal_reg" to="sendtickettomodal">
            <set name="clienthost" value="requestParameters.clienthost" /> <!--  scope="flow"  -->
        </transition>
        <transition on="pickup_error_redirect_reg" to="ssoerrorredirect" />
        <transition on="pickup_error_redirect_login" to="ssoerrorredirect" />
    </subflow-state>

    <!-- 
        <attribute-mapper>
            <input-mapper>
                <mapping source="${flowScope.regform.email}" target="loginId" />
                <mapping source="${flowScope.regform.password}" target="logonPassword" />
                <mapping source="${flowScope.regform.sid}" target="sourceSiteId" />
                <mapping source="${flowScope.regform.service}" target="service" />
                <mapping source="${flowScope.regform.redirectUrl}" target="redirectUrl" />
                <mapping source="${flowScope.reglogin}" target="reglogin" />
                <mapping source="${flowScope.enrollresponse}" target="enrollresponse" />
            </input-mapper>
        </attribute-mapper>
     -->


    <action-state id="sywNumAction">
        <evaluate expression="sywNumSetupAction" />
        <transition on="success" to="process_and_redirect" />
    </action-state>

    <end-state id="process_and_redirect" view="/successconfirmation">
        <on-entry>
            <set name="sourceSiteId" value="flowScope.regform.sid" />
            <set name="sywrNumber" value="flowScope.sywrNumber" />
            <set name ="softLinkFlow" value="requestParameters.softLinkFlow" />
            <set name ="fullpage" value="requestParameters.fullpage" />
            <set name="targetUrl" value="requestParameters.targetUrl" />
        </on-entry>
    </end-state>

    <view-state id="showerror" view="/displayerror">
        <on-entry>
            <set name="errorCode" value="flowScope.enrollresponse.responseCode" />
            <set name="responseString" value="flowScope.enrollresponse.responseString" />
        </on-entry>
    </view-state>
    <view-state id="captchaValidationError" view="/displayerror">
        <on-entry>
            <set name="errorCode" value="401.1" />
            <set name="responseString" value="flowScope.enrollresponse.errorDescription" />
        </on-entry>
    </view-state>
    <view-state id="loyaltydownerror" view="/displayerror">
        <on-entry>
            <set name="errorCode" value="500.2" />
            <set name="responseString" value="flowScope.enrollresponse.responseString" />
        </on-entry>
    </view-state>
    <end-state id="existingUserLogin" view="/existingUserLogin">
        <on-entry>
            <set name="returnCode" value="'500.110'" />
            <set name="clienthost" value="requestParameters.clienthost" />
            <set name="emailId" value="flowScope.regform.email" />
        </on-entry>
    </end-state>

    <view-state id="ccupdateerror" view="/ccEnrollError">
        <on-entry>
            <set name="returnCode" value="'500.111'" />
            <set name="clienthost" value="requestParameters.clienthost" />
            <set name="emailId" value="flowScope.regform.email" />
        </on-entry>
    </view-state>

    <!-- redirect the next step from login flow -->
    <end-state id="ssoerrorredirect" view="/successconfirmationwithssoerror">
        <on-entry>
            <set name="sourceSiteId" value="flowScope.regform.sid" />
            <set name="sywrNumber" value="flowScope.sywrNumber" />
            <set name="softLinkFlow" value="requestParameters.softLinkFlow" />
            <set name="fullpage" value="requestParameters.fullpage" />
        </on-entry>
    </end-state>

    <!-- adding sywmax parameter for registration flow -->
    <end-state id="sendtickettomodal" view="/displayserviceticketandcookie">
        <output value="requestScope.syw" name="sywmax"/>
    </end-state>

        <!--  
            <output-mapper>
            <mapping source="${requestScope.syw" x } target="sywmax" />
        </output-mapper>
         -->

    <global-transitions>
        <transition to="showerror"
            on-exception="org.springframework.webflow.execution.repository.NoSuchFlowExecutionException" />
        <transition to="showerror"
            on-exception="org.jasig.cas.services.UnauthorizedSsoServiceException" />
        <transition to="showerror"
            on-exception="org.jasig.cas.services.UnauthorizedServiceException" />
        <transition to="showerror"
            on-exception="org.springframework.webflow.execution.FlowExecutionException" />
    </global-transitions>
    <!-- <bean-import resource="regenroll-beans.xml" /> -->
</flow>

Test case

Second Test is failing

public class TestRegEnrollFlow extends AbstractXmlFlowExecutionTests {

    SavingQueryParamInSessionAction saveQueryParamInSession;
    SSOGatewayServiceImpl ssoGatewayService;


    @Override
    protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
        return resourceFactory.createFileResource("src/main/webapp/WEB-INF/usr/flows/regEnroll-flow.xml");
    }

    @Override
    protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
        // I Have tried even mocking using Easy Mock
        saveQueryParamInSession = EasyMock.createMock("saveQueryParamInSession", SavingQueryParamInSessionAction.class);
        ssoGatewayService = EasyMock.createMock("ssoGatewayService", SSOGatewayServiceImpl.class);

        builderContext.registerBean("saveQueryParamInSession", saveQueryParamInSession);
        builderContext.registerBean("sywNumSetupAction", new SywNumSetupAction());
        builderContext.registerBean("ssoGatewayService", ssoGatewayService);
        builderContext.registerBean("regEnrollFormAction", new RegEnrollFormAction());

    }

    public void testAction() {
        MockExternalContext ctx = new MockExternalContext();
        MutableAttributeMap input = new LocalAttributeMap();

        input.put("service", "");
        input.put("regform", createRegistrationForm());
        // this is the line where we are changing the state flow
        input.put("success", null);

        input.put("externalContext", ctx);
    input.put("enrollresponse.responseCode", 200);
        input.put("regform.craftsmanAffinity", "any");

        startFlow(input, ctx);

        assertFlowExecutionActive();
        assertCurrentStateEquals("renderform");
        assertResponseWrittenEquals("/regenroll", ctx);

    }



    public void testREgForm() throws Exception {
        setCurrentState("renderform");
        MockExternalContext context = new MockExternalContext();
        context.putRequestParameter("sid", "3");
        context.putRequestParameter("service", "qa.ecom.s.com:4380");
        context.putRequestParameter("clienthost", "qa.ecom.s.com:4380");
        context.putRequestParameter("target", "http://qa.ecom.sears.com:4380/?storeId=10153&catalogId=12605");
        context.putRequestParameter("switchForm", "Donald");
        context.putRequestParameter("oldlogin", "Donald");
        context.putRequestParameter("emailId", "jadiya@gmail.com");
        context.putRequestParameter("emailConfirm", "jadiya@gmail.com");
        context.putRequestParameter("fname", "Ankur");
        context.putRequestParameter("lname", "Jadiya");
        context.putRequestParameter("zip", "56005");
        context.putRequestParameter("modifyservice", "no");
        context.putRequestParameter("ocpPage", "no");
        context.putRequestParameter("fullpage", "no");
        context.putRequestParameter("emailValidateFlag", "true");
        context.putRequestParameter("mode", "active");
        context.putRequestParameter("phone", "8884911391");
        context.putRequestParameter("number", "883427");
        context.putRequestParameter("irp", "true");
        context.putRequestParameter("sywmax", "1234567");
        context.putRequestParameter("enrollresponse.responseCode","200");






        FlowExecution flowExecution = getFlowExecution();
        FlowSession session = flowExecution.getActiveSession();
        //flowExecution.getConversationScope().put("flowScope.enrollresponse.responseCode", 200);
        session.getScope().put("flowScope.regform.loyaltyLookUp", true);
        //session.getScope().put("flowScope.enrollresponse.responseCode", "200");
    //  session.getScope().put("flowScope.enrollresponse", 200);
        //session.getScope().put("responseCode", 200);
        session.getScope().put("flowScope.regform.craftsmanAffinity", "check");
        /*session.getScope().put("enrollresponse.responseCode", 200);*/
      //  session..put("flowScope.enrollresponse.responseCode", 200);
        updateFlowExecution(flowExecution);

        ResponseVO value = new ResponseVO(200, "success");
        session.getScope().put("enrollresponse", value);
        session.getScope().put("flowScope.enrollresponse.responseCode", value);
        context.setEventId("submit");
    //  EasyMock.expect(ssoGatewayService.register(createRegistrationForm(), context)).andReturn(value);

        flowExecution.resume(context);
        assertCurrentStateEquals("showerror");


    }

    private Regform createRegistrationForm() {
        Regform regform = new Regform();
        regform.setEmail("20130410111@gmail.com");
        regform.setLname("mike");
        regform.setFname("sun");
        regform.setPassword("test11");
        regform.setSid("3");
        regform.setZip("60179");
        regform.setLoyaltyLookUp(true);

        return regform;
    }

}

Error

Caused by: org.springframework.binding.expression.PropertyNotFoundException: Property not found
    at org.springframework.binding.expression.spel.SpringELExpression.setValue(SpringELExpression.java:117)
    at org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:80)
    at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188)
    at org.springframework.webflow.execution.AnnotatedAction.execute(AnnotatedAction.java:145)
    at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51)
    ... 36 more
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1010E:(pos 0): Property or field 'enrollresponse' cannot be set on object of type 'org.springframework.webflow.engine.impl.RequestControlContextImpl' - maybe not public?
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.writeProperty(PropertyOrFieldReference.java:270)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.setValue(PropertyOrFieldReference.java:159)
    at org.springframework.expression.spel.standard.SpelExpression.setValue(SpelExpression.java:411)
    at org.springframework.binding.expression.spel.SpringELExpression.setValue(SpringELExpression.java:114)
    ... 40 more

Solution

  • you are setting this property:

    input.put("enrollresponse.responseCode", "200");
    

    but:

    1. I don't see it anywhere in your flow (maybe in the part you omitted)
    2. You have to first create the enrollresponse object before setting "responseCode" on it. I think that is causing the error you are having

    [EDIT]

    1. you also need to specify the scope for variable in <set> element (showrror state). replace:

      <set name="errorCode" value="flowScope.enrollresponse.responseCode" />
      

      by

      <set name="viewScope.errorCode" value="flowScope.enrollresponse.responseCode" />
      

    fix all those issues and try again