Craig McClanahan wrote:
On 4/4/06, *Richard Wallace* <[EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> wrote:
Mike Kienenberger wrote:
>> Mike Kienenberger wrote:
>>
>>> It is possible to simulate a custom required validator
>>> (see
http://wiki.apache.org/myfaces/OptionalValidationFramework), but
>>> it isn't going to help you in any way
>>>
>
> On 4/4/06, Richard Wallace < [EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> wrote:
>
>> How so?
>>
>
> No matter what you do, you're still going to have to write java code
> that consolidates messages to display them. It's just as easy to
> consolidate FacesMessages as it is to consolidate some custom data
> type that you'd conceivably generate in a custom required validator.
> And the required validator controller component is slow due to the
> fact that it has to walk the entire component tree a couple times in
> order to fire the validation and then adjust the component
validation
> state.
>
I guess you're right about the FacesMessages. The only thing I'm not
sure about is how to differentiate the messages I would want to
consolidate from messages that I want to display as is.
Note that your use cases for "consolidation" are probably on the 20%
side of the 80/20 rule :-).
Another thing that I find a little annoying is that you either have
messages tied to a component or global to the page. You can't have
messages tied to a form.
Don't feel limited to using the standard message and messages
components. If the messages themselves are tied to individual input
components, writing a version of the <h:messages> renderer that picks
out only the messages for components nested inside a particular form
is pretty easy.
Well sure, for someone as familiar with it all as you are it's probably
no big deal at all. Now that I've got the general approach from the
description you give down below even I could probably handle it.
And, of course, one of the biggest pains is customizing messages on a
per component basis. What I want is to be able to set the message
to be
displayed for a specific instance rather than for all types of that
component across the application.
I don't know, maybe the solution to my problem is to just have the
validation done in my backing bean. The thing is that that seems
to be
the solution to a lot of my validation use cases. In fact, I don't
think I've run into a single real world use case where the
standard JSF
validation works.
That (validation in the backing bean) seems like the right answer for
*application* defined vaidations that cross multiple components, which
includes the use case you are describing. JSF's validation framework
is focused on single component sorts of validations.
Alright, that makes sense then. I was thinking that the validation
framework in JSF was meant to be a general purpose, handle everything
validation related framework.
>>> Instead, you want to generate standard required validation
messages,
>>> then create a custom renderer for the messages component that
>>> consolidates each of these messages into something else,
probably by a
>>> specific id pattern. I also think you'd be better off
extending the
>>> existing messages renderer than creating it yourself.
>>>
>
>
>> Sounds like a hack to get around a poor validation system.
>>
>
> In this case, it's not the validation system that's the
problem. It's
> the displaying of validation errors. The system logged them as
> FacesMessages, so you simply need to change how they're displayed.
> The messages component renderer is the place to change that.
>
>
But how do you differentiate the messages to be consolidated from
those
that shouldn't be?
Here's a strategy for dealing with "all the errors related to
components in a particular form":
* Build a variant of the standard <h:messages> component that takes some
sort of reference to the containing form component.
* At rendering time for this component, start doing a recursive tree
search of
the form component's children.
* For each component that might have been a source of validation
errors (simplest
test is "instanceof EditableValueHolder" but you might have special
cases too),
call FacesContext.getMessages(String clientId) to grab any messages
assigned
to that client.
* Consolidate all the messages accumulated during this tree search in
any manner
that you desire.
That's a great run down. I'll give this a try sometime soon I think.
The only thing I'm not sure about with that is how could you do global
messages, form specific messages, and component specific messages.
That's probably not a very likely scenario so it's no big deal if I
can't have my cake and eat it too.
>> Is there any
>> way to completely replace the JSF validation process with
something more
>> flexible? I mean, honestly, this is a pretty simple use case
that is
>> extremely difficult to implement.
>>
>
> Sure. JSF is completely pluggable, so you could create your own
> lifecycle factory and create a lifecycle that skips or replaces the
> process validation phase. However, coming up with something "more
> flexible" is going to be a task. You're also going to probably
break
> components that expect a processValidation phase to occur. It'd be
> interesting to hear what you have in mind. I've yet to see any
> decent validation implementations. Before you get too far into
it,
> take a look at subforms (talked about more below) as they solve some
> of the weaknesses of JSF validation.
>
>
I'm not sure of exactly what I'd do. At the moment I'm thinking that
the three things that I'd really like to see are more customizable
messages, required being a child element rather than a component
attribute, and for messages tied to forms in addition to global and
component messages. I was probably being a little extreme when I said
"completely replace". I was just on a bit of a rant cause I've
spent to
much time banging my head against the wall trying to figure out
the best
way of doing things with JSF validation.
As an example of the flexibility JSF does provide (but doesn't deal
directly with your particular issue), consider the fact that Shale
lets you use Commons Validator to implement client side (as well as
server side) validation on standard JSF components.
One of the big things that does really bother me is defining custom
messages on a per component basis. With everything that I've learned
from this thread I think I understand how to deal with the issues I've
had up until now. But not being able to define per component validation
messages just seems like a fundamental shortcoming. I'm glad it's being
addressed in the tomahawk validators by adding a message attribute:
http://issues.apache.org/jira/browse/TOMAHAWK-169?rc=1
Is the next step with that just extending the standard JSF validators to
allow them to have the message attribute? I'm also wondering, can you
set custom required messages if you use the tomahawk extensions?
>> I have to wonder why the required
>> attribute is treated as a special case as well.
>>
>
> I think having the required attribute as a special case was an
example
> of an implementation detail influencing the spec. I'm sure the
idea
> is that if there's no value, then there's no point in validating
it.
> But unfortunately, it's an ugly special-case that you have to
> constantly work around since it's not treated as a "real" validator
> but is instead implemented separately as part of every component.
This was done primarily for usability reasons. The fundamental
philosophy was "there is no point in firing validators when there is
no data to validate" because a typical validator author would assume
something would be there, and inadvertently trigger NPEs. We
originally had the required validation as a standard Validator
implementation, but dealing with this issue would have required some
additional hack on the API that lets a validator say "not only is
there an error here, but don't bother doing any more validations on
it." Much cleaner to have a boolean flag that says whether this
component is required or not.
Also, for any component that extends UIInput, you don't actually have
to do anything to implement this check in your custom component --
it's all done for you in the base class.
>
>
>> Validation in JSF seems
>> to be just a mess. I really like JSF overall, but anytime I start
>> thinking about doing any validation I have to take a couple of
shots of
>> whiskey and bite down on something hard to try and forget about
the pain.
>>
>
> I agree :) It's why I tried to write the
OptionalValidationFramework :)
>
> However, I think using the MyFaces sandbox subform component or the
> ADFFaces subform component is probably a better solution than OVF.
> For one thing, OVF doesn't work well with vanilla JSF 1.1 (requires
> facelets + 1.1 or requires 1.2).
>
> I don't think subform components will help with this specific
> situation, but they'll be helpful in other partial validation
> situations.
>
The subform components definitely look like a good step. It's
definitely one thing that I should have included in my list of
wants for
the JSF validation system.
Rich
Craig