You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by Tom Bednarz <li...@bednarz.ch> on 2006/08/30 18:33:49 UTC

validator and DynaValidatorActionForm

I think the validator fires too early, but probably I am doing something 
wrong. Maybe somebody can hp!

I have the following form bean defined in struts-config.xml:

     <form-bean name="changePersonalDataForm" 
type="org.apache.struts.validator.DynaValidatorActionForm" >
     	<form-property name="subscriberid" type="java.lang.String" />
     	<form-property name="firstname" type="java.lang.String" />
     	<form-property name="familyname" type="java.lang.String" />
     	<form-property name="zip" type="java.lang.String" />
     	<form-property name="place" type="java.lang.String" />
     	<form-property name="country" type="java.lang.String" />
     	<form-property name="addr1" type="java.lang.String" />
     	<form-property name="addr2" type="java.lang.String" />
     	<form-property name="addr3" type="java.lang.String" />
     	<form-property name="email" type="java.lang.String" />
     </form-bean>


and the following action mapping:

     <action
       attribute="changePersonalDataForm"
       input="/form/changePersonalData.jsp"
       name="changePersonalDataForm"
       path="/changePersonalData"
       scope="request"
       type="ch.smartsol.struts.action.ChangePersonalDataAction">
       <forward name="success" path="/template/SuccessMessage.jsp" />
       <forward name="failure" path="/form/changePersonalData.jsp" />
     </action>


The idea is, that I show a form that contains already data and the user 
can edit it. When the form is submitted, the validator should check the 
user input. Here is my validator configuration:


<form name="/changePersonalData">
   <field property="firstname" depends="required">
     <msg name="required" key="PersonalData.firstname.required"/>
   </field>
   <field property="familyname" depends="required">
     <msg name="required" key="PersonalData.familyname.required"/>
   </field>
   <field property="zip" depends="required">
     <msg name="required" key="PersonalData.zip.required"/>
   </field>
   <field property="place" depends="required">
     <msg name="required" key="PersonalData.place.required"/>
   </field>
   <field property="country" depends="required">
     <msg name="required" key="PersonalData.country.required"/>
   </field>
   <field property="addr1" depends="required">
     <msg name="required" key="PersonalData.addr1.required"/>
   </field>
   <field property="email" depends="required,email">
     <msg name="required" key="PersonalData.email.required"/>
     <msg name="email" key="PersonalData.email.email"/>
   </field>
</form>

Now it seems, that the validator gets fired BEFORE the form is filled! 
In the JSP that displays the form, I get lots of error messages all 
fired by the 'required' validator saying, that the field must not be 
empty, but all fields are filled corretly!!.

Here is an extract of the JSP:

<TABLE border="0" width="95%" align="center">
   <TR>
     <TD class="headerLeftLight" width="200">
        <bean:message key="ChangePersonalData.firstname"/>
     </TD>
     <TD class="dataLightAlignLeft" width="200">
       <html:text value="${sessionScope.subscriber.firstname}"
       property="firstname" name="firstname" maxlength="64"
       size="32"/>
     </TD>
     <TD class="errMessage">
        <html:errors property="firstname"/>
     </TD>
   </TR>
   <TR>
     <TD class="headerLeftStrong">
       <bean:message key="ChangePersonalData.lastname"/>
     </TD>
     <TD class="dataStrongAlignLeft">
       <html:text value="${sessionScope.subscriber.familyname}"
       property="familyname" name="familyname" maxlength="64"
       size="32"/>
     </TD>
     <TD class="errMessage">
       <html:errors property="familyname"/>
     </TD>
   </TR>
   .......

  </TABLE>

Every row contains a label, an input control and a TD to display 
validation errors of the specific field.

Does anybody know what is going wrong here??

Many thanks for your help!

Tom


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by Tom Bednarz <li...@bednarz.ch>.
Thanks a lot for all that feedback. I think it gets me a step further.

Tom


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by David Durham <dd...@vailsys.com>.
Tom Bednarz wrote:
> So I used
> <html:text value="${sessionScope.subscriber.firstname}"
>      property="firstname" name="firstname" maxlength="64"
>      size="32"/>

