The problem is really that you are going against the UIInput part of
the JSF specification. By definition, during the processValidators
method, if a UIInput component is found to be invalid, then
renderResponse is called on the current facescontext.
Since you want control of the component's submitted value, perhaps
your best bet is component binding or a phase listener, or you could
even queue custom events.
I can't see an easy way for you do this without a significant hack
though. Especially, trying to reset submitted values will get
especially ugly for components in iterating parents (data table, data
list, tree2, etc.).
The easiest hack I would say is to create a phase listener that
listens for the before and after validation phase. In that phase
listener, replace the faces context. Crude example:
public void beforePhase(PhaseEvent evt) {
new CustomFacesContext(evt.getFacesContext());
}
public void afterPhase(PhaseEvent evt) {
((CustomFacesContext)evt.getFacesContext()).unwrap();
}
private class CustomFacesContext extends FacesContextWrapper
{
private FacesContext wrapped;
public CustomFacesContext(FacesContext orig) {
super(orig);
wrapped = orig;
FacesContext.setCurrentInstance(this);
}
public void renderResponse() { /* swallow */ }
public void unwrap() { wrapped.setFacesContext(wrapped); }
}
Now despite invalid UIInput components, the phases will continue. I
haven't thought through all the ramifications though. You may get some
ugly side-effects from doing this.
-Andrew
On 7/6/07, Toppac <[EMAIL PROTECTED]> wrote:
I am using a custom converter to return null so I can bypass these conversion
errors during submission. What I want to happen is that even when I bypass
these and have my converter return null, I want to have a way to inject the
submitted value back in during renderResponse. This does not appear to work
with MyFaces out of the box. There is not hook to the converter for some
reason and the local value of the component is null. That is the problem I
am trying to solve.
Andrew Robinson-5 wrote:
>
> Just about all components check their member values before they check
> the value bindings. UIOutput is no different. So if either the
> submittedValue or local value is set, your ValueBinding expression
> will not be called. The local value should be converted before being
> rendered however.
>
> If you don't want to throw a conversion error when the user enters
> "abc", then write a custom converter that doesn't throw an error. You
> could turn "abc" in to null or 0, based on your requirements for
> example.
>
> If you use custom validators and custom converters, you can make it so
> that exceptions are never thrown from converting and validation.
>
> Out of curiosity, why do you want to update the model when there is
> invalid data?
>
> If you are only wanting to submit one value and don't care if other
> values are invalid, then I would suggest using the subForm component
> from the sandbox or the a4j:region if you are using ajax4jsf.
>
> -Andrew
>
> On 7/6/07, Toppac <[EMAIL PROTECTED]> wrote:
>>
>> Ok I follow. There a couple of problems here though. let's say my
>> converter
>> is for java.lang.Integer and the submitted value from the POST is "abc".
>> I
>> can't use the default converter since it will throw an exception and try
>> to
>> skip directly to renderResponse, not what i want to happen. Right now my
>> converter is just returning null at this point and caches the submitted
>> value. The rest of the lifecycle goes through and during update model the
>> submitted value is set to null since updateModel succeeds.
>>
>> During renderResponse it appears that it tries to get the value from the
>> component first, and if the component does not have a value it tries to
>> get
>> it from evaluating the value binding (see UiOutput.getValue). In this
>> case
>> they are both null, which is expected. But it never tries to call my
>> converter which would restore the cached submitted valued.
>>
>>
>>
>>
>>
>> Andrew Robinson-5 wrote:
>> >
>> > Typical UIInput behavior:
>> >
>> > Decode phase ->
>> > Is there a value in the POST values with the current component's client
>> > ID?
>> > If so, set the submitted value to that
>> >
>> > Validate phase ->
>> > If there is a submitted value, get the converter
>> > If there is a converter, convert the submitted value using getAsObject
>> > Validate the submitted value
>> > If valid, set the local value
>> >
>> > Update phase ->
>> > If there is a local value, update the value binding property
>> >
>> > Render phase ->
>> > If there is a submitted value, render that
>> > Otherwise, get the value from the component
>> > If there is a converter, convert the value using getAsString
>> > Render the value
>> >
>> > So as you can see, as long as a UIInput control has a submitted value,
>> > it will never render the value from the value attribute of the
>> > component. Typically submitted values are only cleared in the validate
>> > method of UIInput (if the converted value is valid)
>> >
>> > On 7/6/07, Toppac <[EMAIL PROTECTED]> wrote:
>> >>
>> >> I don't think I follow what you are saying exactly. Can you elaborate?
>> >>
>> >>
>> >>
>> >> Andrew Robinson-5 wrote:
>> >> >
>> >> > Converter will only be called if there is no submitted value.
>> >> > Submitted values are already technically converted as they came from
>> >> > the client, so there is no need to use the converter.
>> >> >
>> >> > On 7/6/07, Toppac <[EMAIL PROTECTED]> wrote:
>> >> >>
>> >> >> Just for a small background. I am trying to find a way to fail
>> >> validation
>> >> >> and/or conversion without dumping out of the JSF lifecycle to
>> render
>> >> >> response. I'd like to inject a custom converter that when it fails
>> to
>> >> >> convert it saves the submitted value to a session scoped Map and
>> then
>> >> >> during
>> >> >> render response, when it tries to render the component that failed
>> >> >> conversion, the getAsString method would see that the incoming
>> value
>> >> is
>> >> >> null
>> >> >> and would go to the session map to grab the last submitted value.
>> >> >>
>> >> >> Sounds easy enough and should work. But when I tried it, it appears
>> >> that
>> >> >> during render response, if the value on the domain model is null
>> (or
>> >> if
>> >> >> the
>> >> >> component value is null, not sure) it does not call the
>> >> >> converter.getAsString method. I am not sure why. If someone can
>> tell
>> >> me
>> >> >> why
>> >> >> and where it makes this decision that would be great. If this is a
>> bug
>> >> >> then
>> >> >> great also. But if it is not a bug then can anyone suggest a way to
>> do
>> >> >> what
>> >> >> I am trying to do?
>> >> >> --
>> >> >> View this message in context:
>> >> >>
>> >>
>>
http://www.nabble.com/Converter.getAsString-not-called--tf4038047.html#a11472287
>> >> >> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>> >> >>
>> >> >>
>> >> >
>> >> >
>> >>
>> >> --
>> >> View this message in context:
>> >>
>>
http://www.nabble.com/Converter.getAsString-not-called--tf4038047.html#a11472464
>> >> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>> >>
>> >>
>> >
>> >
>>
>> --
>> View this message in context:
>>
http://www.nabble.com/Converter.getAsString-not-called--tf4038047.html#a11472718
>> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>>
>>
>
>
--
View this message in context:
http://www.nabble.com/Converter.getAsString-not-called--tf4038047.html#a11473052
Sent from the MyFaces - Users mailing list archive at Nabble.com.