Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When are setValue and setSubmittedValue called on UIComponent?

If I correctly combined the information contained in BalusC's great 2006 post http://balusc.blogspot.ch/2006/09/debug-jsf-lifecycle.html with Optimus Prime's even earlier post http://cagataycivici.wordpress.com/2005/12/28/jsf_component_s_value_local/ I get the following:

My understanding:

  1. During the APPLY_REQUEST_VALUES phase,
    • the input value is set to a submittedValue property of the UI component (e.g. inputComponent.setSubmittedValue("test")).
  2. During the PROCESS_VALIDATIONS phase,
    • the same values are read from the submittedValue property (presumably inputComponent.getSubmittedValue()) and used for conversion, if necessary.
    • If the conversion was successful or skipped, the result is set to a value property of the component (e.g. inputComponent.setValue("test")).
    • Also, the submittedValue is erased again immediately (e.g. inputComponent.setSubmittedValue(null))
    • the (converted) value is read from the value property of the UI component (presumably inputComponent.getValue()) and validated.
    • after validation, the backing bean/model's stored value is read (e.g. myBean.getInputValue()) and compared with the newly converted and validated value. If different, the valueChangeListener method(s) will be called.
  3. During the UPDATE_MODEL_VALUES phase,
    • the newly converted and validated value is finally stored in the backing bean's property field (e.g. myBean.setInputValue("test")).

Questions:

  • Is this correct?
  • Is there something missing for a full understanding of what goes on between the POST and the saving of the input value in the backing bean?
  • With immediate="true" on the Input Component, are we merely shifting these events to the APPLY_REQUEST_VALUES phase or do we change more than just the timing/order of events?
like image 508
Chris Avatar asked Oct 04 '22 14:10

Chris


1 Answers

Almost correct. The component's local value is only set when conversion and validation is successful. After that, the submitted value is set to null. You can find the entire process of the validations phase in a rather self-documenting way in the UIInput#validate() method (line numbers are conform JSF 2.1 API):

934    public void validate(FacesContext context) {
935 
936         if (context == null) {
937             throw new NullPointerException();
938         }
939 
940         // Submitted value == null means "the component was not submitted
941         // at all".  
942         Object submittedValue = getSubmittedValue();
943         if (submittedValue == null) {
944             return;
945         }
946 
947         // If non-null, an instanceof String, and we're configured to treat
948         // zero-length Strings as null:
949         //   call setSubmittedValue(null)
950         if ((considerEmptyStringNull(context)
951              && submittedValue instanceof String 
952              && ((String) submittedValue).length() == 0)) {
953             setSubmittedValue(null);
954             submittedValue = null;
955         }
956 
957         Object newValue = null;
958 
959         try {
960             newValue = getConvertedValue(context, submittedValue);
961         }
962         catch (ConverterException ce) {
963             addConversionErrorMessage(context, ce);
964             setValid(false);
965         }
966 
967         validateValue(context, newValue);
968 
969         // If our value is valid, store the new value, erase the
970         // "submitted" value, and emit a ValueChangeEvent if appropriate
971         if (isValid()) {
972             Object previous = getValue();
973             setValue(newValue);
974             setSubmittedValue(null);
975             if (compareValues(previous, newValue)) {
976                 queueEvent(new ValueChangeEvent(this, previous, newValue));
977             }
978         }
979 
980     }

As to the immediate attribute on the UIInput component, yes this merely shifts the validation to the apply request values phase. See also the source code of UIInput#processDecodes() and UIInput#processValidators(), there's a check on UIInput#isImmediate().

like image 151
BalusC Avatar answered Oct 10 '22 16:10

BalusC