Andrew,
Are you saying that if in the method called by valueChangeListener I take:
event.getOldValue() - it's not the same as my 'original value' in my pojo?
It's alredy has been converted from say Integer to String?

The poin I'm trying to make is why I should add another layer of protection
against valueChangeEvent, when it could be done in JSF.

Also in your example: String str = converter.getAsString(value);
JSF API want converter.getAsString(FacesContext,UIComponent,value).
Do you know why it needs two additional args, is it gonna plug this value
into the component and then attach this component to the tree?

I've just wrote this code for bloking the unwanted valueChangeEvent, but
have not tested it yet. I was the above mentioned getAsString(), but with
the only purpose of getting converted value - not updating the tree.


   public static boolean isValueChanged(ValueChangeEvent event) {
       if (event.getOldValue() == null) {
           if (StringUtils.isEmpty(event.getNewValue().toString()))
               return false;
           else
               return true;
       }

       UIInput comp = (UIInput)event.getComponent();
       Converter conv = comp.getConverter();
       if (conv == null) {
           if (event.getOldValue().toString().equals(event.getNewValue
().toString()))
               return false;
           else
               return true;
       } else {
           Object oldVal =
               conv.getAsString(FacesContext.getCurrentInstance(), comp,
                                event.getOldValue());
           if (oldVal.equals(event.getNewValue()))
               return false;
           else
               return true;
       }
   }

vlad

On 7/6/07, Andrew Robinson <[EMAIL PROTECTED]> wrote:

The original value is already converted by specification. The purpose
of a converter is to take an object from the back-end and change it to
a view (HTML typically) compatible value and then change the view
value back to a back-end value on submit.

It is the back-end developer's job to ensure the back-end value is
"converted". If you want the original value to be converted using a
JSF converter, then use the Application object to create a converter
from you backing bean when you load the data, and convert the value as
you wish.

The purpose of the value change event is to tell you if the user
changed something. The user changed something if the value they submit
after conversion is not the same as the value from the back-end.

You keep saying "converted original value", but that is an oxymoron by
JSF definition. If my component is a number input field, the converted
value is type Integer and the client value is type String. So the
converter converts between string and integer, not integer and
integer.

To be even more precise, for a converter to work properly the
following must be true:

Converter converter = ...
Object value = component.getValue();
String str = converter.getAsString(value);
Object value2 = converter.getAsObject(str);
if (value2.equals(value)) {
// converter is valid
}

On 7/6/07, Vladimir Isakovich <[EMAIL PROTECTED]> wrote:
> Null vs empty string is not the only one case, the point I'm trying to
make
> here:
> whenever the JSF framework is applying some data conversion (either the
> converter was explicitly declared or not), it may (should) remember that
> conversion rule, so that when that same page is submitted, the framework
(I
> mean JSF) will compare ( for the purpose of firing changeValueEvent) not
the
> original value with the new value but the converted original value with
the
> new value.
>
> Yes this is an old issue with all previous frameworks, but I thought JSF
> could be better. And thinking of the declared converters, cann't I find
all
> converters for a given UIComponent using JSF API. I did not try but I
> thought it's doable.
>
> vlad
>
>
> On 7/6/07, Bryan Basham <[EMAIL PROTECTED]> wrote:
> > The problem you are experiencing is true for any Java/Web
> > framework.  An HTTP request parameter does not understand
> > what a Java null is but always uses the empty string "".  So
> > somewhere in your application (or framework) you have to
> > handle the conversion from "" to null.
> >
> > When it comes to String values, null is not the same as ""
> > so I would recommend that your backing beans be populated
> > with "" instead of null when dealing with JSF.  Alternatively,
> > you could create a NullStringConverter which converts from
> > "" to null.
> >
> > When it comes to non-String values, then your converter should
> > return null from the getAsObject method when an "" is the
> > request parameter.
> >
> > -Bryan
> >
> > vlad10 wrote:
> > > I'm fresh with JSF,
> > > just started building some prototypes with facelets 1.1.11, myfaces
> > > 1.1.3/tomahawk 1.1.3.
> > >
> > > I'm getting this general feeling that the framework is missing some
> > > important feature.
> > > I may create an inputText and populate it with a null value, the
> framework
> > > conviniently will convert it into an empty string and populate my
page.
> > > However, on submit the valueChangeListener will fire with the reason
> that
> > > null is not the same as an empty string.
> > > I have another example. This the initial value is not null. I may
> explicitly
> > > add a converter to that field, so the value stored in POJO as
> jva.util.Date
> > > or as a BigDecimal or anything else will be nicely displayed on the
> screen,
> > > but I'll face again the unwanted behavior of my valueChangeListener.
> > > For the time being, I'm trying to compensate this deficiency in my
app
> by
> > > adding some filtering in a utility class. At the moment it's in the
> > > beginning, just checking null/empty string case:
> > >
> > >     /**
> > >      * UIInput value is never null when submitted, but the POJO is
> always
> > >      * initialized with nulls. This creates a false alarm by
> > > valueChangeListeners.
> > >      * This method tries to compensate this deficiency.
> > >      * @param input
> > >      * @param rec
> > >      * @return
> > >      */
> > >     public static boolean isValueChanged(UIInput input, Object pojo)
{
> > >         String name = input.getId();
> > >         Object val = BeanUtil.getBeanValue(pojo,name);
> > >         if (val == null)
> > >             if(StringUtils.isEmpty(input.getValue().toString()))
> > >                 return false;
> > >             else
> > >                 return true;
> > >         return ( input.getValue().toString().compareTo(val.toString
())
> != 0);
> > >     }
> > >
> > > My question: am I missing something????
> > > Do I really need to add another layer in my app, I may call it
something
> > > like JSF Frendly POJOs. I may perform all necessary conversions
right
> there
> > > when moving data from DB to the screen, and then on submit perform
the
> > > opposit conversion when moving data back. I hope I can avoid that.
> > > Is not it possible for a framework to 'remember' not just an
oldValue,
> but
> > > also the conversion performed, so prior to comparing old/new values
it
> would
> > > apply that same converter to the old value???
> > > I think, this part has been missed.
> > >
> > > thanks
> > > vlad
> > >
> >
> >
>
>

Reply via email to