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

  • bindAndValidate action

    Hi,
    I have a form with three imagebuttons which submit it. Only one of these buttons actually triggers an action which makes use of the form. The others are for things like reload a page value (request bound not in the form) or going one step back. They are mainly in the form because this allows POST parameters.

    May flow behind the page looks like this:

    Code:
     	<view-state id="step1View" view="page.register.step1">
    		<transition on="back" to="bindAndValidateFormStep0"/>
    		<transition on="next" to="bindAndValidateFormStep1"/>
    		<transition on="items" to="bindAndValidateFormStep1_1"/>
    	</view-state>
    
    	<action-state id="bindAndValidateFormStep0">
    		<action bean="registerFormAction" method="bindAndValidate"/>
    		<transition on="success" to="step0View"/>
    	</action-state>
    
    	<action-state id="bindAndValidateFormStep1">
    		<action bean="registerFormAction" method="bindAndValidate">
    			<property name="validatorMethod" value="validateCustomerDetails"/>
    		</action>
    		<transition on="success" to="step1_selectItem"/>
    		<transition on="error" to="step1View"/>
    	</action-state>
    	
    	<action-state id="bindAndValidateFormStep1_1">
    		<action bean="registerFormAction" method="bindAndValidate"/>
    		<transition on="success" to="step1_fetchItems"/>
    	</action-state>
    My problem here is that on the one hand I need the bindAndValidate state even if I don't want to validate the bean (bindAndValidate method does nothing). Otherwise I get an exception:

    Code:
    java.lang.IllegalStateException&#58; Required attribute 'org.springframework.validation.BindException.#formObject' is not present in flow scope; attributes present are = map&#91;'PROSPECT' -> com.xyz.tst.common.dto.ProspectDTO@1a498b6, 'registerActionForm' -> com.xyz.tst.webapp.struts.forms.RegisterFlowActionForm@125f76b, '#formObject' -> com.xyz.tst.webapp.struts.forms.RegisterFlowActionForm@125f76b
    On the other hand I can't "route" the original event through the bindAndValidate action-state therefor I need three different bindAndValidate actions which are refering to other states. Is there a better way to achive this? Even with the misuse of the imagebuttons in the form?

    Thanks,
    Markus

  • #2
    I don't think there is a real problem with the 3 action states in your flow. They all do something different. I've noticed that a best practice is "not to try and reuse a state definition". A state definition reuses an action implementation (FormAction in this case), but is not itself reusable.

    Erwin

    Comment


    • #3
      It's not a problem. But two of the actions aren't doing different things in their actions. They are simply binding the form. OK, they route to different actions. But this is more or less a "workaround" because I could not propagate the target step to/through the bindAndValidateForm action (and bindAndValidateForm is named wrongly in this case because it should not validate. Binding would be sufficient).

      Less verbose would be:
      Code:
          <view-state id="step1View" view="page.register.step1">
            <transition on="back" to="step0View" via="bindForm"/>
            <transition on="next" to="bindAndValidateFormStep1"/>
            <transition on="items" to="step1_fetchItems" via="bindForm"/>
         </view-state>
      I think this would make the whole flow much more readable as it concentrates on the actions which are doing real stuff instead of declaring multiple actions which are a "must-be-there" because of framework reasons.

      Comment


      • #4
        You do have a point.

        However, your 'via' solution won't work here -- as when the 'bindForm' state is entered, it is the one in charge of where to go next, not the view state.

        A solution here might be transition pre conditions. We've already talked about this a little, particularly for security use cases. Basically:

        TransitionCriteria
        Code:
        public boolean test&#40;RequestContext context&#41;;
        In there you could execute the bind and validate action, and not allow the transition if bind/validate returns error(). Like this:

        Code:
        public boolean test&#40;RequestContext context&#41; &#123;
            Event result = bindAction.execute&#40;context&#41;;
            if &#40;result.getId&#40;&#41;.equals&#40;"success"&#41;&#41; &#123;
               return true;
            &#125; else &#123;
               return false;
            &#125;
        &#125;
        Code:
         <view-state id="step1View" view="page.register.step1"> 
              <transition on="back" to="step0View" precondition="bindForm"/> 
              <transition on="next" to="bindAndValidateFormStep1"/> 
              <transition on="items" to="step1_fetchItems" precondition="bindForm"/> 
           </view-state>

        Comment


        • #5
          I've added initial support for Transition preconditions. It's not yet hooked into the flow builder code, but checkout Transition for a sneak peek.

          Comment


          • #6
            Ok, it's hooked in. There is a "precondition" element now, referenceable by id via a "precondition" attribute of the transition element. The "bean" attribute on the precondition element should be the id of a TransitionCriteria or TransitionCriteriaFactoryBean in the context.

            This means, before a Transition is allowed to execute, the precondition will be tested -- if it returns true, execution is permitted, else it a TransitionNotAllowedException is thrown.

            A BindAndValidateTransitionPrecondition support impl is provided - it should work drop in, doing what you need.

            I think it's time to cut PR3 :-)

            Keith

            Comment


            • #7
              Phonebook now demonstrates this:

              Code:
              <webflow id="person.Search" start-state="criteria.view">
              
              	<view-state id="criteria.view" view="person.Search.criteria.view">
              		<transition on="submit" to="executeQuery" precondition="bindAndValidate"/>
              	</view-state>
              
              	<precondition id="bindAndValidate" bean="person.Search.criteria.bindAndValidate"/>
              Keith

              Comment


              • #8
                unbelievable how fast you are. I'm still exploring the features of SWF and you are adding things faster then I could test them ;-)

                Comment


                • #9
                  I've further refined this support, now providing first-class support for transition actions -- actions that execute after a transition is matched but before it is executed (building on the TransitionCriteria precondition support discussed above.)

                  For example:

                  Code:
                  	<view-state id="criteria.view" view="person.Search.criteria.view">
                  		<transition on="submit" to="executeQuery">
                  			<action bean="person.Search.formAction" method="bindAndValidate"/>
                  		</transition>
                  	</view-state>
                  Let us know what you guys think.

                  Comment


                  • #10
                    perfect. I think it's very clean and simple.

                    Comment

                    Working...
                    X