1

I have gone through this, but the answer is not very clear to me. Hence asking,

For the validate method of the class UIInput, we have this (Marking only those lines which are related to the question)

public void validate(FacesContext context) {

     Object submittedValue = getSubmittedValue();           // LINE 958

     newValue = getConvertedValue(context, submittedValue); // LINE 976

     validateValue(context, newValue);                      // LINE 983

     if (isValid()) {                                       // LINE 987
            Object previous = getValue();
            setValue(newValue);                             // LINE 989
            setSubmittedValue(null);
     }
}

If both Conversion & Validation succeeds, then isValid() returns true.

The component's local value is then set - setValue(newValue), indicated by the flag setLocalValueSet(true)

After that, the submitted value is set to null - setSubmittedValue(null)

If you look at the code for this setValue(...) method of UIInput, it is overridden,

@Override
public void setValue(Object value) {
    super.setValue(value);
    // Mark the local value as set.
    setLocalValueSet(true);
}

So from LINE 989, the call delegated to this above setValue(...). If you look at this method,

@Override
public Object getValue() {
    return isLocalValueSet() ? getLocalValue() : super.getValue();
}

If the local value was set by setValue(...), indicated by the flag setLocalValueSet(true), why is this returning the getLocalValue()? I mean,

isLocalValueSet() ? getLocalValue() : ....

Why is it not

isLocalValueSet() ? getValue() : ....

As seen through above, my confusion is regarding getValue() & getLocalValue() methods. Furthermore, in which case Object previous = getValue(); will be not null?

Community
  • 1
  • 1
Farhan stands with Palestine
  • 13,890
  • 13
  • 58
  • 105

1 Answers1

3

If the local value was set by setValue(...), indicated by the flag setLocalValueSet(true), why is this returning the getLocalValue()?

I think it's helpful to read javadoc of ValueHolder interface.

Object getLocalValue()

Return the local value of this UIComponent (if any), without evaluating any associated ValueExpression.

Object getValue()

Gets the value of this UIComponent. If validation failed, as indicated by FacesContext.isValidationFailed() returning true, always return the local value. Otherwise, first, consult the local value property of this component. If non-null return it. If null, see if we have a ValueExpression for the value property. If so, return the result of evaluating the property, otherwise return null.

void setValue(Object value)

Set the value of this UIComponent (if any).

Note my emphasis on "without".

In other words, getLocalValue() and setValue() form a true getter/setter pair, basically referring component's own instance variable, not the bean property behind any expression specified in component's value attribute such as value="#{bean.value}".

The getValue() method is implemented in such way that it auto-evaluates any associated ValueExpression when validation hasn't failed (yet) and the local value is null. This is undesireable when the (converted) submitted value is actually null and the component is still busy processing the validations phase and the model values haven't been updated yet.

Simply put, if getValue() were used instead of getLocalValue(), then the case "user removed (non-required) input value" would fail as getValue() returns the initial model value.


Furthermore, in which case Object previous = getValue(); will be not null?

When there's an initial value in the model.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • You mentioned here http://stackoverflow.com/questions/6642242/how-can-i-populate-a-text-field-using-primefaces-ajax-after-validation-errors-oc that [When JSF validation fails for a particular input component during the validations phase, then the submitted value is kept in the input component.]i.e the local value wasn't set(i.e setValue(...)in validatemethod is not c/d). Whereas, as above for getValue(), its written that If validation failed, as indicated by FC.isValidationFailed()returning true, always return the local value. If the validation failed, whythen return the local value. – Farhan stands with Palestine Apr 28 '16 at 05:35
  • When validations phase has failed due to a conversion or validation error anywhere, components which successfully passed validation will return local value and components which failed validation will return submitted value. – BalusC Apr 28 '16 at 06:00
  • But the javadoc for getValue() is confusing me.If validation failed[THIS WILL BE FOR A PARTICULAR COMPONENT], as indicated by FacesContext.isValidationFailed() returning true, always return the local value. They haven't said return the SUBMITTED VALUE. – Farhan stands with Palestine Apr 28 '16 at 06:50
  • The submitted value is accessed via `getSubmittedValue()`. Do note that this happens during render response phase only. – BalusC Apr 28 '16 at 07:03
  • The validate method is c/d in PROCESS VALIDATIONS PHASE. the submitted value is getting accessed here- Object submittedValue = getSubmittedValue(); To explain you further, I have raised this-http://stackoverflow.com/questions/36907050/uiinputgetvalue-and-getlocalvalue-after-validation-succeeds-return-differen – Farhan stands with Palestine Apr 28 '16 at 07:07
  • The link in your first comment describes the logic "first submitted value, then local value, then model value" in relationship to logic during generating HTML output, not to logic of `getValue()` method. – BalusC Apr 28 '16 at 07:12