Don't specify value.  Simply copy the properties from a subscriber 
object (session scoped or otherwise) to a formbean (the one being used 
to render the form values).  There's a copyProperties method in 
org.apache.commons.beanutils.BeanUtils:

   http://tinyurl.com/zp6ag

Also, the Spring Framework has a copyProperties method in one of its 
utility classes.  It has the advantage of not throwing a checked 
exception and its parameter ordering makes more sense to some (myself 
included).

A reason to not specify a value for html:text, at the view level, is 
that it overwrites the value in an associated form-bean object.  This 
could lead to overwriting user input or overwriting data that was 
populated from an Action.

It may be acceptable to specify value on a checkbox, for instance, 
because user's don't typically interact with this value directly. 
Still, if a value for a checkbox, like any other form control, was set 
in a controller class, then a page level value will overwrite data.  At 
the very least, this is counterintuitive.  More often, it is incorrect.


-Dave

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by Wendy Smoak <ws...@gmail.com>.
On 8/30/06, Tom Bednarz <li...@bednarz.ch> wrote:

> What is the correct or preferred way to link business-objects with form
> beans. Is this only possible by copying data from a business object to a
> form bean or is there any 'smarter' way?

You might want to take a look at FormDef: https://formdef.dev.java.net/

-- 
Wendy

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by Tom Bednarz <li...@bednarz.ch>.
Thanks a lot for all your input and help. It looks like I need some 
basic concepts clarified. Here a very short background of the 
application and what my intension is:

The object 'subscriber' is a special business object: it represents the 
logged in user and contains a lot of information about him: Personal 
data like name, address, e-mail, preferred language etc. But it contains 
also information about his roles, type of subsciption he bought etc. 
Shortly I need parts of this information almost everywhere in the 
application and thats why the thing sits in session scope.

The action we were discussing 'changePersonalDataForm' represents a form 
where the user can change some of this informations such as personal 
data, language etc. Other things such as roles, subscibtion information 
etc are not visible to the user. The object has logic to retrieve its 
information from various database tables and also store information back 
if there are changes. This is performed exclusively in this object not 
in any action. The object is created and filled when the user has 
successfully logged in.

So I used 

<html:text value="${sessionScope.subscriber.firstname}"
      property="firstname" name="firstname" maxlength="64"
      size="32"/>

to initially fill the firstname directly from the business object into 
the form. If the user submits the form the information is updated in the 
object and also written back to the DB server. Nice things like 
ChangeEventListeners as available in Swing and also in JSF are sort of 
missing in Struts (at least I did not find something alike)

So the key question seems to be:

What is the correct or preferred way to link business-objects with form 
beans. Is this only possible by copying data from a business object to a 
form bean or is there any 'smarter' way? Copying ends up in writing a 
lot of copy-code which is inefficient. I am looking for sort of a 
component model, which means I have a couple of objects in session or 
even application scope and can directly use then in many different 
forms/actions. But so far I am missing a concept like SWING controls do 
have it where you can bind controls such as a listbox, textbox etc 
directly to objects or even database tables. I think JSF offers similar 
things but I don't see anything alike in struts 1.2.8 (the version I am 
currently using).

Maybe someone could clarify these things for me or you may have some 
good recipes for me, how to solve these things best with Struts.


Many thanks again for your help!

Tom


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by Laurie Harper <la...@holoweb.net>.
Tom Bednarz wrote:
> David Durham wrote:
>> Tom Bednarz wrote:
>>> I think the validator fires too early, but probably I am doing 
>>> something wrong. Maybe somebody can hp!
>>
>> Basically, you need 2 actions, one to populate the form and one to 
>> change the personal data.

Or at least two action mappings, if you want to use automatic 
validation. If you're happy to invoke validation manually, you can get 
by with just one action and one mapping.

> This is EXACTLY what I like to AVOID! With this concept I have to write 
> dozends of useless action classes!

Nope, with that approach you would simply *seperate* your one action 
class into two classes which each encapsulate one branch or your if 
statement below -- i.e. an action that does 'Populate the form' and one 
that does 'Perform update operation'.

If you don't like having two separate classes, there are various options 
for combining them, including the various flavours of dispatch action 
and the approach you illustrate below.

