Announcement Announcement Module
Collapse
No announcement yet.
Exit action from view state Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Exit action from view state

    I defined an exit action on a view state. I thought I would be able to read some form parameters from the request scope of the view. But I am not able to find my parameters within the exit action. However, the action called from the next action state is able to find them.

    Is this a limitation of using exit actions?

    I'm employing an exit action to avoid duplicating the same action among multiple transition paths away from the view state.

    - Paul Glezen

  • #2
    Strange. Transition actions are executed before state exit actions, so having the bindAndValidate as a transition action should not cause the problem.

    I'll investigate.

    Erwin

    Comment


    • #3
      Perhaps if I shared more details about my configuration, it might shed some light on what I'm doing wrong.

      Here is a snippet of my flow definition.

      Code:
      	<action-state id="newProduct">
      	    <action bean="formAction"/>
      	    <transition on="success" to="editProduct"/>
      	</action-state>
      
      	<view-state id="editProduct" view="editProduct">
      		<transition on="submit" to="saveProduct"/>
      		<transition on="addExistingWork" to="addExistingWork"/>
      		<exit>
      		   <action bean="formAction" method="populateFields"/>
      		</exit>
      	</view-state>
      	
      	<subflow-state id="addExistingWork" flow="existingWorkAdd">
      		<attribute-mapper>
      		   <input value="flowScope.product" as="product"/>
      		</attribute-mapper>
      		<transition on="finish" to="editProduct"/>
      	</subflow-state>
      	
      	<action-state id="saveProduct">
      	    <entry>
      		    <action bean="formAction" method="bindAndValidate"/>
      	    </entry>
      		<action bean="formAction" method="saveProduct"/>
      		<transition on="success" to="showProductList"/>
      	</action-state>
      The editProduct view-state has some text fields which match some of the attributes of a product. Before I added the subflow. the only transition out of editProduct was submit. The saveProduct action-state retrieves the populated bean from the request scope of the RequestContext. Life was good.

      But then I needed to add a subflow for adding one or more works to a product. So in addition to being able to click "Save" in the editProduct view, I needed to furnish an "AddWorks" button to enter a subflow for retrieving a list of works and selecting which ones to add. But in both transitions, I need to save the editProduct fields. So I took this code out of the "saveProduct" action and placed it in an exit action of the view that would save the fields no matter which transition was taken.

      Here is the exit action code.

      Code:
      	public Event populateFields&#40;RequestContext ctx&#41; throws Exception &#123;
      		Product requestP = &#40;Product&#41;ctx.getRequestScope&#40;&#41;.get&#40;FORM_OBJECT_NAME&#41;;
      		if &#40;requestP != null&#41; 
      			log.debug&#40;"populateFields&#58; Product from request&#58; id = " + requestP.getId&#40;&#41;&#41;;
      		else &#123;
      			log.error&#40;"populateFileds&#58; Could not locate " + FORM_OBJECT_NAME + " in request object."&#41;;
      			ServletEvent evt = &#40;ServletEvent&#41;ctx.getSourceEvent&#40;&#41;;
      			String prodIdStr = evt.getRequest&#40;&#41;.getParameter&#40;"id"&#41;;
      			String prodTitle = evt.getRequest&#40;&#41;.getParameter&#40;"title"&#41;;
      			String prodFormat = evt.getRequest&#40;&#41;.getParameter&#40;"format"&#41;;
      			log.debug&#40;"From ServletEvent&#58; prod    ID = " + prodIdStr&#41;;
      			log.debug&#40;"From ServletEvent&#58; prod Title = " + prodTitle&#41;;
      			log.debug&#40;"From ServletEvent&#58; prod Format = " + prodFormat&#41;;
      			requestP = TransientProducts.newProduct&#40;&#41;;
      			requestP.setFormat&#40;prodFormat&#41;;
      			requestP.setTitle&#40;prodTitle&#41;;
      		&#125;
      		Product flowP = &#40;Product&#41;ctx.getFlowScope&#40;&#41;.getAttribute&#40;"product"&#41;;
      		log.debug&#40;"Product from flow&#58; id = " + flowP.getId&#40;&#41;&#41;;
      		flowP.setFormat&#40;requestP.getFormat&#40;&#41;&#41;;
      		flowP.setTitle&#40;requestP.getTitle&#40;&#41;&#41;;		
      		return success&#40;&#41;;
      	&#125;
      When specified to run as an exit action, the FORM_OBJECT_NAME is not found in the request scope of RequestContext In this case the recovery code retrieves it from the source event. But when the same code is run in a separate action-state, the FORM_OBJECT_NAME is found.

      That's why I wondered whether the request scope of the RequestContext was populated only after the exit action was called.

      - Paul Glezen

      Comment


      • #4
        Found my problem

        Ugh. I've been tracking this down all day. But 30 seconds after I click Submit on my inquiry to this form, I see my problem. I was calling "get" instead of "getAttribute" on the request scope. After changing it back, it seems to work now.

        Sorry for the commotion.

        - Paul

        Comment


        • #5
          Are you sure you didn't change anything else? In the source code of the Scope class you can see that get() and getAttribute() do exactly the same thing:

          Code:
          	public Object getAttribute&#40;String attributeName&#41; &#123;
          		return this.attributes.get&#40;attributeName&#41;;
          	&#125;
          Code:
          	public Object get&#40;Object key&#41; &#123;
          		return this.attributes.get&#40;key&#41;;
          	&#125;
          So as far as I can see "ctx.getRequestScope().get(FORM_OBJECT_NAME)" and "ctx.getRequestScope().getAttribute(FORM_OBJECT_NA ME)" should be the same.

          Erwin

          Comment


          • #6
            Web flow twilight zone

            Hmmm. That's interesting. I'm pretty sure that on Wednesday night, I went from "not working" to "working" simply by changing the method name from "get" to "getAttribute." I was a little baffled by klr8's observation.

            Things were working, so I was tempted to let sleeping dogs lie. But the old maxim of software development kept nagging me.

            If you don't know why your code works, it probably doesn't.
            So this morning I dove back in.
            1. I changed "getAttribute" back to "get". It didn't work.
            2. I changed it back to "getAttribute". It still didn't work again. Oh boy, now I've done it. I couldn't understand how it ever worked before. But I had run it a whole bunch of times yesterday successfully.
            3. I realized that because this was an exit action on a view state, there was no opportunity for running bindAndValidate. So I changed my exit stanza to include bindAndValidate as well.
            Code:
            <exit>
               <action bean="formAction" method="bindAndValidate"/>
               <action bean="formAction" method="populateFields"/>
            </exit>
            This works regardless of "get" or "getAttribute". So I feel a little better about it.

            Comment

            Working...
            X