|
From: =?iso-8859-1?Q?<jp....@ti...> - 2003-08-20 14:45:03
|
Hi,=0D=0AI have a basic problem with the form validation. Ok for rejectVa= lue from a validator, but how to handle Mismatch errors from the binder i= tself? =0D=0AAssume using a date field that is malformed by the user. The= editor will not be able to parse the date. Currently I come back to the = form page as expected. But:=0D=0A1) The malformed data is lost. The field= is empty.=0D=0A2) The status.errorMessage is void also.=0D=0A=0D=0AHow n= ot loose the initial input and how be able to write an error message to t= he user?=0D=0A=0D=0ASorry for a so basic question, but if I cannot find t= he solution, it will be worse for new users.=0D=0A=0D=0AJean-Pierre=0D=0A= =0A=0A********** L'ADSL A 20 EUR/MOIS**********=0ATiscali propose l'ADSL = le moins cher du march=E9 : 20 EUR/mois et le modem ADSL offert ! =0APour= profiter de cette offre exceptionnelle, cliquez ici : http://register.ti= scali.fr/adsl/=0AOffre soumise =E0 conditions.=0A |
|
From: Ken K. <kk...@kk...> - 2003-08-20 16:38:00
|
JP,
Petclinic shows an example of this on the add/edit Pet forms and the
addVisit form. Look at the messages.properties for the typeMismatch
messages.
I got a reply from Juergen when I queried about this situation (sent on
17-JUN). See my original message and the reply below.
As to keeping the data intact, your FormController should set the
sessionForm property to true. In petclinic, this is done in the
constructor. The date editor is setup in AbstractClinicForm.initBinder().
There is a problem with this technique in that this process will retain
the bad date data that was entered but not other subsequent data on the
form as it seems to short circuit the rest of the binding process. Try
entering something in the Description field on the addVisit form. Then
enter a bad date, submit and see what happens. Perhaps I'm not doing it
quite right ??
Initially, I tried to work around the ugly stacktrace message I was
getting by creating my own date editor and trapping the ParseException
and setting the field to null, thereby handing it off to the validator.
Ideally, it would be nice if the custom editor would participate in the
same way as validators do, IMO.
Regards,
Ken
jp....@ti... wrote:
>Hi,
>I have a basic problem with the form validation. Ok for rejectValue from a validator, but how to handle Mismatch errors from the binder itself?
>Assume using a date field that is malformed by the user. The editor will not be able to parse the date. Currently I come back to the form page as expected. But:
>1) The malformed data is lost. The field is empty.
>2) The status.errorMessage is void also.
>
>How not loose the initial input and how be able to write an error message to the user?
>
>Sorry for a so basic question, but if I cannot find the solution, it will be worse for new users.
>
>Jean-Pierre
>
>
>
>
Juergen's reply:
>
>
Hi Ken,
You can easily replace the default error message by defining a
MessageSource, i.e. a "messages.properties" bundle or the like. If you
define a message for the key "typeMismatch" there, you'll see that
message in your form in case of an error with code "typeMismatch". You
can even define more specific messages like for "typeMismatch.myField"
or even "typeMismatch.myObject.myField" that will only get used on the
specified field resp. object and field. Of course this works with your
own error codes that your own validator produces too. See the FieldError
javadoc for details.
So I'd suggest to stick to CustomDateEditor but override the respective
messages. This will both keep the offending entry and provide a
localized message. Is that what you meant to achieve? If there's
anything left, let's try to extend CustomDateEditor accordingly.
Juergen
-----Original Message-----
*From:* Ken Krebs [mailto:kk...@kk...]
*Sent:* Tuesday, June 17, 2003 7:32 PM
*To:* jürgen höller [werk3AT]
*Cc:* 'spring-dev-list'
*Subject:* MVC binding and validation
Juergen,
NOTE: This little problem is not pressing as I have an acceptable
solution in place for petclinic which will be posted Real Soon Now ;-) .
In a couple of my petclinic forms, I use BaseCommandController's
initBinder method to install a custom Date PropertyEditor to handle
dates of the form "yyyy-mm-dd". The framework class CustomDateEditor is
not convenient to subclass so I used it's code as a basis for my own
SimpleDateEditor (code is shown below). In this class's setAsText
method, I handle the ParseException to set the object to null because I
do not like the error message that gets bound in if I let it throw an
IllegalArgumentException as does CustomDateEditor. The message looks
like a stack trace and would be incomprehensible to the average end
user, i.e.: *Failed to convert property value of type [java.lang.String]
to required type [java.util.Date]; nested exception is:
java.lang.IllegalArgumentException: Could not parse date: Unparseable
date: "2000-06-"*. This message comes from BeanWrapperImpl's
setPropertyValue throwing a TypeMismatchException. Setting the object
value to null allows the problem to be handled by my validator which
simply reports the now erased date entry as "invalid". Obviously, this
is not ideal. It would be better to allow the PropertyEditor to provide
a user-friendly, localizable exception while preserving the offending
entry. Unfortunately, setAsText can't throw any checked Exceptions like
the ErrorCodedPropertyVetoException that DataBinder's bind method uses.
What do you think ?
Ken
/*
* SimpleDateEditor.java
*
*/
package petclinic.validation;
import java.util.Date;
import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;
import java.text.ParseException;
/**
*
* @author Ken Krebs
*/
public class SimpleDateEditor extends PropertyEditorSupport {
private SimpleDateFormat dateFormat;
/** Creates a new instance of SimpleDateEditor */
public SimpleDateEditor() {
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
}
/**
* Parse the Date from the given text, using the specified DateFormat.
* Trap a ParseException to allow the Validator to handle it.
*/
public void setAsText(String text) {
try {
setValue(this.dateFormat.parse(text));
} catch (ParseException ex) {
// throw new IllegalArgumentException("Could not parse
date: " + ex.getMessage());
setValue(null);
}
}
/**
* Format the Date as String, using the specified DateFormat.
*/
public String getAsText() {
return this.dateFormat.format((Date) getValue());
}
}
|