> In my Action class I did:
> 
> public ActionForward execute(ActionMapping mapping, ActionForm form,
>           HttpServletRequest request, HttpServletResponse response)
> {
>     ActionForward af = null;
>     ......
> 
>     String operation = request.getParameter("operation");
>     .....
> 
>     if (operation != null &&
>         operation.compareToIgnoreCase("update") == 0)
>     {
>     ..... Perform update operation here
>     }
>    else  // showData
>    {
>     .... Populate form here
>    }
>    return (new ActionForward("/showPersonalData.do"));
> }
> 
> The surprising thing (at least for me...) is, that when running in the 
> debugger, execute method is NEVER called (does not stop at any 
> breakpoint) !!!

Do you have validate="true" on your action mapping? If validate is set 
to true, the framework will perform validation for you automatically 
before invoking the action. Hence, you need to either a) have two action 
mappings in your config (note: two mappings, not necessarily two action 
classes), one with validate=false and operation set to null and one with 
validate=true and operation set to whatever; or b) using a single action 
mapping, set validate=false and call validate() manually as appropriate.

> Is there no more intelligent way then creating lots of actions?? Maybe 
> this is a motivation to move to JSF!!

L.


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by Tom Bednarz <li...@bednarz.ch>.
David Durham wrote:
> Tom Bednarz wrote:
>> I think the validator fires too early, but probably I am doing 
>> something wrong. Maybe somebody can hp!
> 
> Basically, you need 2 actions, one to populate the form and one to 
> change the personal data.
> 
> 

David,

This is EXACTLY what I like to AVOID! With this concept I have to write 
dozends of useless action classes!

In my Action class I did:

public ActionForward execute(ActionMapping mapping, ActionForm form,
           HttpServletRequest request, HttpServletResponse response)
{
     ActionForward af = null;
     ......

     String operation = request.getParameter("operation");
     .....

     if (operation != null &&
         operation.compareToIgnoreCase("update") == 0)
     {
	..... Perform update operation here
     }
    else  // showData
    {
	.... Populate form here
    }
    return (new ActionForward("/showPersonalData.do"));
}

The surprising thing (at least for me...) is, that when running in the 
debugger, execute method is NEVER called (does not stop at any 
breakpoint) !!!

Is there no more intelligent way then creating lots of actions?? Maybe 
this is a motivation to move to JSF!!

Tom


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by David Durham <dd...@vailsys.com>.
Tom Bednarz wrote:
> I think the validator fires too early, but probably I am doing something 
> wrong. Maybe somebody can hp!

Basically, you need 2 actions, one to populate the form and one to 
change the personal data.



