Although null and date are two separate issues, but I'm gettin the picture.
I may create my own converters and attach them to all my fields as I'm
pleased. But I'm trying to have some common services (if thay're missing in
the framework) in a single place, well this may be arguable what's better.
Sorry for annoyance, but still, why JSF would not check for nulls for me
(you've pointed the right method to be changed).
With the date conversion I'll postpone the issue, I have to spend more time
tracing it.
vlad
On 7/6/07, Andrew Robinson <[EMAIL PROTECTED]> wrote:
Convert an empty string in your converter to null. That way if the
Date is null in the bean, the converter will convert the empty string
to null, and since both will be null, you will get no change event.
-Andrew
On 7/6/07, Vladimir Isakovich <[EMAIL PROTECTED]> wrote:
> Andrew,
> thanks for pointing to the source. Aparently this is the exact place.
>
> Now I guess (sorry for guessing, I should take more time and learn the
code)
> getSubmittedValue() never returns null, the request parameter values
> submitted from a page are never nulls; empty strings at the most.
> So, should not this method convert them into nulls?
>
> Also, I clearly see here the call to getConvertedValue(context,
> submittedValue), and just wonder why I am getting valueChangeEvent fired
for
> every date on my screen, when they are not changed. ( java.util.Date in
> pojo)
> I'm displaying oldValue/newValue from the event (toString of cause) and
they
> look different
>
>
> vlad
>
> On 7/6/07, Andrew Robinson <[EMAIL PROTECTED]> wrote:
> > Best way to answer this is to point you to the UIInput code:
> >
> > public void validate(FacesContext context) {
> > ...
> > Object submittedValue = getSubmittedValue();
> > if (submittedValue == null) return;
> > Object convertedValue = getConvertedValue(context, submittedValue);
> > ...
> > Object previousValue = getValue();
> > setValue(convertedValue);
> > setSubmittedValue(null);
> > if (compareValues(previousValue, convertedValue))
> > {
> > queueEvent(new ValueChangeEvent(this, previousValue,
convertedValue));
> > }
> > ...
> > protected boolean compareValues(Object previous,
> > Object value)
> > {
> > return
> previous==null?(value!=null):(!previous.equals(value));
> > }
> >
> > So, as you can see the value change event is generated if the
> > component's "getValue()" returns an object that is not equal to the
> > converted submitted value.
> >
> >
> >
> > On 7/6/07, Vladimir Isakovich <[EMAIL PROTECTED]> wrote:
> > > 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
> > > > > > >
> > > > > >
> > > > > >
> > > > >
> > > > >
> > > >
> > >
> > >
> >
>
>