myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Scott O'Bryan <darkar...@gmail.com>
Subject Re: Converter.getAsString not called?
Date Fri, 06 Jul 2007 22:45:28 GMT
:)  That was going to be my suggestion.

Andrew Robinson wrote:
> Another solution you could consider, is doing the
> conversion/validation in the backing bean instead of in the component,
> it is messy, but possibly less messy than what I told you. It is more
> work though.
>
> public class Bean {
> private Integer intValue;
> private String submittedIntValue;
> // standard get/set properties here for intValue
>
> public String getSubmittedValue() {
>  if (submittedIntValue == null) { return intValue.toString(); }
>  return submittedIntValue();
> }
> public void setSubmittedValue(String value) {
> try {
>  submittedIntValue = value;
>  if (value == null || value.length() == 0) { intValue = null; }
>  intValue = Integer.parseInt(value);
>  submittedIntValue = null;
> } catch (NumberFormatException ex) { }
> }
> ...
>
> <h:inputText value="#{bean.submittedIntValue}" />
>
> Since the backing bean takes any string, you will never get conversion
> or validation errors and update model will always take place. Then
> since the inputText is valid, there is no submitted value and no local
> value, and thus it would get the value from the value binding. Thus it
> is the bean that is doing the work of the conversion and validation.
>
> -Andrew
>
> On 7/6/07, Toppac <toppac@gmail.com> wrote:
>>
>> Unfortunately I was afraid this may be the answer. I knew from 
>> looking at the
>> code that it may require heavy modfications and a departure from the JSF
>> spec. Hopefully I can get the requirements changed. Thanks.
>>
>>
>> Andrew Robinson-5 wrote:
>> >
>> > 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 <toppac@gmail.com> 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 <toppac@gmail.com> 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 <toppac@gmail.com> 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 <toppac@gmail.com> 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.
>> >>
>> >>
>> >
>> >
>>
>> -- 
>> View this message in context: 
>> http://www.nabble.com/Converter.getAsString-not-called--tf4038047.html#a11473455

>>
>> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>>
>>
>


Mime
View raw message