> 
> I have the following form bean defined in struts-config.xml:
> 
>     <form-bean name="changePersonalDataForm" 
> type="org.apache.struts.validator.DynaValidatorActionForm" >
>         <form-property name="subscriberid" type="java.lang.String" />
>         <form-property name="firstname" type="java.lang.String" />
>         <form-property name="familyname" type="java.lang.String" />
>         <form-property name="zip" type="java.lang.String" />
>         <form-property name="place" type="java.lang.String" />
>         <form-property name="country" type="java.lang.String" />
>         <form-property name="addr1" type="java.lang.String" />
>         <form-property name="addr2" type="java.lang.String" />
>         <form-property name="addr3" type="java.lang.String" />
>         <form-property name="email" type="java.lang.String" />
>     </form-bean>
> 
> 
> and the following action mapping:
> 
>     <action
>       attribute="changePersonalDataForm"
>       input="/form/changePersonalData.jsp"
>       name="changePersonalDataForm"
>       path="/changePersonalData"
>       scope="request"
>       type="ch.smartsol.struts.action.ChangePersonalDataAction">
>       <forward name="success" path="/template/SuccessMessage.jsp" />
>       <forward name="failure" path="/form/changePersonalData.jsp" />
>     </action>
> 
> 
> The idea is, that I show a form that contains already data and the user 
> can edit it. When the form is submitted, the validator should check the 
> user input. Here is my validator configuration:
> 
> 
> <form name="/changePersonalData">
>   <field property="firstname" depends="required">
>     <msg name="required" key="PersonalData.firstname.required"/>
>   </field>
>   <field property="familyname" depends="required">
>     <msg name="required" key="PersonalData.familyname.required"/>
>   </field>
>   <field property="zip" depends="required">
>     <msg name="required" key="PersonalData.zip.required"/>
>   </field>
>   <field property="place" depends="required">
>     <msg name="required" key="PersonalData.place.required"/>
>   </field>
>   <field property="country" depends="required">
>     <msg name="required" key="PersonalData.country.required"/>
>   </field>
>   <field property="addr1" depends="required">
>     <msg name="required" key="PersonalData.addr1.required"/>
>   </field>
>   <field property="email" depends="required,email">
>     <msg name="required" key="PersonalData.email.required"/>
>     <msg name="email" key="PersonalData.email.email"/>
>   </field>
> </form>
> 
> Now it seems, that the validator gets fired BEFORE the form is filled! 
> In the JSP that displays the form, I get lots of error messages all 
> fired by the 'required' validator saying, that the field must not be 
> empty, but all fields are filled corretly!!.
> 
> Here is an extract of the JSP:
> 
> <TABLE border="0" width="95%" align="center">
>   <TR>
>     <TD class="headerLeftLight" width="200">
>        <bean:message key="ChangePersonalData.firstname"/>
>     </TD>
>     <TD class="dataLightAlignLeft" width="200">
>       <html:text value="${sessionScope.subscriber.firstname}"
>       property="firstname" name="firstname" maxlength="64"
>       size="32"/>
>     </TD>
>     <TD class="errMessage">
>        <html:errors property="firstname"/>
>     </TD>
>   </TR>
>   <TR>
>     <TD class="headerLeftStrong">
>       <bean:message key="ChangePersonalData.lastname"/>
>     </TD>
>     <TD class="dataStrongAlignLeft">
>       <html:text value="${sessionScope.subscriber.familyname}"
>       property="familyname" name="familyname" maxlength="64"
>       size="32"/>
>     </TD>
>     <TD class="errMessage">
>       <html:errors property="familyname"/>
>     </TD>
>   </TR>
>   .......
> 
>  </TABLE>
> 
> Every row contains a label, an input control and a TD to display 
> validation errors of the specific field.
> 
> Does anybody know what is going wrong here??
> 
> Many thanks for your help!
> 
> Tom
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: validator and DynaValidatorActionForm

Posted by Wendy Smoak <ws...@gmail.com>.
On 8/30/06, Tom Bednarz <li...@bednarz.ch> wrote:

> The idea is, that I show a form that contains already data and the user
> can edit it. When the form is submitted, the validator should check the
> user input. Here is my validator configuration:
...
> Now it seems, that the validator gets fired BEFORE the form is filled!
> In the JSP that displays the form, I get lots of error messages all
> fired by the 'required' validator saying, that the field must not be
> empty, but all fields are filled corretly!!.

Request -> form bean population -> validation -> Action.execute() ->
forward -> JSP

My advice is to turn off automatic validation, and call it explicitly
when you want it to happen.  That will stop the 'validation errors on
first form display' problem.

Looking at your config, you always pull values from a session scoped
'subscriber' object.

I don't think you need 'value' here:

    <html:text value="${sessionScope.subscriber.familyname}"
      property="familyname" name="familyname" maxlength="64"
      size="32"/>

The 'name' attribute [1] is "The attribute name of the bean whose
properties are consulted when rendering the current value of this
input field."

Does this work?

    <html:text name="subscriber" property="familyname"
                    maxlength="64" size="32"/>

Even after dealing with the 'first display' problem, that still leaves
you validating the form bean (which may be missing data) yet
displaying values from some other bean sitting in session scope.

[1] http://struts.apache.org/1.x/struts-taglib/tlddoc/html/text.html

-- 
Wendy

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


RE: validator and DynaValidatorActionForm

Posted by David Friedman <hu...@ix.netcom.com>.
Why are you making these fields so complex?  You have

   <html:text value="${sessionScope.subscriber.familyname}"
       property="familyname" name="familyname" maxlength="64"
       size="32"/>

Instead of the simple form:

<html:text property="familyname" maxlength="64" size="32" /> ?

Why do you need to specify all of that redundant information like value and
name when you have the property attribute?  And why are you pulling values
from the session scope instead of the request data that was submitted?  That
seems an unusual choice to my thinking.

