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:
- During the APPLY_REQUEST_VALUES phase,
- the input value is set to a submittedValue property of the UI component (e.g. inputComponent.setSubmittedValue("test")).
- 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.
- 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?
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().
来源:https://stackoverflow.com/questions/15691126/when-are-setvalue-and-setsubmittedvalue-called-on-uicomponent