>From the jsr-314-comments mailbox comes this discussion between
myself and Mathias Werliz about inter-component validation.
Unfortunately the discussion progressed outside of the mailinglist, so
the post below is the aggregate of the individual messages. If there
is confusion we can summarize the discussion up to this point and
continue the discussion on each individual point.
I wonder that there seems to be little interest in this subject - When I
started to write custom components that consist of more than one
EditableValueHolder child-component I immediatly run into the need to
create such inter-component Validators. After struggling for some time I
realized that this is just not possible (or better say not possible
without duplicating quite some code from the jsf basis to separete
convertion and validation in the subcomponents). Using post-update
validation in the managed bean allways left me feeling unsatisfied since
it doesn't allow to distribute such components with their corresponding
validators. The whole validation-facility of jsf seemed to be quite
limited and unfinished to me.
My vote goes to change this in JSF 2.1 by changing the way this is
handled by separating convertion and validation into two separate steps
(thus effectivly adding an additional step into the jsf lifecyle).
- Norbert
---------- Forwarded message ----------
From: Dan Allen <dan.j.allen(a)gmail.com>
Date: Thu, Jul 9, 2009 at 2:09 PM
Subject: Re: inter-component and form-level validation
To: "Werlitz, Mathias" <werlitz(a)adesso.de>
Cc: jsr-314-comments(a)jcp.org
On Thu, Jul 9, 2009 at 11:36 AM, Werlitz, Mathias <werlitz(a)adesso.de>
wrote:
Sorry for the late response. I’m very busy on a customer
project at the moment, analysing JSF 1.2 (view state) and
Facelets memory consumption on IBM Portal 6.1.
I agree that there are two basic approaches to solve
multiple-field / form-validation:
1. model based validation after the update model phase and
2. validating the converted values of multiple components
In both cases there should be an easy way to assign the proper
validation message to the originating input component or group
of input components. With complex forms including inputs
within naming containers like <h:dataTable> this may become
quite complicated. Flattening the properties of the object
graph for JSR-303 model validation does not seem to be a good
idea in this case.
I realize that JSR-303 isn't going cover every case. I must
admit to still being the fence on how to best handle the
situation you are citing...meaning can I do it comfortably
with JSR-303 or not? I think a solid use case would help us
test the limits.
Well I simplified a test case – I’m unsure that this is easily
done with JSR-303. Image a form with a master date and several
additional dates. The number of the additional dates is
dynamic – will be configured by the user (added and removed)
or determined by the server.
For simplicity there is only one multi-field validation rule:
all additional dates must be after the master date. The view
would look something like this (note: the list of additional
dates is a list of a custom bean that stores the date and
maybe additional data for every entry):
<h:input id=”masterDate” value=”mybean.masterDate” />
<h:datatable value=”mybean.myAdditionalDates” var=”item” >
<h:input id=”addtionalDate”
value=”item.additionalDate” />
</h:datatable>
This could be done with JSR-303. You can have a validation annotation
on the array (or List) property holding the "after" dates and say that
they must come after the master date property. But again, the
limitation is that it has to happen after update model values.
Earlier when I said you have to flatted your model, I didn't mean you
couldn't use collections. You just can't easily validate a property on
one class against a property on another.
But pointing that aside, you could still accomplish w/ a regular JSF
validator if all conversions happened before the validation phase.
Then you just do something like:
<h:input id="additionalDate" value="#{item.additionalDate}">
<x:validateAfter id="masterDate"/>
</h:input>
One downside of the model based validation is that the
whole validation process is split up into two phases.
That means the user may get the error messages in two
bunches: first the errors of the validation phase and
later the model errors. This can be quite confusing.
The reality is, there are two validation phases in input-based
applications. You simply cannot test some business validations
if you don't have correct data to start with. I think the real
point is to make sure that all input validation is handled
together...and that business validation is really business
validation. Having one date before another I agree is likely
an input validation, not a business validation.
Yes, that’s the point. At the moment JSF does make it very
hard to do the input validation altogether.
There will likely always be two steps. The question is, can we get
those two steps right?
To emphasize why there must be two validation phases, consider
this case. You walk into an ice cream store and the employee
asks you which flavor of ice cream you want. You say you want
pizza. They say, "Sir, we don't have pizza, you have to pick
and ice cream." Then you say that you want Heath ice cream.
The employee says, sorry, we don't have that in stock. So the
first is an input validation, the second is business. The
employee couldn't have told you they don't have Heath ice
cream in stock because the employee doesn't know what you
want. It's not really that confusing.
I agree with you, but in fact there are three steps where
messages could be associated with an input field (convert,
validation, business rules) and every step depends on the
previous one.
Well, one common requirement of our customers is:
Display error messages as early as possible.
Separating the validation into two phases makes this
hard. Using good old Struts this example is no problem
at all.
That's because Struts effectively updated the model and then
validated, moving all validation to the later phase. In JSF
there is an understanding that values won't get assigned to
the model unless they are valid syntax or type. You could
throw that out the window and do all your validations after
the update model values phase and get the same result. So we
are questioning the fundamental guarantee of JSF (which, by
the way, may need to be questioned).
Well I think you got me wrong. The point is that in Struts you
are able to store all the form data (as strings) in a form
bean. You are responsible to make your own conversation. But
because of that you are able to validate all input data
including multi-field validation. On success you proceed to
assign the values on your own to the real model.
That’s not perfect. The only problem with JSF is that you
don’t have this intermediate view on the form data where all
converted values of the form is available altogether before
deciding to move on to the update model phase.
I think we are saying the same thing. JSF applies the values directly
to the model by attempting to convert each value. Now, you could copy
all properties to a model with string properties and essentially
coerce JSF into skipping validation so that you can handle it
yourself, but that really defeats a large goal of JSF.
I like your idea of dividing converting and
validation. I think JSR-303 model based validation is
not sufficient. In the discussion with my college we
had a similar idea as a workaround for JSF 1.2: We
thought about a special custom validator added to all
relevant input components that collects all converted
input data from the components and the corresponding
client ids/component instances. This also works fine
with <h:dataTable>. The data could be collected with a
Map or special validation-model bean. At the end of
the validation phase another special form/multi-field
validator (possible phase listener) is called with the
collected data and invokes the validation logic. This
way you get all converted data, components/client ids,
the real model data is not touched at all and the
whole validation is processed in one phase.
It seems blatantly obvious to me that all conversion should
happen before any validation occurs. I think the current
situation is ridiculous and it's the root of why multi-field
validation is so screwed up to begin with.
See my previous comment… The question is: when this will
change. JSF 2.0 would be the right version. But I guess it’s
already too late for such a fundamental change in the
lifecycle – separating conversation and validation.
It won't be JSF 2.0. Hopefully JSF 2.1 or sooner.
-Dan
--
Dan Allen
Senior Software Engineer, Red Hat | Author of Seam in Action
http://mojavelinux.com
http://mojavelinux.com/seaminaction
http://in.relation.to/Bloggers/Dan
NOTE: While I make a strong effort to keep up with my email on a daily
basis, personal or other work matters can sometimes keep me away
from my email. If you contact me, but don't hear back for more than a
week,
it is very likely that I am excessively backlogged or the message was
caught in the spam filters. Please don't hesitate to resend a message
if
you feel that it did not reach my attention.
--
Dan Allen
Senior Software Engineer, Red Hat | Author of Seam in Action
Registered Linux User #231597
http://mojavelinux.com
http://mojavelinux.com/seaminaction
http://in.relation.to/Bloggers/Dan