PDA

View Full Version : bindAndValidate action



jocsch
Apr 21st, 2005, 12:33 PM
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:


<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:


java.lang.IllegalStateException&#58; Required attribute 'org.springframework.validation.BindException.#for mObject' 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.RegisterFlowAction Form@125f76b, '#formObject' -> com.xyz.tst.webapp.struts.forms.RegisterFlowAction Form@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

klr8
Apr 21st, 2005, 01:07 PM
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

jocsch
Apr 22nd, 2005, 04:16 AM
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:

<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.

Keith Donald
Apr 22nd, 2005, 08:22 AM
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


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:



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;




<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>

Keith Donald
Apr 22nd, 2005, 10:22 AM
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.

Keith Donald
Apr 22nd, 2005, 02:16 PM
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

Keith Donald
Apr 22nd, 2005, 03:06 PM
Phonebook now demonstrates this:



<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

jocsch
Apr 23rd, 2005, 09:48 AM
unbelievable how fast you are. I'm still exploring the features of SWF and you are adding things faster then I could test them ;-)

Keith Donald
Apr 23rd, 2005, 12:38 PM
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:



<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.

jocsch
Apr 23rd, 2005, 02:19 PM
perfect. I think it's very clean and simple.