Also, what is your html:form action specified there?  Is it listed as
"/changePersonalDataForm"? Or another form name?  Using a different form
might be your problem - after all the html:form uses the bean associated
with that form so a different bean would have different values, especially
if you are mixing and matching values from a session scoped bean with a
request that has its own values.

Regards,
David

-----Original Message-----
From: Tom Bednarz [mailto:list@bednarz.ch]
Sent: Wednesday, August 30, 2006 12:34 PM
To: Struts Users Mailing List
Subject: validator and DynaValidatorActionForm


I think the validator fires too early, but probably I am doing something
wrong. Maybe somebody can hp!

I have the following form bean defined in struts-config.xml:

     <form-bean name="changePersonalDataForm"
type="org.apache.struts.validator.DynaValidatorActionForm" >
     	<form-property name="subscriberid" type="java.lang.String" />
     	<form-property name="firstname" type="java.lang.String" />
     	<form-property name="familyname" type="java.lang.String" />
     	<form-property name="zip" type="java.lang.String" />
     	<form-property name="place" type="java.lang.String" />
     	<form-property name="country" type="java.lang.String" />
     	<form-property name="addr1" type="java.lang.String" />
     	<form-property name="addr2" type="java.lang.String" />
     	<form-property name="addr3" type="java.lang.String" />
     	<form-property name="email" type="java.lang.String" />
     </form-bean>


and the following action mapping:

     <action
       attribute="changePersonalDataForm"
       input="/form/changePersonalData.jsp"
       name="changePersonalDataForm"
       path="/changePersonalData"
       scope="request"
       type="ch.smartsol.struts.action.ChangePersonalDataAction">
       <forward name="success" path="/template/SuccessMessage.jsp" />
       <forward name="failure" path="/form/changePersonalData.jsp" />
     </action>


The idea is, that I show a form that contains already data and the user
can edit it. When the form is submitted, the validator should check the
user input. Here is my validator configuration:


<form name="/changePersonalData">
   <field property="firstname" depends="required">
     <msg name="required" key="PersonalData.firstname.required"/>
   </field>
   <field property="familyname" depends="required">
     <msg name="required" key="PersonalData.familyname.required"/>
   </field>
   <field property="zip" depends="required">
     <msg name="required" key="PersonalData.zip.required"/>
   </field>
   <field property="place" depends="required">
     <msg name="required" key="PersonalData.place.required"/>
   </field>
   <field property="country" depends="required">
     <msg name="required" key="PersonalData.country.required"/>
   </field>
   <field property="addr1" depends="required">
     <msg name="required" key="PersonalData.addr1.required"/>
   </field>
   <field property="email" depends="required,email">
     <msg name="required" key="PersonalData.email.required"/>
     <msg name="email" key="PersonalData.email.email"/>
   </field>
</form>

Now it seems, that the validator gets fired BEFORE the form is filled!
In the JSP that displays the form, I get lots of error messages all
fired by the 'required' validator saying, that the field must not be
empty, but all fields are filled corretly!!.

Here is an extract of the JSP:

<TABLE border="0" width="95%" align="center">
   <TR>
     <TD class="headerLeftLight" width="200">
        <bean:message key="ChangePersonalData.firstname"/>
     </TD>
     <TD class="dataLightAlignLeft" width="200">
       <html:text value="${sessionScope.subscriber.firstname}"
       property="firstname" name="firstname" maxlength="64"
       size="32"/>
     </TD>
     <TD class="errMessage">
        <html:errors property="firstname"/>
     </TD>
   </TR>
   <TR>
     <TD class="headerLeftStrong">
       <bean:message key="ChangePersonalData.lastname"/>
     </TD>
     <TD class="dataStrongAlignLeft">
       <html:text value="${sessionScope.subscriber.familyname}"
       property="familyname" name="familyname" maxlength="64"
       size="32"/>
     </TD>
     <TD class="errMessage">
       <html:errors property="familyname"/>
     </TD>
   </TR>
   .......

  </TABLE>

Every row contains a label, an input control and a TD to display
validation errors of the specific field.

Does anybody know what is going wrong here??

Many thanks for your help!

Tom


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org