On 4/4/06, Richard Wallace <[EMAIL PROTECTED]> wrote:
Note that your use cases for "consolidation" are probably on the 20% side of the 80/20 rule :-).
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.
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.
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.
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.
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.
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]> 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.
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.
>>> 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.
>> 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.
>> 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

