Announcement Announcement Module
Collapse
No announcement yet.
Can't pass a form object from parent flow to subflow Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can't pass a form object from parent flow to subflow

    Hi

    I want to use a subflow with parent's form object and not just the same class, but in the state that that form object is right before the subflow is entered, meaning, preserving values in all the fields that were populated by the parent flow.

    I am using attribute-mapper for that and i set the form object name to the name i want to use, however, in my onBindAndValidate method (in the subflow) the formObject field is always newly created and I can't find a way to set it to my object. Here's the exerpt of my code:

    *flow.xml:
    <subflow-state id="mysubflow" flow="mySubFlow">
    <attribute-mapper>
    <input value="${flowScope.command}" as="command"/>
    <output value="command" as="command" />
    </attribute-mapper>

    subflow action class:
    public MySubflowFormAction() {
    setFormObjectName("command");
    setFormObjectClass(MyDTO.class);
    setFormObjectScope(ScopeType.FLOW);
    }

    subflow onBindAndValidate
    MyDTO myDTO = (MyDTO) command;

    at this point myDTO is null. That is if I do not execute setupForm when entering the subflow. If i execute setupForm, I simply get an empty object with all null fields.

    Does anyone know the way around this problem. Do I have to manually access FormObjectAccessor and set attribute '#formObject' to the value of MyDTO?

  • #2
    I think the problem is actually in the attribute mapping. What version of SWF are you using? There were some problems with the attribute mapping in PR3, but PR4 and the current CVS builds (PR5) should be fine.

    Also make sure that the form object you want to map is actually available at '${flowScope.command}' in the parent flow. If not, null would get mapped and that would explain the behaviour of the FormAction in the subflow (e.g. it doesn't find an existing form object so it creates a new one).

    Keep in mind that from PR4 onward the attribute mapping maps from the request context to flow scope when you use the 'value' attribute. so the output mapping should be as the input mapping:
    <output value="${flowScope.command} as="command"/>

    Erwin

    Comment


    • #3
      I added a unit test to verify the situation you describe and with the code currently in CVS it is working correctly. From ParameterizableFlowAttributeMapperTests:

      Code:
      	public void testFormActionInCombinationWithMapping&#40;&#41; throws Exception &#123;
      		context.setLastEvent&#40;new Event&#40;this&#41;&#41;;
      
      		context.setActiveSession&#40;parentSession&#41;;
      		assertTrue&#40;context.getFlowScope&#40;&#41;.isEmpty&#40;&#41;&#41;;
      		
      		FormAction action = new FormAction&#40;&#41;;
      		action.setFormObjectName&#40;"command"&#41;;
      		action.setFormObjectClass&#40;TestBean.class&#41;;
      		action.setFormObjectScope&#40;ScopeType.FLOW&#41;;
      		context.setProperty&#40;"method", "setupForm"&#41;;
      		
      		action.execute&#40;context&#41;;
      		
      		assertEquals&#40;2, context.getFlowScope&#40;&#41;.size&#40;&#41;&#41;;
      		assertNotNull&#40;context.getFlowScope&#40;&#41;.get&#40;"command"&#41;&#41;;
      				
      		Map mappingsMap = new HashMap&#40;&#41;;
      		mappingsMap.put&#40;"$&#123;flowScope.command&#125;", "command"&#41;;
      		mapper.setInputMappingsMap&#40;mappingsMap&#41;;
      		Map input = mapper.createSubflowInput&#40;context&#41;;
      		
      		assertEquals&#40;1, input.size&#40;&#41;&#41;;
      		assertSame&#40;parentSession.getScope&#40;&#41;.get&#40;"command"&#41;, input.get&#40;"command"&#41;&#41;;
      		assertTrue&#40;subflowSession.getScope&#40;&#41;.isEmpty&#40;&#41;&#41;;
      		subflowSession.getScope&#40;&#41;.putAll&#40;input&#41;;
      		
      		context.setActiveSession&#40;subflowSession&#41;;
      		assertEquals&#40;1, context.getFlowScope&#40;&#41;.size&#40;&#41;&#41;;
      		
      		action.execute&#40;context&#41;;
      		
      		assertEquals&#40;2, context.getFlowScope&#40;&#41;.size&#40;&#41;&#41;;
      		assertSame&#40;parentSession.getScope&#40;&#41;.get&#40;"command"&#41;, context.getFlowScope&#40;&#41;.get&#40;"command"&#41;&#41;;
      	&#125;
      Erwin

      Comment


      • #4
        I'm Boris's coworker.

        The problem isn't with the mapping. we've already tested that it works. It's a more general problem. We want this other FormAction to use an existing formObject in flowScope (which we happen to put there by a mapping), under the attribute "command".

        The problem is with FormAction's setupForm method in PR4.

        In PR3 setupForm eventually called this piece of code:

        Code:
        protected Object loadFormObject&#40;RequestContext context&#41; throws FormObjectRetrievalFailureException &#123;
        		if &#40;getFormObjectScope&#40;&#41; == ScopeType.FLOW && context.getFlowScope&#40;&#41;.containsAttribute&#40;getFormObjectName&#40;&#41;&#41;&#41; &#123;
        			Object formObject = context.getFlowScope&#40;&#41;.getAttribute&#40;getFormObjectName&#40;&#41;, getFormObjectClass&#40;&#41;&#41;;
        			if &#40;logger.isDebugEnabled&#40;&#41;&#41; &#123;
        				logger.debug&#40;"Using previously loaded form object '" + getFormObjectName&#40;&#41; + "' cached in flow scope"&#41;;
        			&#125;
        			return formObject;
        		&#125;
        Using "getFormObjectName()" to find an existing formObject in FlowScope.

        In PR4 setupForm does this:

        Code:
        public Event setupForm&#40;RequestContext context&#41; throws Exception &#123;
        		FormObjectAccessor accessor = new FormObjectAccessor&#40;context&#41;;
        		Object formObject = accessor.getFormObject&#40;&#41;;
        Notice that it does NOT use the "formObjectName" you've specified to look up the formObject, but uses the default "#formObject".

        This call in FormAction.setupForm() should be changed to:
        Code:
        		Object formObject = accessor.getFormObject&#40;getFormObjectName&#40;&#41;&#41;;

        Comment


        • #5
          I haven't built and tested it, but I see in the latest CVS that you're using a different method to retrieve the formObject (that does use "getFormObjectName") in setupForm that should fix this problem.

          Comment


          • #6
            Yes, the PR4 FormAction was seriouly messed up. The current CVS code, or PR5, which we're about to release, should fix things!

            Erwin

            Comment

            Working...
            X