问题
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?
回答1:
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